blob: 8ace30ed4186fcf302cd00417f56714532e7f205 [file] [log] [blame]
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04001#define ASC_VERSION "3.4" /* AdvanSys Driver Version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3/*
4 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
5 *
6 * Copyright (c) 1995-2000 Advanced System Products, Inc.
7 * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04008 * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * All Rights Reserved.
10 *
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
19 * changed its name to ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040020 * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 */
22
23/*
24
25 Documentation for the AdvanSys Driver
26
27 A. Linux Kernels Supported by this Driver
28 B. Adapters Supported by this Driver
29 C. Linux source files modified by AdvanSys Driver
30 D. Source Comments
31 E. Driver Compile Time Options and Debugging
32 F. Driver LILO Option
33 G. Tests to run before releasing new driver
34 H. Release History
35 I. Known Problems/Fix List
36 J. Credits (Chronological Order)
37
38 A. Linux Kernels Supported by this Driver
39
40 This driver has been tested in the following Linux kernels: v2.2.18
41 v2.4.0. The driver is supported on v2.2 and v2.4 kernels and on x86,
42 alpha, and PowerPC platforms.
43
44 B. Adapters Supported by this Driver
45
46 AdvanSys (Advanced System Products, Inc.) manufactures the following
47 RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
48 (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
49 buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
50 transfer) SCSI Host Adapters for the PCI bus.
51
52 The CDB counts below indicate the number of SCSI CDB (Command
53 Descriptor Block) requests that can be stored in the RISC chip
54 cache and board LRAM. A CDB is a single SCSI command. The driver
55 detect routine will display the number of CDBs available for each
56 adapter detected. The number of CDBs used by the driver can be
57 lowered in the BIOS by changing the 'Host Queue Size' adapter setting.
58
59 Laptop Products:
60 ABP-480 - Bus-Master CardBus (16 CDB) (2.4 kernel and greater)
61
62 Connectivity Products:
63 ABP510/5150 - Bus-Master ISA (240 CDB)
64 ABP5140 - Bus-Master ISA PnP (16 CDB)
65 ABP5142 - Bus-Master ISA PnP with floppy (16 CDB)
66 ABP902/3902 - Bus-Master PCI (16 CDB)
67 ABP3905 - Bus-Master PCI (16 CDB)
68 ABP915 - Bus-Master PCI (16 CDB)
69 ABP920 - Bus-Master PCI (16 CDB)
70 ABP3922 - Bus-Master PCI (16 CDB)
71 ABP3925 - Bus-Master PCI (16 CDB)
72 ABP930 - Bus-Master PCI (16 CDB)
73 ABP930U - Bus-Master PCI Ultra (16 CDB)
74 ABP930UA - Bus-Master PCI Ultra (16 CDB)
75 ABP960 - Bus-Master PCI MAC/PC (16 CDB)
76 ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
77
78 Single Channel Products:
79 ABP542 - Bus-Master ISA with floppy (240 CDB)
80 ABP742 - Bus-Master EISA (240 CDB)
81 ABP842 - Bus-Master VL (240 CDB)
82 ABP940 - Bus-Master PCI (240 CDB)
83 ABP940U - Bus-Master PCI Ultra (240 CDB)
84 ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB)
85 ABP970 - Bus-Master PCI MAC/PC (240 CDB)
86 ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
87 ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB)
88 ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB)
89 ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB)
90 ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB)
91
92 Multi-Channel Products:
93 ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
94 ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
95 ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
96 ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel)
97 ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
98 ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
99 ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.)
100 ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB)
101 ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB)
102
103 C. Linux source files modified by AdvanSys Driver
104
105 This section for historical purposes documents the changes
106 originally made to the Linux kernel source to add the advansys
107 driver. As Linux has changed some of these files have also
108 been modified.
109
110 1. linux/arch/i386/config.in:
111
112 bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
113
114 2. linux/drivers/scsi/hosts.c:
115
116 #ifdef CONFIG_SCSI_ADVANSYS
117 #include "advansys.h"
118 #endif
119
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100120 and after "static struct scsi_host_template builtin_scsi_hosts[] =":
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122 #ifdef CONFIG_SCSI_ADVANSYS
123 ADVANSYS,
124 #endif
125
126 3. linux/drivers/scsi/Makefile:
127
128 ifdef CONFIG_SCSI_ADVANSYS
129 SCSI_SRCS := $(SCSI_SRCS) advansys.c
130 SCSI_OBJS := $(SCSI_OBJS) advansys.o
131 else
132 SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
133 endif
134
135 4. linux/init/main.c:
136
137 extern void advansys_setup(char *str, int *ints);
138
139 and add the following lines to the bootsetups[] array.
140
141 #ifdef CONFIG_SCSI_ADVANSYS
142 { "advansys=", advansys_setup },
143 #endif
144
145 D. Source Comments
146
147 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
148
149 2. This driver should be maintained in multiple files. But to make
150 it easier to include with Linux and to follow Linux conventions,
151 the whole driver is maintained in the source files advansys.h and
152 advansys.c. In this file logical sections of the driver begin with
153 a comment that contains '---'. The following are the logical sections
154 of the driver below.
155
156 --- Linux Version
157 --- Linux Include File
158 --- Driver Options
159 --- Debugging Header
160 --- Asc Library Constants and Macros
161 --- Adv Library Constants and Macros
162 --- Driver Constants and Macros
163 --- Driver Structures
164 --- Driver Data
165 --- Driver Function Prototypes
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100166 --- Linux 'struct scsi_host_template' and advansys_setup() Functions
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 --- Loadable Driver Support
168 --- Miscellaneous Driver Functions
169 --- Functions Required by the Asc Library
170 --- Functions Required by the Adv Library
171 --- Tracing and Debugging Functions
172 --- Asc Library Functions
173 --- Adv Library Functions
174
175 3. The string 'XXX' is used to flag code that needs to be re-written
176 or that contains a problem that needs to be addressed.
177
178 4. I have stripped comments from and reformatted the source for the
179 Asc Library and Adv Library to reduce the size of this file. This
180 source can be found under the following headings. The Asc Library
181 is used to support Narrow Boards. The Adv Library is used to
182 support Wide Boards.
183
184 --- Asc Library Constants and Macros
185 --- Adv Library Constants and Macros
186 --- Asc Library Functions
187 --- Adv Library Functions
188
189 E. Driver Compile Time Options and Debugging
190
191 In this source file the following constants can be defined. They are
192 defined in the source below. Both of these options are enabled by
193 default.
194
195 1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled)
196
197 Enabling this option adds assertion logic statements to the
198 driver. If an assertion fails a message will be displayed to
199 the console, but the system will continue to operate. Any
200 assertions encountered should be reported to the person
201 responsible for the driver. Assertion statements may proactively
202 detect problems with the driver and facilitate fixing these
203 problems. Enabling assertions will add a small overhead to the
204 execution of the driver.
205
206 2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled)
207
208 Enabling this option adds tracing functions to the driver and
209 the ability to set a driver tracing level at boot time. This
210 option will also export symbols not required outside the driver to
211 the kernel name space. This option is very useful for debugging
212 the driver, but it will add to the size of the driver execution
213 image and add overhead to the execution of the driver.
214
215 The amount of debugging output can be controlled with the global
216 variable 'asc_dbglvl'. The higher the number the more output. By
217 default the debug level is 0.
218
219 If the driver is loaded at boot time and the LILO Driver Option
220 is included in the system, the debug level can be changed by
221 specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The
222 first three hex digits of the pseudo I/O Port must be set to
223 'deb' and the fourth hex digit specifies the debug level: 0 - F.
224 The following command line will look for an adapter at 0x330
225 and set the debug level to 2.
226
227 linux advansys=0x330,0,0,0,0xdeb2
228
229 If the driver is built as a loadable module this variable can be
230 defined when the driver is loaded. The following insmod command
231 will set the debug level to one.
232
233 insmod advansys.o asc_dbglvl=1
234
235 Debugging Message Levels:
236 0: Errors Only
237 1: High-Level Tracing
238 2-N: Verbose Tracing
239
240 To enable debug output to console, please make sure that:
241
242 a. System and kernel logging is enabled (syslogd, klogd running).
243 b. Kernel messages are routed to console output. Check
244 /etc/syslog.conf for an entry similar to this:
245
246 kern.* /dev/console
247
248 c. klogd is started with the appropriate -c parameter
249 (e.g. klogd -c 8)
250
251 This will cause printk() messages to be be displayed on the
252 current console. Refer to the klogd(8) and syslogd(8) man pages
253 for details.
254
255 Alternatively you can enable printk() to console with this
256 program. However, this is not the 'official' way to do this.
257 Debug output is logged in /var/log/messages.
258
259 main()
260 {
261 syscall(103, 7, 0, 0);
262 }
263
264 Increasing LOG_BUF_LEN in kernel/printk.c to something like
265 40960 allows more debug messages to be buffered in the kernel
266 and written to the console or log file.
267
268 3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0)
269
270 Enabling this option adds statistics collection and display
271 through /proc to the driver. The information is useful for
272 monitoring driver and device performance. It will add to the
273 size of the driver execution image and add minor overhead to
274 the execution of the driver.
275
276 Statistics are maintained on a per adapter basis. Driver entry
277 point call counts and transfer size counts are maintained.
278 Statistics are only available for kernels greater than or equal
279 to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured.
280
281 AdvanSys SCSI adapter files have the following path name format:
282
283 /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
284
285 This information can be displayed with cat. For example:
286
287 cat /proc/scsi/advansys/0
288
289 When ADVANSYS_STATS is not defined the AdvanSys /proc files only
290 contain adapter and device configuration information.
291
292 F. Driver LILO Option
293
294 If init/main.c is modified as described in the 'Directions for Adding
295 the AdvanSys Driver to Linux' section (B.4.) above, the driver will
296 recognize the 'advansys' LILO command line and /etc/lilo.conf option.
297 This option can be used to either disable I/O port scanning or to limit
298 scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
299 PCI boards will still be searched for and detected. This option only
300 affects searching for ISA and VL boards.
301
302 Examples:
303 1. Eliminate I/O port scanning:
304 boot: linux advansys=
305 or
306 boot: linux advansys=0x0
307 2. Limit I/O port scanning to one I/O port:
308 boot: linux advansys=0x110
309 3. Limit I/O port scanning to four I/O ports:
310 boot: linux advansys=0x110,0x210,0x230,0x330
311
312 For a loadable module the same effect can be achieved by setting
313 the 'asc_iopflag' variable and 'asc_ioport' array when loading
314 the driver, e.g.
315
316 insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
317
318 If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1)
319 I/O Port may be added to specify the driver debug level. Refer to
320 the 'Driver Compile Time Options and Debugging' section above for
321 more information.
322
323 G. Tests to run before releasing new driver
324
325 1. In the supported kernels verify there are no warning or compile
326 errors when the kernel is built as both a driver and as a module
327 and with the following options:
328
329 ADVANSYS_DEBUG - enabled and disabled
330 CONFIG_SMP - enabled and disabled
331 CONFIG_PROC_FS - enabled and disabled
332
333 2. Run tests on an x86, alpha, and PowerPC with at least one narrow
334 card and one wide card attached to a hard disk and CD-ROM drive:
335 fdisk, mkfs, fsck, bonnie, copy/compare test from the
336 CD-ROM to the hard drive.
337
338 H. Release History
339
340 BETA-1.0 (12/23/95):
341 First Release
342
343 BETA-1.1 (12/28/95):
344 1. Prevent advansys_detect() from being called twice.
345 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
346
347 1.2 (1/12/96):
348 1. Prevent re-entrancy in the interrupt handler which
349 resulted in the driver hanging Linux.
350 2. Fix problem that prevented ABP-940 cards from being
351 recognized on some PCI motherboards.
352 3. Add support for the ABP-5140 PnP ISA card.
353 4. Fix check condition return status.
354 5. Add conditionally compiled code for Linux v1.3.X.
355
356 1.3 (2/23/96):
357 1. Fix problem in advansys_biosparam() that resulted in the
358 wrong drive geometry being returned for drives > 1GB with
359 extended translation enabled.
360 2. Add additional tracing during device initialization.
361 3. Change code that only applies to ISA PnP adapter.
362 4. Eliminate 'make dep' warning.
363 5. Try to fix problem with handling resets by increasing their
364 timeout value.
365
366 1.4 (5/8/96):
367 1. Change definitions to eliminate conflicts with other subsystems.
368 2. Add versioning code for the shared interrupt changes.
369 3. Eliminate problem in asc_rmqueue() with iterating after removing
370 a request.
371 4. Remove reset request loop problem from the "Known Problems or
372 Issues" section. This problem was isolated and fixed in the
373 mid-level SCSI driver.
374
375 1.5 (8/8/96):
376 1. Add support for ABP-940U (PCI Ultra) adapter.
Thomas Gleixner1d6f3592006-07-01 19:29:42 -0700377 2. Add support for IRQ sharing by setting the IRQF_SHARED flag for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 request_irq and supplying a dev_id pointer to both request_irq()
379 and free_irq().
380 3. In AscSearchIOPortAddr11() restore a call to check_region() which
381 should be used before I/O port probing.
382 4. Fix bug in asc_prt_hex() which resulted in the displaying
383 the wrong data.
384 5. Incorporate miscellaneous Asc Library bug fixes and new microcode.
385 6. Change driver versioning to be specific to each Linux sub-level.
386 7. Change statistics gathering to be per adapter instead of global
387 to the driver.
388 8. Add more information and statistics to the adapter /proc file:
389 /proc/scsi/advansys[0...].
390 9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list.
391 This problem has been addressed with the SCSI mid-level changes
392 made in v1.3.89. The advansys_select_queue_depths() function
393 was added for the v1.3.89 changes.
394
395 1.6 (9/10/96):
396 1. Incorporate miscellaneous Asc Library bug fixes and new microcode.
397
398 1.7 (9/25/96):
399 1. Enable clustering and optimize the setting of the maximum number
400 of scatter gather elements for any particular board. Clustering
401 increases CPU utilization, but results in a relatively larger
402 increase in I/O throughput.
403 2. Improve the performance of the request queuing functions by
404 adding a last pointer to the queue structure.
405 3. Correct problems with reset and abort request handling that
406 could have hung or crashed Linux.
407 4. Add more information to the adapter /proc file:
408 /proc/scsi/advansys[0...].
409 5. Remove the request timeout issue form the driver issues list.
410 6. Miscellaneous documentation additions and changes.
411
412 1.8 (10/4/96):
413 1. Make changes to handle the new v2.1.0 kernel memory mapping
414 in which a kernel virtual address may not be equivalent to its
415 bus or DMA memory address.
416 2. Change abort and reset request handling to make it yet even
417 more robust.
418 3. Try to mitigate request starvation by sending ordered requests
419 to heavily loaded, tag queuing enabled devices.
420 4. Maintain statistics on request response time.
421 5. Add request response time statistics and other information to
422 the adapter /proc file: /proc/scsi/advansys[0...].
423
424 1.9 (10/21/96):
425 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
426 make use of mid-level SCSI driver device queue depth flow
427 control mechanism. This will eliminate aborts caused by a
428 device being unable to keep up with requests and eliminate
429 repeat busy or QUEUE FULL status returned by a device.
430 2. Incorporate miscellaneous Asc Library bug fixes.
431 3. To allow the driver to work in kernels with broken module
432 support set 'cmd_per_lun' if the driver is compiled as a
433 module. This change affects kernels v1.3.89 to present.
434 4. Remove PCI BIOS address from the driver banner. The PCI BIOS
435 is relocated by the motherboard BIOS and its new address can
436 not be determined by the driver.
437 5. Add mid-level SCSI queue depth information to the adapter
438 /proc file: /proc/scsi/advansys[0...].
439
440 2.0 (11/14/96):
441 1. Change allocation of global structures used for device
442 initialization to guarantee they are in DMA-able memory.
443 Previously when the driver was loaded as a module these
444 structures might not have been in DMA-able memory, causing
445 device initialization to fail.
446
447 2.1 (12/30/96):
448 1. In advansys_reset(), if the request is a synchronous reset
449 request, even if the request serial number has changed, then
450 complete the request.
451 2. Add Asc Library bug fixes including new microcode.
452 3. Clear inquiry buffer before using it.
453 4. Correct ifdef typo.
454
455 2.2 (1/15/97):
456 1. Add Asc Library bug fixes including new microcode.
457 2. Add synchronous data transfer rate information to the
458 adapter /proc file: /proc/scsi/advansys[0...].
459 3. Change ADVANSYS_DEBUG to be disabled by default. This
460 will reduce the size of the driver image, eliminate execution
461 overhead, and remove unneeded symbols from the kernel symbol
462 space that were previously added by the driver.
463 4. Add new compile-time option ADVANSYS_ASSERT for assertion
464 code that used to be defined within ADVANSYS_DEBUG. This
465 option is enabled by default.
466
467 2.8 (5/26/97):
468 1. Change version number to 2.8 to synchronize the Linux driver
469 version numbering with other AdvanSys drivers.
470 2. Reformat source files without tabs to present the same view
471 of the file to everyone regardless of the editor tab setting
472 being used.
473 3. Add Asc Library bug fixes.
474
475 3.1A (1/8/98):
476 1. Change version number to 3.1 to indicate that support for
477 Ultra-Wide adapters (ABP-940UW) is included in this release.
478 2. Add Asc Library (Narrow Board) bug fixes.
479 3. Report an underrun condition with the host status byte set
480 to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which
481 causes the underrun condition to be ignored. When Linux defines
482 its own DID_UNDERRUN the constant defined in this file can be
483 removed.
484 4. Add patch to AscWaitTixISRDone().
485 5. Add support for up to 16 different AdvanSys host adapter SCSI
486 channels in one system. This allows four cards with four channels
487 to be used in one system.
488
489 3.1B (1/9/98):
490 1. Handle that PCI register base addresses are not always page
491 aligned even though ioremap() requires that the address argument
492 be page aligned.
493
494 3.1C (1/10/98):
495 1. Update latest BIOS version checked for from the /proc file.
496 2. Don't set microcode SDTR variable at initialization. Instead
497 wait until device capabilities have been detected from an Inquiry
498 command.
499
500 3.1D (1/21/98):
501 1. Improve performance when the driver is compiled as module by
502 allowing up to 64 scatter-gather elements instead of 8.
503
504 3.1E (5/1/98):
505 1. Set time delay in AscWaitTixISRDone() to 1000 ms.
506 2. Include SMP locking changes.
507 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS
508 access functions.
509 4. Update board serial number printing.
Thomas Gleixner1d6f3592006-07-01 19:29:42 -0700510 5. Try allocating an IRQ both with and without the IRQF_DISABLED
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 flag set to allow IRQ sharing with drivers that do not set
Thomas Gleixner1d6f3592006-07-01 19:29:42 -0700512 the IRQF_DISABLED flag. Also display a more descriptive error
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 message if request_irq() fails.
514 6. Update to latest Asc and Adv Libraries.
515
516 3.2A (7/22/99):
517 1. Update Adv Library to 4.16 which includes support for
518 the ASC38C0800 (Ultra2/LVD) IC.
519
520 3.2B (8/23/99):
521 1. Correct PCI compile time option for v2.1.93 and greater
522 kernels, advansys_info() string, and debug compile time
523 option.
524 2. Correct DvcSleepMilliSecond() for v2.1.0 and greater
525 kernels. This caused an LVD detection/BIST problem problem
526 among other things.
527 3. Sort PCI cards by PCI Bus, Slot, Function ascending order
528 to be consistent with the BIOS.
529 4. Update to Asc Library S121 and Adv Library 5.2.
530
531 3.2C (8/24/99):
532 1. Correct PCI card detection bug introduced in 3.2B that
533 prevented PCI cards from being detected in kernels older
534 than v2.1.93.
535
536 3.2D (8/26/99):
537 1. Correct /proc device synchronous speed information display.
538 Also when re-negotiation is pending for a target device
539 note this condition with an * and footnote.
540 2. Correct initialization problem with Ultra-Wide cards that
541 have a pre-3.2 BIOS. A microcode variable changed locations
542 in 3.2 and greater BIOSes which caused WDTR to be attempted
543 erroneously with drives that don't support WDTR.
544
545 3.2E (8/30/99):
546 1. Fix compile error caused by v2.3.13 PCI structure change.
547 2. Remove field from ASCEEP_CONFIG that resulted in an EEPROM
548 checksum error for ISA cards.
549 3. Remove ASC_QUEUE_FLOW_CONTROL conditional code. The mid-level
550 SCSI changes that it depended on were never included in Linux.
551
552 3.2F (9/3/99):
553 1. Handle new initial function code added in v2.3.16 for all
554 driver versions.
555
556 3.2G (9/8/99):
557 1. Fix PCI board detection in v2.3.13 and greater kernels.
558 2. Fix comiple errors in v2.3.X with debugging enabled.
559
560 3.2H (9/13/99):
561 1. Add 64-bit address, long support for Alpha and UltraSPARC.
562 The driver has been verified to work on an Alpha system.
563 2. Add partial byte order handling support for Power PC and
564 other big-endian platforms. This support has not yet been
565 completed or verified.
566 3. For wide boards replace block zeroing of request and
567 scatter-gather structures with individual field initialization
568 to improve performance.
569 4. Correct and clarify ROM BIOS version detection.
570
571 3.2I (10/8/99):
572 1. Update to Adv Library 5.4.
573 2. Add v2.3.19 underrun reporting to asc_isr_callback() and
574 adv_isr_callback(). Remove DID_UNDERRUN constant and other
575 no longer needed code that previously documented the lack
576 of underrun handling.
577
578 3.2J (10/14/99):
579 1. Eliminate compile errors for v2.0 and earlier kernels.
580
581 3.2K (11/15/99):
582 1. Correct debug compile error in asc_prt_adv_scsi_req_q().
583 2. Update Adv Library to 5.5.
584 3. Add ifdef handling for /proc changes added in v2.3.28.
585 4. Increase Wide board scatter-gather list maximum length to
586 255 when the driver is compiled into the kernel.
587
588 3.2L (11/18/99):
589 1. Fix bug in adv_get_sglist() that caused an assertion failure
590 at line 7475. The reqp->sgblkp pointer must be initialized
591 to NULL in adv_get_sglist().
592
593 3.2M (11/29/99):
594 1. Really fix bug in adv_get_sglist().
595 2. Incorporate v2.3.29 changes into driver.
596
597 3.2N (4/1/00):
598 1. Add CONFIG_ISA ifdef code.
599 2. Include advansys_interrupts_enabled name change patch.
600 3. For >= v2.3.28 use new SCSI error handling with new function
601 advansys_eh_bus_reset(). Don't include an abort function
602 because of base library limitations.
603 4. For >= v2.3.28 use per board lock instead of io_request_lock.
604 5. For >= v2.3.28 eliminate advansys_command() and
605 advansys_command_done().
606 6. Add some changes for PowerPC (Big Endian) support, but it isn't
607 working yet.
608 7. Fix "nonexistent resource free" problem that occurred on a module
609 unload for boards with an I/O space >= 255. The 'n_io_port' field
610 is only one byte and can not be used to hold an ioport length more
611 than 255.
612
613 3.3A (4/4/00):
614 1. Update to Adv Library 5.8.
615 2. For wide cards add support for CDBs up to 16 bytes.
616 3. Eliminate warnings when CONFIG_PROC_FS is not defined.
617
618 3.3B (5/1/00):
619 1. Support for PowerPC (Big Endian) wide cards. Narrow cards
620 still need work.
621 2. Change bitfields to shift and mask access for endian
622 portability.
623
624 3.3C (10/13/00):
625 1. Update for latest 2.4 kernel.
626 2. Test ABP-480 CardBus support in 2.4 kernel - works!
627 3. Update to Asc Library S123.
628 4. Update to Adv Library 5.12.
629
630 3.3D (11/22/00):
631 1. Update for latest 2.4 kernel.
632 2. Create patches for 2.2 and 2.4 kernels.
633
634 3.3E (1/9/01):
635 1. Now that 2.4 is released remove ifdef code for kernel versions
636 less than 2.2. The driver is now only supported in kernels 2.2,
637 2.4, and greater.
638 2. Add code to release and acquire the io_request_lock in
639 the driver entrypoint functions: advansys_detect and
640 advansys_queuecommand. In kernel 2.4 the SCSI mid-level driver
641 still holds the io_request_lock on entry to SCSI low-level drivers.
642 This was supposed to be removed before 2.4 was released but never
643 happened. When the mid-level SCSI driver is changed all references
644 to the io_request_lock should be removed from the driver.
645 3. Simplify error handling by removing advansys_abort(),
646 AscAbortSRB(), AscResetDevice(). SCSI bus reset requests are
647 now handled by resetting the SCSI bus and fully re-initializing
648 the chip. This simple method of error recovery has proven to work
649 most reliably after attempts at different methods. Also now only
650 support the "new" error handling method and remove the obsolete
651 error handling interface.
652 4. Fix debug build errors.
653
654 3.3F (1/24/01):
655 1. Merge with ConnectCom version from Andy Kellner which
656 updates Adv Library to 5.14.
657 2. Make PowerPC (Big Endian) work for narrow cards and
658 fix problems writing EEPROM for wide cards.
659 3. Remove interrupts_enabled assertion function.
660
661 3.3G (2/16/01):
662 1. Return an error from narrow boards if passed a 16 byte
663 CDB. The wide board can already handle 16 byte CDBs.
664
665 3.3GJ (4/15/02):
666 1. hacks for lk 2.5 series (D. Gilbert)
667
668 3.3GJD (10/14/02):
669 1. change select_queue_depths to slave_configure
670 2. make cmd_per_lun be sane again
671
672 3.3K [2004/06/24]:
673 1. continuing cleanup for lk 2.6 series
674 2. Fix problem in lk 2.6.7-bk2 that broke PCI wide cards
675 3. Fix problem that oopsed ISA cards
676
677 I. Known Problems/Fix List (XXX)
678
679 1. Need to add memory mapping workaround. Test the memory mapping.
680 If it doesn't work revert to I/O port access. Can a test be done
681 safely?
682 2. Handle an interrupt not working. Keep an interrupt counter in
683 the interrupt handler. In the timeout function if the interrupt
684 has not occurred then print a message and run in polled mode.
685 3. Allow bus type scanning order to be changed.
686 4. Need to add support for target mode commands, cf. CAM XPT.
687
688 J. Credits (Chronological Order)
689
690 Bob Frey <bfrey@turbolinux.com.cn> wrote the AdvanSys SCSI driver
691 and maintained it up to 3.3F. He continues to answer questions
692 and help maintain the driver.
693
694 Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
695 basis for the Linux v1.3.X changes which were included in the
696 1.2 release.
697
698 Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug
699 in advansys_biosparam() which was fixed in the 1.3 release.
700
701 Erik Ratcliffe <erik@caldera.com> has done testing of the
702 AdvanSys driver in the Caldera releases.
703
704 Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
705 AscWaitTixISRDone() which he found necessary to make the
706 driver work with a SCSI-1 disk.
707
708 Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide
709 support in the 3.1A driver.
710
711 Doug Gilbert <dgilbert@interlog.com> has made changes and
712 suggestions to improve the driver and done a lot of testing.
713
714 Ken Mort <ken@mort.net> reported a DEBUG compile bug fixed
715 in 3.2K.
716
717 Tom Rini <trini@kernel.crashing.org> provided the CONFIG_ISA
718 patch and helped with PowerPC wide and narrow board support.
719
720 Philip Blundell <philb@gnu.org> provided an
721 advansys_interrupts_enabled patch.
722
723 Dave Jones <dave@denial.force9.co.uk> reported the compiler
724 warnings generated when CONFIG_PROC_FS was not defined in
725 the 3.2M driver.
726
727 Jerry Quinn <jlquinn@us.ibm.com> fixed PowerPC support (endian
728 problems) for wide cards.
729
730 Bryan Henderson <bryanh@giraffe-data.com> helped debug narrow
731 card error handling.
732
733 Manuel Veloso <veloso@pobox.com> worked hard on PowerPC narrow
734 board support and fixed a bug in AscGetEEPConfig().
735
736 Arnaldo Carvalho de Melo <acme@conectiva.com.br> made
737 save_flags/restore_flags changes.
738
739 Andy Kellner <AKellner@connectcom.net> continues the Advansys SCSI
740 driver development for ConnectCom (Version > 3.3F).
741
742 K. ConnectCom (AdvanSys) Contact Information
743
744 Mail: ConnectCom Solutions, Inc.
745 1150 Ringwood Court
746 San Jose, CA 95131
747 Operator/Sales: 1-408-383-9400
748 FAX: 1-408-383-9612
749 Tech Support: 1-408-467-2930
750 Tech Support E-Mail: linux@connectcom.net
751 FTP Site: ftp.connectcom.net (login: anonymous)
752 Web Site: http://www.connectcom.net
753
754*/
755
756/*
757 * --- Linux Include Files
758 */
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761#include <linux/string.h>
762#include <linux/kernel.h>
763#include <linux/types.h>
764#include <linux/ioport.h>
765#include <linux/interrupt.h>
766#include <linux/delay.h>
767#include <linux/slab.h>
768#include <linux/mm.h>
769#include <linux/proc_fs.h>
770#include <linux/init.h>
771#include <linux/blkdev.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -0400772#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773#include <linux/spinlock.h>
774#include <linux/dma-mapping.h>
775
776#include <asm/io.h>
777#include <asm/system.h>
778#include <asm/dma.h>
779
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -0400780#include <scsi/scsi_cmnd.h>
781#include <scsi/scsi_device.h>
782#include <scsi/scsi_tcq.h>
783#include <scsi/scsi.h>
784#include <scsi/scsi_host.h>
785
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786/* FIXME: (by jejb@steeleye.com) This warning is present for two
787 * reasons:
788 *
789 * 1) This driver badly needs converting to the correct driver model
790 * probing API
791 *
792 * 2) Although all of the necessary command mapping places have the
793 * appropriate dma_map.. APIs, the driver still processes its internal
794 * queue using bus_to_virt() and virt_to_bus() which are illegal under
795 * the API. The entire queue processing structure will need to be
796 * altered to fix this.
797 */
798#warning this driver is still not properly converted to the DMA API
799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800/*
801 * --- Driver Options
802 */
803
804/* Enable driver assertions. */
805#define ADVANSYS_ASSERT
806
807/* Enable driver /proc statistics. */
808#define ADVANSYS_STATS
809
810/* Enable driver tracing. */
811/* #define ADVANSYS_DEBUG */
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813/*
814 * --- Asc Library Constants and Macros
815 */
816
817#define ASC_LIB_VERSION_MAJOR 1
818#define ASC_LIB_VERSION_MINOR 24
819#define ASC_LIB_SERIAL_NUMBER 123
820
821/*
822 * Portable Data Types
823 *
824 * Any instance where a 32-bit long or pointer type is assumed
825 * for precision or HW defined structures, the following define
826 * types must be used. In Linux the char, short, and int types
827 * are all consistent at 8, 16, and 32 bits respectively. Pointers
828 * and long types are 64 bits on Alpha and UltraSPARC.
829 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400830#define ASC_PADDR __u32 /* Physical/Bus address data type. */
831#define ASC_VADDR __u32 /* Virtual address data type. */
832#define ASC_DCNT __u32 /* Unsigned Data count type. */
833#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835/*
836 * These macros are used to convert a virtual address to a
837 * 32-bit value. This currently can be used on Linux Alpha
838 * which uses 64-bit virtual address but a 32-bit bus address.
839 * This is likely to break in the future, but doing this now
840 * will give us time to change the HW and FW to handle 64-bit
841 * addresses.
842 */
843#define ASC_VADDR_TO_U32 virt_to_bus
844#define ASC_U32_TO_VADDR bus_to_virt
845
846typedef unsigned char uchar;
847
848#ifndef TRUE
849#define TRUE (1)
850#endif
851#ifndef FALSE
852#define FALSE (0)
853#endif
854
855#define EOF (-1)
856#define ERR (-1)
857#define UW_ERR (uint)(0xFFFF)
858#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
859#define AscPCIConfigVendorIDRegister 0x0000
860#define AscPCIConfigDeviceIDRegister 0x0002
861#define AscPCIConfigCommandRegister 0x0004
862#define AscPCIConfigStatusRegister 0x0006
863#define AscPCIConfigRevisionIDRegister 0x0008
864#define AscPCIConfigCacheSize 0x000C
865#define AscPCIConfigLatencyTimer 0x000D
866#define AscPCIIOBaseRegister 0x0010
867#define AscPCICmdRegBits_IOMemBusMaster 0x0007
868#define ASC_PCI_ID2BUS(id) ((id) & 0xFF)
869#define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F)
870#define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7)
871#define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872#define ASC_PCI_REVISION_3150 0x02
873#define ASC_PCI_REVISION_3050 0x03
874
875#define ASC_DVCLIB_CALL_DONE (1)
876#define ASC_DVCLIB_CALL_FAILED (0)
877#define ASC_DVCLIB_CALL_ERROR (-1)
878
Dave Jones2672ea82006-08-02 17:11:49 -0400879#define PCI_VENDOR_ID_ASP 0x10cd
880#define PCI_DEVICE_ID_ASP_1200A 0x1100
881#define PCI_DEVICE_ID_ASP_ABP940 0x1200
882#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
883#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
884#define PCI_DEVICE_ID_38C0800_REV1 0x2500
885#define PCI_DEVICE_ID_38C1600_REV1 0x2700
886
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887/*
888 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
889 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
890 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
891 * SRB structure.
892 */
893#define CC_VERY_LONG_SG_LIST 0
894#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
895
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400896#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897#define inp(port) inb(port)
898#define outp(port, byte) outb((byte), (port))
899
900#define inpw(port) inw(port)
901#define outpw(port, word) outw((word), (port))
902
903#define ASC_MAX_SG_QUEUE 7
904#define ASC_MAX_SG_LIST 255
905
906#define ASC_CS_TYPE unsigned short
907
908#define ASC_IS_ISA (0x0001)
909#define ASC_IS_ISAPNP (0x0081)
910#define ASC_IS_EISA (0x0002)
911#define ASC_IS_PCI (0x0004)
912#define ASC_IS_PCI_ULTRA (0x0104)
913#define ASC_IS_PCMCIA (0x0008)
914#define ASC_IS_MCA (0x0020)
915#define ASC_IS_VL (0x0040)
916#define ASC_ISA_PNP_PORT_ADDR (0x279)
917#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
918#define ASC_IS_WIDESCSI_16 (0x0100)
919#define ASC_IS_WIDESCSI_32 (0x0200)
920#define ASC_IS_BIG_ENDIAN (0x8000)
921#define ASC_CHIP_MIN_VER_VL (0x01)
922#define ASC_CHIP_MAX_VER_VL (0x07)
923#define ASC_CHIP_MIN_VER_PCI (0x09)
924#define ASC_CHIP_MAX_VER_PCI (0x0F)
925#define ASC_CHIP_VER_PCI_BIT (0x08)
926#define ASC_CHIP_MIN_VER_ISA (0x11)
927#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
928#define ASC_CHIP_MAX_VER_ISA (0x27)
929#define ASC_CHIP_VER_ISA_BIT (0x30)
930#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
931#define ASC_CHIP_VER_ASYN_BUG (0x21)
932#define ASC_CHIP_VER_PCI 0x08
933#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
934#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
935#define ASC_CHIP_MIN_VER_EISA (0x41)
936#define ASC_CHIP_MAX_VER_EISA (0x47)
937#define ASC_CHIP_VER_EISA_BIT (0x40)
938#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
939#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
940#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
941#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
942#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
943#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
944#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
945#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
946#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
947#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
948#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
949
950#define ASC_SCSI_ID_BITS 3
951#define ASC_SCSI_TIX_TYPE uchar
952#define ASC_ALL_DEVICE_BIT_SET 0xFF
953#define ASC_SCSI_BIT_ID_TYPE uchar
954#define ASC_MAX_TID 7
955#define ASC_MAX_LUN 7
956#define ASC_SCSI_WIDTH_BIT_SET 0xFF
957#define ASC_MAX_SENSE_LEN 32
958#define ASC_MIN_SENSE_LEN 14
959#define ASC_MAX_CDB_LEN 12
960#define ASC_SCSI_RESET_HOLD_TIME_US 60
961
962#define ADV_INQ_CLOCKING_ST_ONLY 0x0
963#define ADV_INQ_CLOCKING_DT_ONLY 0x1
964#define ADV_INQ_CLOCKING_ST_AND_DT 0x3
965
966/*
967 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
968 * and CmdDt (Command Support Data) field bit definitions.
969 */
970#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
971#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
972#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
973#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
974
975#define ASC_SCSIDIR_NOCHK 0x00
976#define ASC_SCSIDIR_T2H 0x08
977#define ASC_SCSIDIR_H2T 0x10
978#define ASC_SCSIDIR_NODATA 0x18
979#define SCSI_ASC_NOMEDIA 0x3A
980#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
981#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
982#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
983#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
984#define MS_CMD_DONE 0x00
985#define MS_EXTEND 0x01
986#define MS_SDTR_LEN 0x03
987#define MS_SDTR_CODE 0x01
988#define MS_WDTR_LEN 0x02
989#define MS_WDTR_CODE 0x03
990#define MS_MDP_LEN 0x05
991#define MS_MDP_CODE 0x00
992
993/*
994 * Inquiry data structure and bitfield macros
995 *
996 * Only quantities of more than 1 bit are shifted, since the others are
997 * just tested for true or false. C bitfields aren't portable between big
998 * and little-endian platforms so they are not used.
999 */
1000
1001#define ASC_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f)
1002#define ASC_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5)
1003#define ASC_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f)
1004#define ASC_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80)
1005#define ASC_INQ_ANSI_VER(inq) ((inq)->ver & 0x07)
1006#define ASC_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3)
1007#define ASC_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6)
1008#define ASC_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f)
1009#define ASC_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40)
1010#define ASC_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80)
1011#define ASC_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01)
1012#define ASC_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02)
1013#define ASC_INQ_LINK_CMD(inq) ((inq)->flags & 0x08)
1014#define ASC_INQ_SYNC(inq) ((inq)->flags & 0x10)
1015#define ASC_INQ_WIDE16(inq) ((inq)->flags & 0x20)
1016#define ASC_INQ_WIDE32(inq) ((inq)->flags & 0x40)
1017#define ASC_INQ_REL_ADDR(inq) ((inq)->flags & 0x80)
1018#define ASC_INQ_INFO_UNIT(inq) ((inq)->info & 0x01)
1019#define ASC_INQ_QUICK_ARB(inq) ((inq)->info & 0x02)
1020#define ASC_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2)
1021
1022typedef struct {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001023 uchar periph;
1024 uchar devtype;
1025 uchar ver;
1026 uchar byte3;
1027 uchar add_len;
1028 uchar res1;
1029 uchar res2;
1030 uchar flags;
1031 uchar vendor_id[8];
1032 uchar product_id[16];
1033 uchar product_rev_level[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034} ASC_SCSI_INQUIRY;
1035
1036#define ASC_SG_LIST_PER_Q 7
1037#define QS_FREE 0x00
1038#define QS_READY 0x01
1039#define QS_DISC1 0x02
1040#define QS_DISC2 0x04
1041#define QS_BUSY 0x08
1042#define QS_ABORTED 0x40
1043#define QS_DONE 0x80
1044#define QC_NO_CALLBACK 0x01
1045#define QC_SG_SWAP_QUEUE 0x02
1046#define QC_SG_HEAD 0x04
1047#define QC_DATA_IN 0x08
1048#define QC_DATA_OUT 0x10
1049#define QC_URGENT 0x20
1050#define QC_MSG_OUT 0x40
1051#define QC_REQ_SENSE 0x80
1052#define QCSG_SG_XFER_LIST 0x02
1053#define QCSG_SG_XFER_MORE 0x04
1054#define QCSG_SG_XFER_END 0x08
1055#define QD_IN_PROGRESS 0x00
1056#define QD_NO_ERROR 0x01
1057#define QD_ABORTED_BY_HOST 0x02
1058#define QD_WITH_ERROR 0x04
1059#define QD_INVALID_REQUEST 0x80
1060#define QD_INVALID_HOST_NUM 0x81
1061#define QD_INVALID_DEVICE 0x82
1062#define QD_ERR_INTERNAL 0xFF
1063#define QHSTA_NO_ERROR 0x00
1064#define QHSTA_M_SEL_TIMEOUT 0x11
1065#define QHSTA_M_DATA_OVER_RUN 0x12
1066#define QHSTA_M_DATA_UNDER_RUN 0x12
1067#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
1068#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
1069#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1070#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
1071#define QHSTA_D_HOST_ABORT_FAILED 0x23
1072#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
1073#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1074#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
1075#define QHSTA_M_WTM_TIMEOUT 0x41
1076#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
1077#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
1078#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1079#define QHSTA_M_TARGET_STATUS_BUSY 0x45
1080#define QHSTA_M_BAD_TAG_CODE 0x46
1081#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
1082#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
1083#define QHSTA_D_LRAM_CMP_ERROR 0x81
1084#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1085#define ASC_FLAG_SCSIQ_REQ 0x01
1086#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1087#define ASC_FLAG_BIOS_ASYNC_IO 0x04
1088#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1089#define ASC_FLAG_WIN16 0x10
1090#define ASC_FLAG_WIN32 0x20
1091#define ASC_FLAG_ISA_OVER_16MB 0x40
1092#define ASC_FLAG_DOS_VM_CALLBACK 0x80
1093#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
1094#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
1095#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
1096#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
1097#define ASC_SCSIQ_CPY_BEG 4
1098#define ASC_SCSIQ_SGHD_CPY_BEG 2
1099#define ASC_SCSIQ_B_FWD 0
1100#define ASC_SCSIQ_B_BWD 1
1101#define ASC_SCSIQ_B_STATUS 2
1102#define ASC_SCSIQ_B_QNO 3
1103#define ASC_SCSIQ_B_CNTL 4
1104#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1105#define ASC_SCSIQ_D_DATA_ADDR 8
1106#define ASC_SCSIQ_D_DATA_CNT 12
1107#define ASC_SCSIQ_B_SENSE_LEN 20
1108#define ASC_SCSIQ_DONE_INFO_BEG 22
1109#define ASC_SCSIQ_D_SRBPTR 22
1110#define ASC_SCSIQ_B_TARGET_IX 26
1111#define ASC_SCSIQ_B_CDB_LEN 28
1112#define ASC_SCSIQ_B_TAG_CODE 29
1113#define ASC_SCSIQ_W_VM_ID 30
1114#define ASC_SCSIQ_DONE_STATUS 32
1115#define ASC_SCSIQ_HOST_STATUS 33
1116#define ASC_SCSIQ_SCSI_STATUS 34
1117#define ASC_SCSIQ_CDB_BEG 36
1118#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1119#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1120#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
1121#define ASC_SCSIQ_B_SG_WK_QP 49
1122#define ASC_SCSIQ_B_SG_WK_IX 50
1123#define ASC_SCSIQ_W_ALT_DC1 52
1124#define ASC_SCSIQ_B_LIST_CNT 6
1125#define ASC_SCSIQ_B_CUR_LIST_CNT 7
1126#define ASC_SGQ_B_SG_CNTL 4
1127#define ASC_SGQ_B_SG_HEAD_QP 5
1128#define ASC_SGQ_B_SG_LIST_CNT 6
1129#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1130#define ASC_SGQ_LIST_BEG 8
1131#define ASC_DEF_SCSI1_QNG 4
1132#define ASC_MAX_SCSI1_QNG 4
1133#define ASC_DEF_SCSI2_QNG 16
1134#define ASC_MAX_SCSI2_QNG 32
1135#define ASC_TAG_CODE_MASK 0x23
1136#define ASC_STOP_REQ_RISC_STOP 0x01
1137#define ASC_STOP_ACK_RISC_STOP 0x03
1138#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1139#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1140#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1141#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
1142#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
1143#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
1144#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
1145#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
1146#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
1147#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
1148
1149typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001150 uchar status;
1151 uchar q_no;
1152 uchar cntl;
1153 uchar sg_queue_cnt;
1154 uchar target_id;
1155 uchar target_lun;
1156 ASC_PADDR data_addr;
1157 ASC_DCNT data_cnt;
1158 ASC_PADDR sense_addr;
1159 uchar sense_len;
1160 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161} ASC_SCSIQ_1;
1162
1163typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001164 ASC_VADDR srb_ptr;
1165 uchar target_ix;
1166 uchar flag;
1167 uchar cdb_len;
1168 uchar tag_code;
1169 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170} ASC_SCSIQ_2;
1171
1172typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001173 uchar done_stat;
1174 uchar host_stat;
1175 uchar scsi_stat;
1176 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177} ASC_SCSIQ_3;
1178
1179typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001180 uchar cdb[ASC_MAX_CDB_LEN];
1181 uchar y_first_sg_list_qp;
1182 uchar y_working_sg_qp;
1183 uchar y_working_sg_ix;
1184 uchar y_res;
1185 ushort x_req_count;
1186 ushort x_reconnect_rtn;
1187 ASC_PADDR x_saved_data_addr;
1188 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189} ASC_SCSIQ_4;
1190
1191typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001192 ASC_SCSIQ_2 d2;
1193 ASC_SCSIQ_3 d3;
1194 uchar q_status;
1195 uchar q_no;
1196 uchar cntl;
1197 uchar sense_len;
1198 uchar extra_bytes;
1199 uchar res;
1200 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201} ASC_QDONE_INFO;
1202
1203typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001204 ASC_PADDR addr;
1205 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206} ASC_SG_LIST;
1207
1208typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001209 ushort entry_cnt;
1210 ushort queue_cnt;
1211 ushort entry_to_copy;
1212 ushort res;
1213 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214} ASC_SG_HEAD;
1215
1216#define ASC_MIN_SG_LIST 2
1217
1218typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001219 ushort entry_cnt;
1220 ushort queue_cnt;
1221 ushort entry_to_copy;
1222 ushort res;
1223 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224} ASC_MIN_SG_HEAD;
1225
1226#define QCX_SORT (0x0001)
1227#define QCX_COALEASE (0x0002)
1228
1229typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001230 ASC_SCSIQ_1 q1;
1231 ASC_SCSIQ_2 q2;
1232 uchar *cdbptr;
1233 ASC_SG_HEAD *sg_head;
1234 ushort remain_sg_entry_cnt;
1235 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236} ASC_SCSI_Q;
1237
1238typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001239 ASC_SCSIQ_1 r1;
1240 ASC_SCSIQ_2 r2;
1241 uchar *cdbptr;
1242 ASC_SG_HEAD *sg_head;
1243 uchar *sense_ptr;
1244 ASC_SCSIQ_3 r3;
1245 uchar cdb[ASC_MAX_CDB_LEN];
1246 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247} ASC_SCSI_REQ_Q;
1248
1249typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001250 ASC_SCSIQ_1 r1;
1251 ASC_SCSIQ_2 r2;
1252 uchar *cdbptr;
1253 ASC_SG_HEAD *sg_head;
1254 uchar *sense_ptr;
1255 ASC_SCSIQ_3 r3;
1256 uchar cdb[ASC_MAX_CDB_LEN];
1257 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258} ASC_SCSI_BIOS_REQ_Q;
1259
1260typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001261 uchar fwd;
1262 uchar bwd;
1263 ASC_SCSIQ_1 i1;
1264 ASC_SCSIQ_2 i2;
1265 ASC_SCSIQ_3 i3;
1266 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267} ASC_RISC_Q;
1268
1269typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001270 uchar seq_no;
1271 uchar q_no;
1272 uchar cntl;
1273 uchar sg_head_qp;
1274 uchar sg_list_cnt;
1275 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276} ASC_SG_LIST_Q;
1277
1278typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001279 uchar fwd;
1280 uchar bwd;
1281 ASC_SG_LIST_Q sg;
1282 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283} ASC_RISC_SG_LIST_Q;
1284
1285#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1286#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1287#define ASCQ_ERR_NO_ERROR 0
1288#define ASCQ_ERR_IO_NOT_FOUND 1
1289#define ASCQ_ERR_LOCAL_MEM 2
1290#define ASCQ_ERR_CHKSUM 3
1291#define ASCQ_ERR_START_CHIP 4
1292#define ASCQ_ERR_INT_TARGET_ID 5
1293#define ASCQ_ERR_INT_LOCAL_MEM 6
1294#define ASCQ_ERR_HALT_RISC 7
1295#define ASCQ_ERR_GET_ASPI_ENTRY 8
1296#define ASCQ_ERR_CLOSE_ASPI 9
1297#define ASCQ_ERR_HOST_INQUIRY 0x0A
1298#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1299#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1300#define ASCQ_ERR_Q_STATUS 0x0D
1301#define ASCQ_ERR_WR_SCSIQ 0x0E
1302#define ASCQ_ERR_PC_ADDR 0x0F
1303#define ASCQ_ERR_SYN_OFFSET 0x10
1304#define ASCQ_ERR_SYN_XFER_TIME 0x11
1305#define ASCQ_ERR_LOCK_DMA 0x12
1306#define ASCQ_ERR_UNLOCK_DMA 0x13
1307#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1308#define ASCQ_ERR_MICRO_CODE_HALT 0x15
1309#define ASCQ_ERR_SET_LRAM_ADDR 0x16
1310#define ASCQ_ERR_CUR_QNG 0x17
1311#define ASCQ_ERR_SG_Q_LINKS 0x18
1312#define ASCQ_ERR_SCSIQ_PTR 0x19
1313#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1314#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1315#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1316#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1317#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1318#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1319#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1320#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1321#define ASCQ_ERR_SEND_SCSI_Q 0x22
1322#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1323#define ASCQ_ERR_RESET_SDTR 0x24
1324
1325/*
1326 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
1327 */
1328#define ASC_WARN_NO_ERROR 0x0000
1329#define ASC_WARN_IO_PORT_ROTATE 0x0001
1330#define ASC_WARN_EEPROM_CHKSUM 0x0002
1331#define ASC_WARN_IRQ_MODIFIED 0x0004
1332#define ASC_WARN_AUTO_CONFIG 0x0008
1333#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1334#define ASC_WARN_EEPROM_RECOVER 0x0020
1335#define ASC_WARN_CFG_MSW_RECOVER 0x0040
1336#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
1337
1338/*
1339 * Error code values are set in ASC_DVC_VAR 'err_code'.
1340 */
1341#define ASC_IERR_WRITE_EEPROM 0x0001
1342#define ASC_IERR_MCODE_CHKSUM 0x0002
1343#define ASC_IERR_SET_PC_ADDR 0x0004
1344#define ASC_IERR_START_STOP_CHIP 0x0008
1345#define ASC_IERR_IRQ_NO 0x0010
1346#define ASC_IERR_SET_IRQ_NO 0x0020
1347#define ASC_IERR_CHIP_VERSION 0x0040
1348#define ASC_IERR_SET_SCSI_ID 0x0080
1349#define ASC_IERR_GET_PHY_ADDR 0x0100
1350#define ASC_IERR_BAD_SIGNATURE 0x0200
1351#define ASC_IERR_NO_BUS_TYPE 0x0400
1352#define ASC_IERR_SCAM 0x0800
1353#define ASC_IERR_SET_SDTR 0x1000
1354#define ASC_IERR_RW_LRAM 0x8000
1355
1356#define ASC_DEF_IRQ_NO 10
1357#define ASC_MAX_IRQ_NO 15
1358#define ASC_MIN_IRQ_NO 10
1359#define ASC_MIN_REMAIN_Q (0x02)
1360#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
1361#define ASC_MIN_TAG_Q_PER_DVC (0x04)
1362#define ASC_DEF_TAG_Q_PER_DVC (0x04)
1363#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1364#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
1365#define ASC_MAX_TOTAL_QNG 240
1366#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
1367#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
1368#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1369#define ASC_MAX_INRAM_TAG_QNG 16
1370#define ASC_IOADR_TABLE_MAX_IX 11
1371#define ASC_IOADR_GAP 0x10
1372#define ASC_SEARCH_IOP_GAP 0x10
1373#define ASC_MIN_IOP_ADDR (PortAddr)0x0100
1374#define ASC_MAX_IOP_ADDR (PortAddr)0x3F0
1375#define ASC_IOADR_1 (PortAddr)0x0110
1376#define ASC_IOADR_2 (PortAddr)0x0130
1377#define ASC_IOADR_3 (PortAddr)0x0150
1378#define ASC_IOADR_4 (PortAddr)0x0190
1379#define ASC_IOADR_5 (PortAddr)0x0210
1380#define ASC_IOADR_6 (PortAddr)0x0230
1381#define ASC_IOADR_7 (PortAddr)0x0250
1382#define ASC_IOADR_8 (PortAddr)0x0330
1383#define ASC_IOADR_DEF ASC_IOADR_8
1384#define ASC_LIB_SCSIQ_WK_SP 256
1385#define ASC_MAX_SYN_XFER_NO 16
1386#define ASC_SYN_MAX_OFFSET 0x0F
1387#define ASC_DEF_SDTR_OFFSET 0x0F
1388#define ASC_DEF_SDTR_INDEX 0x00
1389#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
1390#define SYN_XFER_NS_0 25
1391#define SYN_XFER_NS_1 30
1392#define SYN_XFER_NS_2 35
1393#define SYN_XFER_NS_3 40
1394#define SYN_XFER_NS_4 50
1395#define SYN_XFER_NS_5 60
1396#define SYN_XFER_NS_6 70
1397#define SYN_XFER_NS_7 85
1398#define SYN_ULTRA_XFER_NS_0 12
1399#define SYN_ULTRA_XFER_NS_1 19
1400#define SYN_ULTRA_XFER_NS_2 25
1401#define SYN_ULTRA_XFER_NS_3 32
1402#define SYN_ULTRA_XFER_NS_4 38
1403#define SYN_ULTRA_XFER_NS_5 44
1404#define SYN_ULTRA_XFER_NS_6 50
1405#define SYN_ULTRA_XFER_NS_7 57
1406#define SYN_ULTRA_XFER_NS_8 63
1407#define SYN_ULTRA_XFER_NS_9 69
1408#define SYN_ULTRA_XFER_NS_10 75
1409#define SYN_ULTRA_XFER_NS_11 82
1410#define SYN_ULTRA_XFER_NS_12 88
1411#define SYN_ULTRA_XFER_NS_13 94
1412#define SYN_ULTRA_XFER_NS_14 100
1413#define SYN_ULTRA_XFER_NS_15 107
1414
1415typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001416 uchar msg_type;
1417 uchar msg_len;
1418 uchar msg_req;
1419 union {
1420 struct {
1421 uchar sdtr_xfer_period;
1422 uchar sdtr_req_ack_offset;
1423 } sdtr;
1424 struct {
1425 uchar wdtr_width;
1426 } wdtr;
1427 struct {
1428 uchar mdp_b3;
1429 uchar mdp_b2;
1430 uchar mdp_b1;
1431 uchar mdp_b0;
1432 } mdp;
1433 } u_ext_msg;
1434 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435} EXT_MSG;
1436
1437#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
1438#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
1439#define wdtr_width u_ext_msg.wdtr.wdtr_width
1440#define mdp_b3 u_ext_msg.mdp_b3
1441#define mdp_b2 u_ext_msg.mdp_b2
1442#define mdp_b1 u_ext_msg.mdp_b1
1443#define mdp_b0 u_ext_msg.mdp_b0
1444
1445typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001446 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1447 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1448 ASC_SCSI_BIT_ID_TYPE disc_enable;
1449 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
1450 uchar chip_scsi_id;
1451 uchar isa_dma_speed;
1452 uchar isa_dma_channel;
1453 uchar chip_version;
1454 ushort lib_serial_no;
1455 ushort lib_version;
1456 ushort mcode_date;
1457 ushort mcode_version;
1458 uchar max_tag_qng[ASC_MAX_TID + 1];
1459 uchar *overrun_buf;
1460 uchar sdtr_period_offset[ASC_MAX_TID + 1];
1461 ushort pci_slot_info;
1462 uchar adapter_info[6];
1463 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464} ASC_DVC_CFG;
1465
1466#define ASC_DEF_DVC_CNTL 0xFFFF
1467#define ASC_DEF_CHIP_SCSI_ID 7
1468#define ASC_DEF_ISA_DMA_SPEED 4
1469#define ASC_INIT_STATE_NULL 0x0000
1470#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1471#define ASC_INIT_STATE_END_GET_CFG 0x0002
1472#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1473#define ASC_INIT_STATE_END_SET_CFG 0x0008
1474#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1475#define ASC_INIT_STATE_END_LOAD_MC 0x0020
1476#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1477#define ASC_INIT_STATE_END_INQUIRY 0x0080
1478#define ASC_INIT_RESET_SCSI_DONE 0x0100
1479#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
1481#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
1482#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1483#define ASC_MIN_TAGGED_CMD 7
1484#define ASC_MAX_SCSI_RESET_WAIT 30
1485
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001486struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001488typedef void (*ASC_ISR_CALLBACK) (struct asc_dvc_var *, ASC_QDONE_INFO *);
1489typedef int (*ASC_EXE_CALLBACK) (struct asc_dvc_var *, ASC_SCSI_Q *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
1491typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001492 PortAddr iop_base;
1493 ushort err_code;
1494 ushort dvc_cntl;
1495 ushort bug_fix_cntl;
1496 ushort bus_type;
1497 ASC_ISR_CALLBACK isr_callback;
1498 ASC_EXE_CALLBACK exe_callback;
1499 ASC_SCSI_BIT_ID_TYPE init_sdtr;
1500 ASC_SCSI_BIT_ID_TYPE sdtr_done;
1501 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1502 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1503 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1504 ASC_SCSI_BIT_ID_TYPE start_motor;
1505 uchar scsi_reset_wait;
1506 uchar chip_no;
1507 char is_in_int;
1508 uchar max_total_qng;
1509 uchar cur_total_qng;
1510 uchar in_critical_cnt;
1511 uchar irq_no;
1512 uchar last_q_shortage;
1513 ushort init_state;
1514 uchar cur_dvc_qng[ASC_MAX_TID + 1];
1515 uchar max_dvc_qng[ASC_MAX_TID + 1];
1516 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
1517 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
1518 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
1519 ASC_DVC_CFG *cfg;
1520 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
1521 char redo_scam;
1522 ushort res2;
1523 uchar dos_int13_table[ASC_MAX_TID + 1];
1524 ASC_DCNT max_dma_count;
1525 ASC_SCSI_BIT_ID_TYPE no_scam;
1526 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1527 uchar max_sdtr_index;
1528 uchar host_init_sdtr_index;
1529 struct asc_board *drv_ptr;
1530 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531} ASC_DVC_VAR;
1532
1533typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001534 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535} ASC_DVC_INQ_INFO;
1536
1537typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001538 ASC_DCNT lba;
1539 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540} ASC_CAP_INFO;
1541
1542typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001543 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544} ASC_CAP_INFO_ARRAY;
1545
1546#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
1547#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
1548#define ASC_CNTL_INITIATOR (ushort)0x0001
1549#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
1550#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
1551#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
1552#define ASC_CNTL_NO_SCAM (ushort)0x0010
1553#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
1554#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
1555#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
1556#define ASC_CNTL_RESET_SCSI (ushort)0x0200
1557#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
1558#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
1559#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
1560#define ASC_CNTL_BURST_MODE (ushort)0x2000
1561#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
1562#define ASC_EEP_DVC_CFG_BEG_VL 2
1563#define ASC_EEP_MAX_DVC_ADDR_VL 15
1564#define ASC_EEP_DVC_CFG_BEG 32
1565#define ASC_EEP_MAX_DVC_ADDR 45
1566#define ASC_EEP_DEFINED_WORDS 10
1567#define ASC_EEP_MAX_ADDR 63
1568#define ASC_EEP_RES_WORDS 0
1569#define ASC_EEP_MAX_RETRY 20
1570#define ASC_MAX_INIT_BUSY_RETRY 8
1571#define ASC_EEP_ISA_PNP_WSIZE 16
1572
1573/*
1574 * These macros keep the chip SCSI id and ISA DMA speed
1575 * bitfields in board order. C bitfields aren't portable
1576 * between big and little-endian platforms so they are
1577 * not used.
1578 */
1579
1580#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
1581#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
1582#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
1583 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
1584#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
1585 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
1586
1587typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001588 ushort cfg_lsw;
1589 ushort cfg_msw;
1590 uchar init_sdtr;
1591 uchar disc_enable;
1592 uchar use_cmd_qng;
1593 uchar start_motor;
1594 uchar max_total_qng;
1595 uchar max_tag_qng;
1596 uchar bios_scan;
1597 uchar power_up_wait;
1598 uchar no_scam;
1599 uchar id_speed; /* low order 4 bits is chip scsi id */
1600 /* high order 4 bits is isa dma speed */
1601 uchar dos_int13_table[ASC_MAX_TID + 1];
1602 uchar adapter_info[6];
1603 ushort cntl;
1604 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605} ASCEEP_CONFIG;
1606
1607#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
1608#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
1609#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
1610
1611#define ASC_EEP_CMD_READ 0x80
1612#define ASC_EEP_CMD_WRITE 0x40
1613#define ASC_EEP_CMD_WRITE_ABLE 0x30
1614#define ASC_EEP_CMD_WRITE_DISABLE 0x00
1615#define ASC_OVERRUN_BSIZE 0x00000048UL
1616#define ASC_CTRL_BREAK_ONCE 0x0001
1617#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
1618#define ASCV_MSGOUT_BEG 0x0000
1619#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1620#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1621#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
1622#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1623#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1624#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1625#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1626#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1627#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
1628#define ASCV_BREAK_ADDR (ushort)0x0028
1629#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
1630#define ASCV_BREAK_CONTROL (ushort)0x002C
1631#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
1632
1633#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
1634#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
1635#define ASCV_MCODE_SIZE_W (ushort)0x0034
1636#define ASCV_STOP_CODE_B (ushort)0x0036
1637#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
1638#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
1639#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
1640#define ASCV_HALTCODE_W (ushort)0x0040
1641#define ASCV_CHKSUM_W (ushort)0x0042
1642#define ASCV_MC_DATE_W (ushort)0x0044
1643#define ASCV_MC_VER_W (ushort)0x0046
1644#define ASCV_NEXTRDY_B (ushort)0x0048
1645#define ASCV_DONENEXT_B (ushort)0x0049
1646#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
1647#define ASCV_SCSIBUSY_B (ushort)0x004B
1648#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
1649#define ASCV_CURCDB_B (ushort)0x004D
1650#define ASCV_RCLUN_B (ushort)0x004E
1651#define ASCV_BUSY_QHEAD_B (ushort)0x004F
1652#define ASCV_DISC1_QHEAD_B (ushort)0x0050
1653#define ASCV_DISC_ENABLE_B (ushort)0x0052
1654#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
1655#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
1656#define ASCV_MCODE_CNTL_B (ushort)0x0056
1657#define ASCV_NULL_TARGET_B (ushort)0x0057
1658#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
1659#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
1660#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
1661#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
1662#define ASCV_HOST_FLAG_B (ushort)0x005D
1663#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
1664#define ASCV_VER_SERIAL_B (ushort)0x0065
1665#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
1666#define ASCV_WTM_FLAG_B (ushort)0x0068
1667#define ASCV_RISC_FLAG_B (ushort)0x006A
1668#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
1669#define ASC_HOST_FLAG_IN_ISR 0x01
1670#define ASC_HOST_FLAG_ACK_INT 0x02
1671#define ASC_RISC_FLAG_GEN_INT 0x01
1672#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1673#define IOP_CTRL (0x0F)
1674#define IOP_STATUS (0x0E)
1675#define IOP_INT_ACK IOP_STATUS
1676#define IOP_REG_IFC (0x0D)
1677#define IOP_SYN_OFFSET (0x0B)
1678#define IOP_EXTRA_CONTROL (0x0D)
1679#define IOP_REG_PC (0x0C)
1680#define IOP_RAM_ADDR (0x0A)
1681#define IOP_RAM_DATA (0x08)
1682#define IOP_EEP_DATA (0x06)
1683#define IOP_EEP_CMD (0x07)
1684#define IOP_VERSION (0x03)
1685#define IOP_CONFIG_HIGH (0x04)
1686#define IOP_CONFIG_LOW (0x02)
1687#define IOP_SIG_BYTE (0x01)
1688#define IOP_SIG_WORD (0x00)
1689#define IOP_REG_DC1 (0x0E)
1690#define IOP_REG_DC0 (0x0C)
1691#define IOP_REG_SB (0x0B)
1692#define IOP_REG_DA1 (0x0A)
1693#define IOP_REG_DA0 (0x08)
1694#define IOP_REG_SC (0x09)
1695#define IOP_DMA_SPEED (0x07)
1696#define IOP_REG_FLAG (0x07)
1697#define IOP_FIFO_H (0x06)
1698#define IOP_FIFO_L (0x04)
1699#define IOP_REG_ID (0x05)
1700#define IOP_REG_QP (0x03)
1701#define IOP_REG_IH (0x02)
1702#define IOP_REG_IX (0x01)
1703#define IOP_REG_AX (0x00)
1704#define IFC_REG_LOCK (0x00)
1705#define IFC_REG_UNLOCK (0x09)
1706#define IFC_WR_EN_FILTER (0x10)
1707#define IFC_RD_NO_EEPROM (0x10)
1708#define IFC_SLEW_RATE (0x20)
1709#define IFC_ACT_NEG (0x40)
1710#define IFC_INP_FILTER (0x80)
1711#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
1712#define SC_SEL (uchar)(0x80)
1713#define SC_BSY (uchar)(0x40)
1714#define SC_ACK (uchar)(0x20)
1715#define SC_REQ (uchar)(0x10)
1716#define SC_ATN (uchar)(0x08)
1717#define SC_IO (uchar)(0x04)
1718#define SC_CD (uchar)(0x02)
1719#define SC_MSG (uchar)(0x01)
1720#define SEC_SCSI_CTL (uchar)(0x80)
1721#define SEC_ACTIVE_NEGATE (uchar)(0x40)
1722#define SEC_SLEW_RATE (uchar)(0x20)
1723#define SEC_ENABLE_FILTER (uchar)(0x10)
1724#define ASC_HALT_EXTMSG_IN (ushort)0x8000
1725#define ASC_HALT_CHK_CONDITION (ushort)0x8100
1726#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
1727#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
1728#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
1729#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
1730#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
1731#define ASC_MAX_QNO 0xF8
1732#define ASC_DATA_SEC_BEG (ushort)0x0080
1733#define ASC_DATA_SEC_END (ushort)0x0080
1734#define ASC_CODE_SEC_BEG (ushort)0x0080
1735#define ASC_CODE_SEC_END (ushort)0x0080
1736#define ASC_QADR_BEG (0x4000)
1737#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
1738#define ASC_QADR_END (ushort)0x7FFF
1739#define ASC_QLAST_ADR (ushort)0x7FC0
1740#define ASC_QBLK_SIZE 0x40
1741#define ASC_BIOS_DATA_QBEG 0xF8
1742#define ASC_MIN_ACTIVE_QNO 0x01
1743#define ASC_QLINK_END 0xFF
1744#define ASC_EEPROM_WORDS 0x10
1745#define ASC_MAX_MGS_LEN 0x10
1746#define ASC_BIOS_ADDR_DEF 0xDC00
1747#define ASC_BIOS_SIZE 0x3800
1748#define ASC_BIOS_RAM_OFF 0x3800
1749#define ASC_BIOS_RAM_SIZE 0x800
1750#define ASC_BIOS_MIN_ADDR 0xC000
1751#define ASC_BIOS_MAX_ADDR 0xEC00
1752#define ASC_BIOS_BANK_SIZE 0x0400
1753#define ASC_MCODE_START_ADDR 0x0080
1754#define ASC_CFG0_HOST_INT_ON 0x0020
1755#define ASC_CFG0_BIOS_ON 0x0040
1756#define ASC_CFG0_VERA_BURST_ON 0x0080
1757#define ASC_CFG0_SCSI_PARITY_ON 0x0800
1758#define ASC_CFG1_SCSI_TARGET_ON 0x0080
1759#define ASC_CFG1_LRAM_8BITS_ON 0x0800
1760#define ASC_CFG_MSW_CLR_MASK 0x3080
1761#define CSW_TEST1 (ASC_CS_TYPE)0x8000
1762#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
1763#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
1764#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
1765#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
1766#define CSW_TEST2 (ASC_CS_TYPE)0x0400
1767#define CSW_TEST3 (ASC_CS_TYPE)0x0200
1768#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
1769#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
1770#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
1771#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
1772#define CSW_HALTED (ASC_CS_TYPE)0x0010
1773#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
1774#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
1775#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
1776#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
1777#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
1778#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
1779#define CIW_TEST1 (ASC_CS_TYPE)0x0200
1780#define CIW_TEST2 (ASC_CS_TYPE)0x0400
1781#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
1782#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
1783#define CC_CHIP_RESET (uchar)0x80
1784#define CC_SCSI_RESET (uchar)0x40
1785#define CC_HALT (uchar)0x20
1786#define CC_SINGLE_STEP (uchar)0x10
1787#define CC_DMA_ABLE (uchar)0x08
1788#define CC_TEST (uchar)0x04
1789#define CC_BANK_ONE (uchar)0x02
1790#define CC_DIAG (uchar)0x01
1791#define ASC_1000_ID0W 0x04C1
1792#define ASC_1000_ID0W_FIX 0x00C1
1793#define ASC_1000_ID1B 0x25
1794#define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50)
1795#define ASC_EISA_SMALL_IOP_GAP (0x0020)
1796#define ASC_EISA_MIN_IOP_ADDR (0x0C30)
1797#define ASC_EISA_MAX_IOP_ADDR (0xFC50)
1798#define ASC_EISA_REV_IOP_MASK (0x0C83)
1799#define ASC_EISA_PID_IOP_MASK (0x0C80)
1800#define ASC_EISA_CFG_IOP_MASK (0x0C86)
1801#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
1802#define ASC_EISA_ID_740 0x01745004UL
1803#define ASC_EISA_ID_750 0x01755004UL
1804#define INS_HALTINT (ushort)0x6281
1805#define INS_HALT (ushort)0x6280
1806#define INS_SINT (ushort)0x6200
1807#define INS_RFLAG_WTM (ushort)0x7380
1808#define ASC_MC_SAVE_CODE_WSIZE 0x500
1809#define ASC_MC_SAVE_DATA_WSIZE 0x40
1810
1811typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001812 ushort data[ASC_MC_SAVE_DATA_WSIZE];
1813 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814} ASC_MC_SAVED;
1815
1816#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
1817#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1818#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1819#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1820#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1821#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1822#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1823#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1824#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1825#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1826#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1827#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1828#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1829#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1830#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1831#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1832#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1833#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1834#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1835#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1836#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1837#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1838#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1839#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1840#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1841#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1842#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1843#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1844#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1845#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1846#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1847#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1848#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1849#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1850#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1851#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1852#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1853#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1854#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1855#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1856#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1857#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1858#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1859#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1860#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1861#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1862#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1863#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1864#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1865#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1866#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1867#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1868#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1869#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1870#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1871#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1872#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1873#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1874#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1875#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1876#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1877#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1878#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1879#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1880#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1881#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1882#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1883#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1884
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001885static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1886static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1887static void AscWaitEEPRead(void);
1888static void AscWaitEEPWrite(void);
1889static ushort AscReadEEPWord(PortAddr, uchar);
1890static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1891static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1892static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1893static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1894static int AscStartChip(PortAddr);
1895static int AscStopChip(PortAddr);
1896static void AscSetChipIH(PortAddr, ushort);
1897static int AscIsChipHalted(PortAddr);
1898static void AscAckInterrupt(PortAddr);
1899static void AscDisableInterrupt(PortAddr);
1900static void AscEnableInterrupt(PortAddr);
1901static void AscSetBank(PortAddr, uchar);
1902static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001904static ushort AscGetIsaDmaChannel(PortAddr);
1905static ushort AscSetIsaDmaChannel(PortAddr, ushort);
1906static uchar AscSetIsaDmaSpeed(PortAddr, uchar);
1907static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001909static uchar AscReadLramByte(PortAddr, ushort);
1910static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001912static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001914static void AscWriteLramWord(PortAddr, ushort, ushort);
1915static void AscWriteLramByte(PortAddr, ushort, uchar);
1916static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1917static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1918static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1919static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1920static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1921static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1922static ushort AscInitFromEEP(ASC_DVC_VAR *);
1923static ushort AscInitFromAscDvcVar(ASC_DVC_VAR *);
1924static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1925static int AscTestExternalLram(ASC_DVC_VAR *);
1926static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1927static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1928static void AscSetChipSDTR(PortAddr, uchar, uchar);
1929static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1930static uchar AscAllocFreeQueue(PortAddr, uchar);
1931static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1932static int AscHostReqRiscHalt(PortAddr);
1933static int AscStopQueueExe(PortAddr);
1934static int AscSendScsiQueue(ASC_DVC_VAR *,
1935 ASC_SCSI_Q *scsiq, uchar n_q_required);
1936static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1937static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1938static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1939static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1940static ushort AscInitLram(ASC_DVC_VAR *);
1941static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1942static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1943static int AscIsrChipHalted(ASC_DVC_VAR *);
1944static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1945 ASC_QDONE_INFO *, ASC_DCNT);
1946static int AscIsrQDone(ASC_DVC_VAR *);
1947static int AscCompareString(uchar *, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001949static ushort AscGetEisaChipCfg(PortAddr);
1950static ASC_DCNT AscGetEisaProductID(PortAddr);
1951static PortAddr AscSearchIOPortAddrEISA(PortAddr);
1952static PortAddr AscSearchIOPortAddr11(PortAddr);
1953static PortAddr AscSearchIOPortAddr(PortAddr, ushort);
1954static void AscSetISAPNPWaitForKey(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001956static uchar AscGetChipScsiCtrl(PortAddr);
1957static uchar AscSetChipScsiID(PortAddr, uchar);
1958static uchar AscGetChipVersion(PortAddr, ushort);
1959static ushort AscGetChipBusType(PortAddr);
1960static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
1961static int AscFindSignature(PortAddr);
1962static void AscToggleIRQAct(PortAddr);
1963static uchar AscGetChipIRQ(PortAddr, ushort);
1964static uchar AscSetChipIRQ(PortAddr, uchar, ushort);
1965static ushort AscGetChipBiosAddress(PortAddr, ushort);
1966static inline ulong DvcEnterCritical(void);
1967static inline void DvcLeaveCritical(ulong);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001969static uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort);
1970static void DvcWritePCIConfigByte(ASC_DVC_VAR *, ushort, uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001972static ushort AscGetChipBiosAddress(PortAddr, ushort);
1973static void DvcSleepMilliSecond(ASC_DCNT);
1974static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1975static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1976static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
1977static ushort AscInitGetConfig(ASC_DVC_VAR *);
1978static ushort AscInitSetConfig(ASC_DVC_VAR *);
1979static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
1980static void AscAsyncFix(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *);
1981static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
1982static void AscInquiryHandling(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *);
1983static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1984static int AscISR(ASC_DVC_VAR *);
1985static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1986static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001988static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001990static ASC_DCNT AscGetMaxDmaCount(ushort);
1991static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993/*
1994 * --- Adv Library Constants and Macros
1995 */
1996
1997#define ADV_LIB_VERSION_MAJOR 5
1998#define ADV_LIB_VERSION_MINOR 14
1999
2000/*
2001 * Define Adv Library required special types.
2002 */
2003
2004/*
2005 * Portable Data Types
2006 *
2007 * Any instance where a 32-bit long or pointer type is assumed
2008 * for precision or HW defined structures, the following define
2009 * types must be used. In Linux the char, short, and int types
2010 * are all consistent at 8, 16, and 32 bits respectively. Pointers
2011 * and long types are 64 bits on Alpha and UltraSPARC.
2012 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002013#define ADV_PADDR __u32 /* Physical address data type. */
2014#define ADV_VADDR __u32 /* Virtual address data type. */
2015#define ADV_DCNT __u32 /* Unsigned Data count type. */
2016#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
2018/*
2019 * These macros are used to convert a virtual address to a
2020 * 32-bit value. This currently can be used on Linux Alpha
2021 * which uses 64-bit virtual address but a 32-bit bus address.
2022 * This is likely to break in the future, but doing this now
2023 * will give us time to change the HW and FW to handle 64-bit
2024 * addresses.
2025 */
2026#define ADV_VADDR_TO_U32 virt_to_bus
2027#define ADV_U32_TO_VADDR bus_to_virt
2028
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002029#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030
2031/*
2032 * Define Adv Library required memory access macros.
2033 */
2034#define ADV_MEM_READB(addr) readb(addr)
2035#define ADV_MEM_READW(addr) readw(addr)
2036#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
2037#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
2038#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
2039
2040#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
2041
2042/*
2043 * For wide boards a CDB length maximum of 16 bytes
2044 * is supported.
2045 */
2046#define ADV_MAX_CDB_LEN 16
2047
2048/*
2049 * Define total number of simultaneous maximum element scatter-gather
2050 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
2051 * maximum number of outstanding commands per wide host adapter. Each
2052 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
2053 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
2054 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
2055 * structures or 255 scatter-gather elements.
2056 *
2057 */
2058#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
2059
2060/*
2061 * Define Adv Library required maximum number of scatter-gather
2062 * elements per request.
2063 */
2064#define ADV_MAX_SG_LIST 255
2065
2066/* Number of SG blocks needed. */
2067#define ADV_NUM_SG_BLOCK \
2068 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
2069
2070/* Total contiguous memory needed for SG blocks. */
2071#define ADV_SG_TOTAL_MEM_SIZE \
2072 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
2073
2074#define ADV_PAGE_SIZE PAGE_SIZE
2075
2076#define ADV_NUM_PAGE_CROSSING \
2077 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2078
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079#define ADV_EEP_DVC_CFG_BEGIN (0x00)
2080#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002081#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082#define ADV_EEP_MAX_WORD_ADDR (0x1E)
2083
2084#define ADV_EEP_DELAY_MS 100
2085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002086#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
2087#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088/*
2089 * For the ASC3550 Bit 13 is Termination Polarity control bit.
2090 * For later ICs Bit 13 controls whether the CIS (Card Information
2091 * Service Section) is loaded from EEPROM.
2092 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002093#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
2094#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095/*
2096 * ASC38C1600 Bit 11
2097 *
2098 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
2099 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
2100 * Function 0 will specify INT B.
2101 *
2102 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
2103 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
2104 * Function 1 will specify INT A.
2105 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002106#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002108typedef struct adveep_3550_config {
2109 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002111 ushort cfg_lsw; /* 00 power up initialization */
2112 /* bit 13 set - Term Polarity Control */
2113 /* bit 14 set - BIOS Enable */
2114 /* bit 15 set - Big Endian Mode */
2115 ushort cfg_msw; /* 01 unused */
2116 ushort disc_enable; /* 02 disconnect enable */
2117 ushort wdtr_able; /* 03 Wide DTR able */
2118 ushort sdtr_able; /* 04 Synchronous DTR able */
2119 ushort start_motor; /* 05 send start up motor */
2120 ushort tagqng_able; /* 06 tag queuing able */
2121 ushort bios_scan; /* 07 BIOS device control */
2122 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002124 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2125 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002127 uchar scsi_reset_delay; /* 10 reset delay */
2128 uchar bios_id_lun; /* first boot device scsi id & lun */
2129 /* high nibble is lun */
2130 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002132 uchar termination; /* 11 0 - automatic */
2133 /* 1 - low off / high off */
2134 /* 2 - low off / high on */
2135 /* 3 - low on / high on */
2136 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002138 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002140 ushort bios_ctrl; /* 12 BIOS control bits */
2141 /* bit 0 BIOS don't act as initiator. */
2142 /* bit 1 BIOS > 1 GB support */
2143 /* bit 2 BIOS > 2 Disk Support */
2144 /* bit 3 BIOS don't support removables */
2145 /* bit 4 BIOS support bootable CD */
2146 /* bit 5 BIOS scan enabled */
2147 /* bit 6 BIOS support multiple LUNs */
2148 /* bit 7 BIOS display of message */
2149 /* bit 8 SCAM disabled */
2150 /* bit 9 Reset SCSI bus during init. */
2151 /* bit 10 */
2152 /* bit 11 No verbose initialization. */
2153 /* bit 12 SCSI parity enabled */
2154 /* bit 13 */
2155 /* bit 14 */
2156 /* bit 15 */
2157 ushort ultra_able; /* 13 ULTRA speed able */
2158 ushort reserved2; /* 14 reserved */
2159 uchar max_host_qng; /* 15 maximum host queuing */
2160 uchar max_dvc_qng; /* maximum per device queuing */
2161 ushort dvc_cntl; /* 16 control bit for driver */
2162 ushort bug_fix; /* 17 control bit for bug fix */
2163 ushort serial_number_word1; /* 18 Board serial number word 1 */
2164 ushort serial_number_word2; /* 19 Board serial number word 2 */
2165 ushort serial_number_word3; /* 20 Board serial number word 3 */
2166 ushort check_sum; /* 21 EEP check sum */
2167 uchar oem_name[16]; /* 22 OEM name */
2168 ushort dvc_err_code; /* 30 last device driver error code */
2169 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2170 ushort adv_err_addr; /* 32 last uc error address */
2171 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2172 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2173 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2174 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175} ADVEEP_3550_CONFIG;
2176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002177typedef struct adveep_38C0800_config {
2178 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002180 ushort cfg_lsw; /* 00 power up initialization */
2181 /* bit 13 set - Load CIS */
2182 /* bit 14 set - BIOS Enable */
2183 /* bit 15 set - Big Endian Mode */
2184 ushort cfg_msw; /* 01 unused */
2185 ushort disc_enable; /* 02 disconnect enable */
2186 ushort wdtr_able; /* 03 Wide DTR able */
2187 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2188 ushort start_motor; /* 05 send start up motor */
2189 ushort tagqng_able; /* 06 tag queuing able */
2190 ushort bios_scan; /* 07 BIOS device control */
2191 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002193 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2194 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002196 uchar scsi_reset_delay; /* 10 reset delay */
2197 uchar bios_id_lun; /* first boot device scsi id & lun */
2198 /* high nibble is lun */
2199 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002201 uchar termination_se; /* 11 0 - automatic */
2202 /* 1 - low off / high off */
2203 /* 2 - low off / high on */
2204 /* 3 - low on / high on */
2205 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002207 uchar termination_lvd; /* 11 0 - automatic */
2208 /* 1 - low off / high off */
2209 /* 2 - low off / high on */
2210 /* 3 - low on / high on */
2211 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002213 ushort bios_ctrl; /* 12 BIOS control bits */
2214 /* bit 0 BIOS don't act as initiator. */
2215 /* bit 1 BIOS > 1 GB support */
2216 /* bit 2 BIOS > 2 Disk Support */
2217 /* bit 3 BIOS don't support removables */
2218 /* bit 4 BIOS support bootable CD */
2219 /* bit 5 BIOS scan enabled */
2220 /* bit 6 BIOS support multiple LUNs */
2221 /* bit 7 BIOS display of message */
2222 /* bit 8 SCAM disabled */
2223 /* bit 9 Reset SCSI bus during init. */
2224 /* bit 10 */
2225 /* bit 11 No verbose initialization. */
2226 /* bit 12 SCSI parity enabled */
2227 /* bit 13 */
2228 /* bit 14 */
2229 /* bit 15 */
2230 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2231 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2232 uchar max_host_qng; /* 15 maximum host queueing */
2233 uchar max_dvc_qng; /* maximum per device queuing */
2234 ushort dvc_cntl; /* 16 control bit for driver */
2235 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2236 ushort serial_number_word1; /* 18 Board serial number word 1 */
2237 ushort serial_number_word2; /* 19 Board serial number word 2 */
2238 ushort serial_number_word3; /* 20 Board serial number word 3 */
2239 ushort check_sum; /* 21 EEP check sum */
2240 uchar oem_name[16]; /* 22 OEM name */
2241 ushort dvc_err_code; /* 30 last device driver error code */
2242 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2243 ushort adv_err_addr; /* 32 last uc error address */
2244 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2245 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2246 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2247 ushort reserved36; /* 36 reserved */
2248 ushort reserved37; /* 37 reserved */
2249 ushort reserved38; /* 38 reserved */
2250 ushort reserved39; /* 39 reserved */
2251 ushort reserved40; /* 40 reserved */
2252 ushort reserved41; /* 41 reserved */
2253 ushort reserved42; /* 42 reserved */
2254 ushort reserved43; /* 43 reserved */
2255 ushort reserved44; /* 44 reserved */
2256 ushort reserved45; /* 45 reserved */
2257 ushort reserved46; /* 46 reserved */
2258 ushort reserved47; /* 47 reserved */
2259 ushort reserved48; /* 48 reserved */
2260 ushort reserved49; /* 49 reserved */
2261 ushort reserved50; /* 50 reserved */
2262 ushort reserved51; /* 51 reserved */
2263 ushort reserved52; /* 52 reserved */
2264 ushort reserved53; /* 53 reserved */
2265 ushort reserved54; /* 54 reserved */
2266 ushort reserved55; /* 55 reserved */
2267 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2268 ushort cisprt_msw; /* 57 CIS PTR MSW */
2269 ushort subsysvid; /* 58 SubSystem Vendor ID */
2270 ushort subsysid; /* 59 SubSystem ID */
2271 ushort reserved60; /* 60 reserved */
2272 ushort reserved61; /* 61 reserved */
2273 ushort reserved62; /* 62 reserved */
2274 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275} ADVEEP_38C0800_CONFIG;
2276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002277typedef struct adveep_38C1600_config {
2278 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002280 ushort cfg_lsw; /* 00 power up initialization */
2281 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
2282 /* clear - Func. 0 INTA, Func. 1 INTB */
2283 /* bit 13 set - Load CIS */
2284 /* bit 14 set - BIOS Enable */
2285 /* bit 15 set - Big Endian Mode */
2286 ushort cfg_msw; /* 01 unused */
2287 ushort disc_enable; /* 02 disconnect enable */
2288 ushort wdtr_able; /* 03 Wide DTR able */
2289 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2290 ushort start_motor; /* 05 send start up motor */
2291 ushort tagqng_able; /* 06 tag queuing able */
2292 ushort bios_scan; /* 07 BIOS device control */
2293 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002295 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2296 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002298 uchar scsi_reset_delay; /* 10 reset delay */
2299 uchar bios_id_lun; /* first boot device scsi id & lun */
2300 /* high nibble is lun */
2301 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002303 uchar termination_se; /* 11 0 - automatic */
2304 /* 1 - low off / high off */
2305 /* 2 - low off / high on */
2306 /* 3 - low on / high on */
2307 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002309 uchar termination_lvd; /* 11 0 - automatic */
2310 /* 1 - low off / high off */
2311 /* 2 - low off / high on */
2312 /* 3 - low on / high on */
2313 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002315 ushort bios_ctrl; /* 12 BIOS control bits */
2316 /* bit 0 BIOS don't act as initiator. */
2317 /* bit 1 BIOS > 1 GB support */
2318 /* bit 2 BIOS > 2 Disk Support */
2319 /* bit 3 BIOS don't support removables */
2320 /* bit 4 BIOS support bootable CD */
2321 /* bit 5 BIOS scan enabled */
2322 /* bit 6 BIOS support multiple LUNs */
2323 /* bit 7 BIOS display of message */
2324 /* bit 8 SCAM disabled */
2325 /* bit 9 Reset SCSI bus during init. */
2326 /* bit 10 Basic Integrity Checking disabled */
2327 /* bit 11 No verbose initialization. */
2328 /* bit 12 SCSI parity enabled */
2329 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
2330 /* bit 14 */
2331 /* bit 15 */
2332 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2333 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2334 uchar max_host_qng; /* 15 maximum host queueing */
2335 uchar max_dvc_qng; /* maximum per device queuing */
2336 ushort dvc_cntl; /* 16 control bit for driver */
2337 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2338 ushort serial_number_word1; /* 18 Board serial number word 1 */
2339 ushort serial_number_word2; /* 19 Board serial number word 2 */
2340 ushort serial_number_word3; /* 20 Board serial number word 3 */
2341 ushort check_sum; /* 21 EEP check sum */
2342 uchar oem_name[16]; /* 22 OEM name */
2343 ushort dvc_err_code; /* 30 last device driver error code */
2344 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2345 ushort adv_err_addr; /* 32 last uc error address */
2346 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2347 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2348 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2349 ushort reserved36; /* 36 reserved */
2350 ushort reserved37; /* 37 reserved */
2351 ushort reserved38; /* 38 reserved */
2352 ushort reserved39; /* 39 reserved */
2353 ushort reserved40; /* 40 reserved */
2354 ushort reserved41; /* 41 reserved */
2355 ushort reserved42; /* 42 reserved */
2356 ushort reserved43; /* 43 reserved */
2357 ushort reserved44; /* 44 reserved */
2358 ushort reserved45; /* 45 reserved */
2359 ushort reserved46; /* 46 reserved */
2360 ushort reserved47; /* 47 reserved */
2361 ushort reserved48; /* 48 reserved */
2362 ushort reserved49; /* 49 reserved */
2363 ushort reserved50; /* 50 reserved */
2364 ushort reserved51; /* 51 reserved */
2365 ushort reserved52; /* 52 reserved */
2366 ushort reserved53; /* 53 reserved */
2367 ushort reserved54; /* 54 reserved */
2368 ushort reserved55; /* 55 reserved */
2369 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2370 ushort cisprt_msw; /* 57 CIS PTR MSW */
2371 ushort subsysvid; /* 58 SubSystem Vendor ID */
2372 ushort subsysid; /* 59 SubSystem ID */
2373 ushort reserved60; /* 60 reserved */
2374 ushort reserved61; /* 61 reserved */
2375 ushort reserved62; /* 62 reserved */
2376 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377} ADVEEP_38C1600_CONFIG;
2378
2379/*
2380 * EEPROM Commands
2381 */
2382#define ASC_EEP_CMD_DONE 0x0200
2383#define ASC_EEP_CMD_DONE_ERR 0x0001
2384
2385/* cfg_word */
2386#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
2387
2388/* bios_ctrl */
2389#define BIOS_CTRL_BIOS 0x0001
2390#define BIOS_CTRL_EXTENDED_XLAT 0x0002
2391#define BIOS_CTRL_GT_2_DISK 0x0004
2392#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
2393#define BIOS_CTRL_BOOTABLE_CD 0x0010
2394#define BIOS_CTRL_MULTIPLE_LUN 0x0040
2395#define BIOS_CTRL_DISPLAY_MSG 0x0080
2396#define BIOS_CTRL_NO_SCAM 0x0100
2397#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
2398#define BIOS_CTRL_INIT_VERBOSE 0x0800
2399#define BIOS_CTRL_SCSI_PARITY 0x1000
2400#define BIOS_CTRL_AIPP_DIS 0x2000
2401
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002402#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
2403#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002405#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
2406#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
2408/*
2409 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
2410 * a special 16K Adv Library and Microcode version. After the issue is
2411 * resolved, should restore 32K support.
2412 *
2413 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
2414 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002415#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
2416#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */
2417#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
2419/*
2420 * Byte I/O register address from base of 'iop_base'.
2421 */
2422#define IOPB_INTR_STATUS_REG 0x00
2423#define IOPB_CHIP_ID_1 0x01
2424#define IOPB_INTR_ENABLES 0x02
2425#define IOPB_CHIP_TYPE_REV 0x03
2426#define IOPB_RES_ADDR_4 0x04
2427#define IOPB_RES_ADDR_5 0x05
2428#define IOPB_RAM_DATA 0x06
2429#define IOPB_RES_ADDR_7 0x07
2430#define IOPB_FLAG_REG 0x08
2431#define IOPB_RES_ADDR_9 0x09
2432#define IOPB_RISC_CSR 0x0A
2433#define IOPB_RES_ADDR_B 0x0B
2434#define IOPB_RES_ADDR_C 0x0C
2435#define IOPB_RES_ADDR_D 0x0D
2436#define IOPB_SOFT_OVER_WR 0x0E
2437#define IOPB_RES_ADDR_F 0x0F
2438#define IOPB_MEM_CFG 0x10
2439#define IOPB_RES_ADDR_11 0x11
2440#define IOPB_GPIO_DATA 0x12
2441#define IOPB_RES_ADDR_13 0x13
2442#define IOPB_FLASH_PAGE 0x14
2443#define IOPB_RES_ADDR_15 0x15
2444#define IOPB_GPIO_CNTL 0x16
2445#define IOPB_RES_ADDR_17 0x17
2446#define IOPB_FLASH_DATA 0x18
2447#define IOPB_RES_ADDR_19 0x19
2448#define IOPB_RES_ADDR_1A 0x1A
2449#define IOPB_RES_ADDR_1B 0x1B
2450#define IOPB_RES_ADDR_1C 0x1C
2451#define IOPB_RES_ADDR_1D 0x1D
2452#define IOPB_RES_ADDR_1E 0x1E
2453#define IOPB_RES_ADDR_1F 0x1F
2454#define IOPB_DMA_CFG0 0x20
2455#define IOPB_DMA_CFG1 0x21
2456#define IOPB_TICKLE 0x22
2457#define IOPB_DMA_REG_WR 0x23
2458#define IOPB_SDMA_STATUS 0x24
2459#define IOPB_SCSI_BYTE_CNT 0x25
2460#define IOPB_HOST_BYTE_CNT 0x26
2461#define IOPB_BYTE_LEFT_TO_XFER 0x27
2462#define IOPB_BYTE_TO_XFER_0 0x28
2463#define IOPB_BYTE_TO_XFER_1 0x29
2464#define IOPB_BYTE_TO_XFER_2 0x2A
2465#define IOPB_BYTE_TO_XFER_3 0x2B
2466#define IOPB_ACC_GRP 0x2C
2467#define IOPB_RES_ADDR_2D 0x2D
2468#define IOPB_DEV_ID 0x2E
2469#define IOPB_RES_ADDR_2F 0x2F
2470#define IOPB_SCSI_DATA 0x30
2471#define IOPB_RES_ADDR_31 0x31
2472#define IOPB_RES_ADDR_32 0x32
2473#define IOPB_SCSI_DATA_HSHK 0x33
2474#define IOPB_SCSI_CTRL 0x34
2475#define IOPB_RES_ADDR_35 0x35
2476#define IOPB_RES_ADDR_36 0x36
2477#define IOPB_RES_ADDR_37 0x37
2478#define IOPB_RAM_BIST 0x38
2479#define IOPB_PLL_TEST 0x39
2480#define IOPB_PCI_INT_CFG 0x3A
2481#define IOPB_RES_ADDR_3B 0x3B
2482#define IOPB_RFIFO_CNT 0x3C
2483#define IOPB_RES_ADDR_3D 0x3D
2484#define IOPB_RES_ADDR_3E 0x3E
2485#define IOPB_RES_ADDR_3F 0x3F
2486
2487/*
2488 * Word I/O register address from base of 'iop_base'.
2489 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002490#define IOPW_CHIP_ID_0 0x00 /* CID0 */
2491#define IOPW_CTRL_REG 0x02 /* CC */
2492#define IOPW_RAM_ADDR 0x04 /* LA */
2493#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002495#define IOPW_RISC_CSR 0x0A /* CSR */
2496#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
2497#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002499#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002501#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002503#define IOPW_EE_CMD 0x1A /* EC */
2504#define IOPW_EE_DATA 0x1C /* ED */
2505#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002507#define IOPW_Q_BASE 0x22 /* QB */
2508#define IOPW_QP 0x24 /* QP */
2509#define IOPW_IX 0x26 /* IX */
2510#define IOPW_SP 0x28 /* SP */
2511#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512#define IOPW_RES_ADDR_2C 0x2C
2513#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002514#define IOPW_SCSI_DATA 0x30 /* SD */
2515#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
2516#define IOPW_SCSI_CTRL 0x34 /* SC */
2517#define IOPW_HSHK_CFG 0x36 /* HCFG */
2518#define IOPW_SXFR_STATUS 0x36 /* SXS */
2519#define IOPW_SXFR_CNTL 0x38 /* SXL */
2520#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002522#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523
2524/*
2525 * Doubleword I/O register address from base of 'iop_base'.
2526 */
2527#define IOPDW_RES_ADDR_0 0x00
2528#define IOPDW_RAM_DATA 0x04
2529#define IOPDW_RES_ADDR_8 0x08
2530#define IOPDW_RES_ADDR_C 0x0C
2531#define IOPDW_RES_ADDR_10 0x10
2532#define IOPDW_COMMA 0x14
2533#define IOPDW_COMMB 0x18
2534#define IOPDW_RES_ADDR_1C 0x1C
2535#define IOPDW_SDMA_ADDR0 0x20
2536#define IOPDW_SDMA_ADDR1 0x24
2537#define IOPDW_SDMA_COUNT 0x28
2538#define IOPDW_SDMA_ERROR 0x2C
2539#define IOPDW_RDMA_ADDR0 0x30
2540#define IOPDW_RDMA_ADDR1 0x34
2541#define IOPDW_RDMA_COUNT 0x38
2542#define IOPDW_RDMA_ERROR 0x3C
2543
2544#define ADV_CHIP_ID_BYTE 0x25
2545#define ADV_CHIP_ID_WORD 0x04C1
2546
2547#define ADV_SC_SCSI_BUS_RESET 0x2000
2548
2549#define ADV_INTR_ENABLE_HOST_INTR 0x01
2550#define ADV_INTR_ENABLE_SEL_INTR 0x02
2551#define ADV_INTR_ENABLE_DPR_INTR 0x04
2552#define ADV_INTR_ENABLE_RTA_INTR 0x08
2553#define ADV_INTR_ENABLE_RMA_INTR 0x10
2554#define ADV_INTR_ENABLE_RST_INTR 0x20
2555#define ADV_INTR_ENABLE_DPE_INTR 0x40
2556#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
2557
2558#define ADV_INTR_STATUS_INTRA 0x01
2559#define ADV_INTR_STATUS_INTRB 0x02
2560#define ADV_INTR_STATUS_INTRC 0x04
2561
2562#define ADV_RISC_CSR_STOP (0x0000)
2563#define ADV_RISC_TEST_COND (0x2000)
2564#define ADV_RISC_CSR_RUN (0x4000)
2565#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
2566
2567#define ADV_CTRL_REG_HOST_INTR 0x0100
2568#define ADV_CTRL_REG_SEL_INTR 0x0200
2569#define ADV_CTRL_REG_DPR_INTR 0x0400
2570#define ADV_CTRL_REG_RTA_INTR 0x0800
2571#define ADV_CTRL_REG_RMA_INTR 0x1000
2572#define ADV_CTRL_REG_RES_BIT14 0x2000
2573#define ADV_CTRL_REG_DPE_INTR 0x4000
2574#define ADV_CTRL_REG_POWER_DONE 0x8000
2575#define ADV_CTRL_REG_ANY_INTR 0xFF00
2576
2577#define ADV_CTRL_REG_CMD_RESET 0x00C6
2578#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
2579#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
2580#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
2581#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
2582
2583#define ADV_TICKLE_NOP 0x00
2584#define ADV_TICKLE_A 0x01
2585#define ADV_TICKLE_B 0x02
2586#define ADV_TICKLE_C 0x03
2587
2588#define ADV_SCSI_CTRL_RSTOUT 0x2000
2589
2590#define AdvIsIntPending(port) \
2591 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
2592
2593/*
2594 * SCSI_CFG0 Register bit definitions
2595 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002596#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
2597#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
2598#define EVEN_PARITY 0x1000 /* Select Even Parity */
2599#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
2600#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
2601#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
2602#define SCAM_EN 0x0080 /* Enable SCAM selection */
2603#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
2604#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
2605#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
2606#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
2608/*
2609 * SCSI_CFG1 Register bit definitions
2610 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002611#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
2612#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
2613#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
2614#define FILTER_SEL 0x0C00 /* Filter Period Selection */
2615#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
2616#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
2617#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
2618#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
2619#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
2620#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
2621#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
2622#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
2623#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
2624#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
2625#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
2627/*
2628 * Addendum for ASC-38C0800 Chip
2629 *
2630 * The ASC-38C1600 Chip uses the same definitions except that the
2631 * bus mode override bits [12:10] have been moved to byte register
2632 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
2633 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
2634 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
2635 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
2636 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
2637 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002638#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
2639#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
2640#define HVD 0x1000 /* HVD Device Detect */
2641#define LVD 0x0800 /* LVD Device Detect */
2642#define SE 0x0400 /* SE Device Detect */
2643#define TERM_LVD 0x00C0 /* LVD Termination Bits */
2644#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
2645#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
2646#define TERM_SE 0x0030 /* SE Termination Bits */
2647#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
2648#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
2649#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
2650#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
2651#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
2652#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
2653#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
2654#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
2656#define CABLE_ILLEGAL_A 0x7
2657 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
2658
2659#define CABLE_ILLEGAL_B 0xB
2660 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
2661
2662/*
2663 * MEM_CFG Register bit definitions
2664 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002665#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
2666#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
2667#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
2668#define RAM_SZ_2KB 0x00 /* 2 KB */
2669#define RAM_SZ_4KB 0x04 /* 4 KB */
2670#define RAM_SZ_8KB 0x08 /* 8 KB */
2671#define RAM_SZ_16KB 0x0C /* 16 KB */
2672#define RAM_SZ_32KB 0x10 /* 32 KB */
2673#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
2675/*
2676 * DMA_CFG0 Register bit definitions
2677 *
2678 * This register is only accessible to the host.
2679 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002680#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
2681#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
2682#define FIFO_THRESH_16B 0x00 /* 16 bytes */
2683#define FIFO_THRESH_32B 0x20 /* 32 bytes */
2684#define FIFO_THRESH_48B 0x30 /* 48 bytes */
2685#define FIFO_THRESH_64B 0x40 /* 64 bytes */
2686#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
2687#define FIFO_THRESH_96B 0x60 /* 96 bytes */
2688#define FIFO_THRESH_112B 0x70 /* 112 bytes */
2689#define START_CTL 0x0C /* DMA start conditions */
2690#define START_CTL_TH 0x00 /* Wait threshold level (default) */
2691#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
2692#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
2693#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
2694#define READ_CMD 0x03 /* Memory Read Method */
2695#define READ_CMD_MR 0x00 /* Memory Read */
2696#define READ_CMD_MRL 0x02 /* Memory Read Long */
2697#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
2699/*
2700 * ASC-38C0800 RAM BIST Register bit definitions
2701 */
2702#define RAM_TEST_MODE 0x80
2703#define PRE_TEST_MODE 0x40
2704#define NORMAL_MODE 0x00
2705#define RAM_TEST_DONE 0x10
2706#define RAM_TEST_STATUS 0x0F
2707#define RAM_TEST_HOST_ERROR 0x08
2708#define RAM_TEST_INTRAM_ERROR 0x04
2709#define RAM_TEST_RISC_ERROR 0x02
2710#define RAM_TEST_SCSI_ERROR 0x01
2711#define RAM_TEST_SUCCESS 0x00
2712#define PRE_TEST_VALUE 0x05
2713#define NORMAL_VALUE 0x00
2714
2715/*
2716 * ASC38C1600 Definitions
2717 *
2718 * IOPB_PCI_INT_CFG Bit Field Definitions
2719 */
2720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002721#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
2723/*
2724 * Bit 1 can be set to change the interrupt for the Function to operate in
2725 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
2726 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
2727 * mode, otherwise the operating mode is undefined.
2728 */
2729#define TOTEMPOLE 0x02
2730
2731/*
2732 * Bit 0 can be used to change the Int Pin for the Function. The value is
2733 * 0 by default for both Functions with Function 0 using INT A and Function
2734 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
2735 * INT A is used.
2736 *
2737 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
2738 * value specified in the PCI Configuration Space.
2739 */
2740#define INTAB 0x01
2741
2742/* a_advlib.h */
2743
2744/*
2745 * Adv Library Status Definitions
2746 */
2747#define ADV_TRUE 1
2748#define ADV_FALSE 0
2749#define ADV_NOERROR 1
2750#define ADV_SUCCESS 1
2751#define ADV_BUSY 0
2752#define ADV_ERROR (-1)
2753
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754/*
2755 * ADV_DVC_VAR 'warn_code' values
2756 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002757#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
2758#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
2759#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
2760#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
2761#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002763#define ADV_MAX_TID 15 /* max. target identifier */
2764#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
2766/*
2767 * Error code values are set in ADV_DVC_VAR 'err_code'.
2768 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002769#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
2770#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
2771#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
2772#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
2773#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
2774#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
2775#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
2776#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
2777#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
2778#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
2779#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
2780#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
2781#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
2782#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783
2784/*
2785 * Fixed locations of microcode operating variables.
2786 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002787#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
2788#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
2789#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
2790#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
2791#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
2792#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
2793#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
2794#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
2795#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
2796#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
2797#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
2798#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
2799#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800#define ASC_MC_CHIP_TYPE 0x009A
2801#define ASC_MC_INTRB_CODE 0x009B
2802#define ASC_MC_WDTR_ABLE 0x009C
2803#define ASC_MC_SDTR_ABLE 0x009E
2804#define ASC_MC_TAGQNG_ABLE 0x00A0
2805#define ASC_MC_DISC_ENABLE 0x00A2
2806#define ASC_MC_IDLE_CMD_STATUS 0x00A4
2807#define ASC_MC_IDLE_CMD 0x00A6
2808#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
2809#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
2810#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
2811#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
2812#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
2813#define ASC_MC_SDTR_DONE 0x00B6
2814#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
2815#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
2816#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002817#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002819#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820#define ASC_MC_ICQ 0x0160
2821#define ASC_MC_IRQ 0x0164
2822#define ASC_MC_PPR_ABLE 0x017A
2823
2824/*
2825 * BIOS LRAM variable absolute offsets.
2826 */
2827#define BIOS_CODESEG 0x54
2828#define BIOS_CODELEN 0x56
2829#define BIOS_SIGNATURE 0x58
2830#define BIOS_VERSION 0x5A
2831
2832/*
2833 * Microcode Control Flags
2834 *
2835 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
2836 * and handled by the microcode.
2837 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002838#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
2839#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840
2841/*
2842 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
2843 */
2844#define HSHK_CFG_WIDE_XFR 0x8000
2845#define HSHK_CFG_RATE 0x0F00
2846#define HSHK_CFG_OFFSET 0x001F
2847
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002848#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
2849#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
2850#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
2851#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002853#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2854#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2855#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2856#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2857#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002859#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2860#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2861#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2862#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2863#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864/*
2865 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2866 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2867 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002868#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2869#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
2871/*
2872 * All fields here are accessed by the board microcode and need to be
2873 * little-endian.
2874 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002875typedef struct adv_carr_t {
2876 ADV_VADDR carr_va; /* Carrier Virtual Address */
2877 ADV_PADDR carr_pa; /* Carrier Physical Address */
2878 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2879 /*
2880 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2881 *
2882 * next_vpa [3:1] Reserved Bits
2883 * next_vpa [0] Done Flag set in Response Queue.
2884 */
2885 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886} ADV_CARR_T;
2887
2888/*
2889 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2890 */
2891#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2892
2893#define ASC_RQ_DONE 0x00000001
2894#define ASC_RQ_GOOD 0x00000002
2895#define ASC_CQ_STOPPER 0x00000000
2896
2897#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2898
2899#define ADV_CARRIER_NUM_PAGE_CROSSING \
2900 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2901 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2902
2903#define ADV_CARRIER_BUFSIZE \
2904 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2905
2906/*
2907 * ASC_SCSI_REQ_Q 'a_flag' definitions
2908 *
2909 * The Adv Library should limit use to the lower nibble (4 bits) of
2910 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2911 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002912#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2913#define ADV_SCSIQ_DONE 0x02 /* request done */
2914#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002916#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2917#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2918#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
2920/*
2921 * Adapter temporary configuration structure
2922 *
2923 * This structure can be discarded after initialization. Don't add
2924 * fields here needed after initialization.
2925 *
2926 * Field naming convention:
2927 *
2928 * *_enable indicates the field enables or disables a feature. The
2929 * value of the field is never reset.
2930 */
2931typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002932 ushort disc_enable; /* enable disconnection */
2933 uchar chip_version; /* chip version */
2934 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2935 ushort lib_version; /* Adv Library version number */
2936 ushort control_flag; /* Microcode Control Flag */
2937 ushort mcode_date; /* Microcode date */
2938 ushort mcode_version; /* Microcode version */
2939 ushort pci_slot_info; /* high byte device/function number */
2940 /* bits 7-3 device num., bits 2-0 function num. */
2941 /* low byte bus num. */
2942 ushort serial1; /* EEPROM serial number word 1 */
2943 ushort serial2; /* EEPROM serial number word 2 */
2944 ushort serial3; /* EEPROM serial number word 3 */
2945 struct device *dev; /* pointer to the pci dev structure for this board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946} ADV_DVC_CFG;
2947
2948struct adv_dvc_var;
2949struct adv_scsi_req_q;
2950
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002951typedef void (*ADV_ISR_CALLBACK)
2952 (struct adv_dvc_var *, struct adv_scsi_req_q *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002954typedef void (*ADV_ASYNC_CALLBACK)
2955 (struct adv_dvc_var *, uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
2957/*
2958 * Adapter operation variable structure.
2959 *
2960 * One structure is required per host adapter.
2961 *
2962 * Field naming convention:
2963 *
2964 * *_able indicates both whether a feature should be enabled or disabled
2965 * and whether a device isi capable of the feature. At initialization
2966 * this field may be set, but later if a device is found to be incapable
2967 * of the feature, the field is cleared.
2968 */
2969typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002970 AdvPortAddr iop_base; /* I/O port address */
2971 ushort err_code; /* fatal error code */
2972 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
2973 ADV_ISR_CALLBACK isr_callback;
2974 ADV_ASYNC_CALLBACK async_callback;
2975 ushort wdtr_able; /* try WDTR for a device */
2976 ushort sdtr_able; /* try SDTR for a device */
2977 ushort ultra_able; /* try SDTR Ultra speed for a device */
2978 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2979 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2980 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2981 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2982 ushort tagqng_able; /* try tagged queuing with a device */
2983 ushort ppr_able; /* PPR message capable per TID bitmask. */
2984 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2985 ushort start_motor; /* start motor command allowed */
2986 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2987 uchar chip_no; /* should be assigned by caller */
2988 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2989 uchar irq_no; /* IRQ number */
2990 ushort no_scam; /* scam_tolerant of EEPROM */
2991 struct asc_board *drv_ptr; /* driver pointer to private structure */
2992 uchar chip_scsi_id; /* chip SCSI target ID */
2993 uchar chip_type;
2994 uchar bist_err_code;
2995 ADV_CARR_T *carrier_buf;
2996 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2997 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2998 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2999 ushort carr_pending_cnt; /* Count of pending carriers. */
3000 /*
3001 * Note: The following fields will not be used after initialization. The
3002 * driver may discard the buffer after initialization is done.
3003 */
3004 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005} ADV_DVC_VAR;
3006
3007#define NO_OF_SG_PER_BLOCK 15
3008
3009typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003010 uchar reserved1;
3011 uchar reserved2;
3012 uchar reserved3;
3013 uchar sg_cnt; /* Valid entries in block. */
3014 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
3015 struct {
3016 ADV_PADDR sg_addr; /* SG element address. */
3017 ADV_DCNT sg_count; /* SG element count. */
3018 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019} ADV_SG_BLOCK;
3020
3021/*
3022 * ADV_SCSI_REQ_Q - microcode request structure
3023 *
3024 * All fields in this structure up to byte 60 are used by the microcode.
3025 * The microcode makes assumptions about the size and ordering of fields
3026 * in this structure. Do not change the structure definition here without
3027 * coordinating the change with the microcode.
3028 *
3029 * All fields accessed by microcode must be maintained in little_endian
3030 * order.
3031 */
3032typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003033 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
3034 uchar target_cmd;
3035 uchar target_id; /* Device target identifier. */
3036 uchar target_lun; /* Device target logical unit number. */
3037 ADV_PADDR data_addr; /* Data buffer physical address. */
3038 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
3039 ADV_PADDR sense_addr;
3040 ADV_PADDR carr_pa;
3041 uchar mflag;
3042 uchar sense_len;
3043 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
3044 uchar scsi_cntl;
3045 uchar done_status; /* Completion status. */
3046 uchar scsi_status; /* SCSI status byte. */
3047 uchar host_status; /* Ucode host status. */
3048 uchar sg_working_ix;
3049 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
3050 ADV_PADDR sg_real_addr; /* SG list physical address. */
3051 ADV_PADDR scsiq_rptr;
3052 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
3053 ADV_VADDR scsiq_ptr;
3054 ADV_VADDR carr_va;
3055 /*
3056 * End of microcode structure - 60 bytes. The rest of the structure
3057 * is used by the Adv Library and ignored by the microcode.
3058 */
3059 ADV_VADDR srb_ptr;
3060 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
3061 char *vdata_addr; /* Data buffer virtual address. */
3062 uchar a_flag;
3063 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064} ADV_SCSI_REQ_Q;
3065
3066/*
3067 * Microcode idle loop commands
3068 */
3069#define IDLE_CMD_COMPLETED 0
3070#define IDLE_CMD_STOP_CHIP 0x0001
3071#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
3072#define IDLE_CMD_SEND_INT 0x0004
3073#define IDLE_CMD_ABORT 0x0008
3074#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003075#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
3076#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077#define IDLE_CMD_SCSIREQ 0x0080
3078
3079#define IDLE_CMD_STATUS_SUCCESS 0x0001
3080#define IDLE_CMD_STATUS_FAILURE 0x0002
3081
3082/*
3083 * AdvSendIdleCmd() flag definitions.
3084 */
3085#define ADV_NOWAIT 0x01
3086
3087/*
3088 * Wait loop time out values.
3089 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003090#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
3091#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
3092#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
3093#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
3094#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003096#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
3097#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
3098#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
3099#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003101#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
3103/*
3104 * Device drivers must define the following functions.
3105 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003106static inline ulong DvcEnterCritical(void);
3107static inline void DvcLeaveCritical(ulong);
3108static void DvcSleepMilliSecond(ADV_DCNT);
3109static uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
3110static void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
3111static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
3112 uchar *, ASC_SDCNT *, int);
3113static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114
3115/*
3116 * Adv Library functions available to drivers.
3117 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003118static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3119static int AdvISR(ADV_DVC_VAR *);
3120static int AdvInitGetConfig(ADV_DVC_VAR *);
3121static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
3122static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
3123static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
3124static int AdvResetChipAndSB(ADV_DVC_VAR *);
3125static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
3127/*
3128 * Internal Adv Library functions.
3129 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003130static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
3131static void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3132static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
3133static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
3134static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
3135static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3136static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3137static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3138static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3139static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
3140static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
3141static void AdvWaitEEPCmd(AdvPortAddr);
3142static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143
3144/*
3145 * PCI Bus Definitions
3146 */
3147#define AscPCICmdRegBits_BusMastering 0x0007
3148#define AscPCICmdRegBits_ParErrRespCtrl 0x0040
3149
3150/* Read byte from a register. */
3151#define AdvReadByteRegister(iop_base, reg_off) \
3152 (ADV_MEM_READB((iop_base) + (reg_off)))
3153
3154/* Write byte to a register. */
3155#define AdvWriteByteRegister(iop_base, reg_off, byte) \
3156 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
3157
3158/* Read word (2 bytes) from a register. */
3159#define AdvReadWordRegister(iop_base, reg_off) \
3160 (ADV_MEM_READW((iop_base) + (reg_off)))
3161
3162/* Write word (2 bytes) to a register. */
3163#define AdvWriteWordRegister(iop_base, reg_off, word) \
3164 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
3165
3166/* Write dword (4 bytes) to a register. */
3167#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
3168 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
3169
3170/* Read byte from LRAM. */
3171#define AdvReadByteLram(iop_base, addr, byte) \
3172do { \
3173 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3174 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
3175} while (0)
3176
3177/* Write byte to LRAM. */
3178#define AdvWriteByteLram(iop_base, addr, byte) \
3179 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3180 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
3181
3182/* Read word (2 bytes) from LRAM. */
3183#define AdvReadWordLram(iop_base, addr, word) \
3184do { \
3185 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3186 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
3187} while (0)
3188
3189/* Write word (2 bytes) to LRAM. */
3190#define AdvWriteWordLram(iop_base, addr, word) \
3191 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3192 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3193
3194/* Write little-endian double word (4 bytes) to LRAM */
3195/* Because of unspecified C language ordering don't use auto-increment. */
3196#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
3197 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3198 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3199 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
3200 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3201 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3202 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
3203
3204/* Read word (2 bytes) from LRAM assuming that the address is already set. */
3205#define AdvReadWordAutoIncLram(iop_base) \
3206 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
3207
3208/* Write word (2 bytes) to LRAM assuming that the address is already set. */
3209#define AdvWriteWordAutoIncLram(iop_base, word) \
3210 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3211
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212/*
3213 * Define macro to check for Condor signature.
3214 *
3215 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
3216 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
3217 */
3218#define AdvFindSignature(iop_base) \
3219 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
3220 ADV_CHIP_ID_BYTE) && \
3221 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
3222 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
3223
3224/*
3225 * Define macro to Return the version number of the chip at 'iop_base'.
3226 *
3227 * The second parameter 'bus_type' is currently unused.
3228 */
3229#define AdvGetChipVersion(iop_base, bus_type) \
3230 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
3231
3232/*
3233 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
3234 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
3235 *
3236 * If the request has not yet been sent to the device it will simply be
3237 * aborted from RISC memory. If the request is disconnected it will be
3238 * aborted on reselection by sending an Abort Message to the target ID.
3239 *
3240 * Return value:
3241 * ADV_TRUE(1) - Queue was successfully aborted.
3242 * ADV_FALSE(0) - Queue was not found on the active queue list.
3243 */
3244#define AdvAbortQueue(asc_dvc, scsiq) \
3245 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
3246 (ADV_DCNT) (scsiq))
3247
3248/*
3249 * Send a Bus Device Reset Message to the specified target ID.
3250 *
3251 * All outstanding commands will be purged if sending the
3252 * Bus Device Reset Message is successful.
3253 *
3254 * Return Value:
3255 * ADV_TRUE(1) - All requests on the target are purged.
3256 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
3257 * are not purged.
3258 */
3259#define AdvResetDevice(asc_dvc, target_id) \
3260 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
3261 (ADV_DCNT) (target_id))
3262
3263/*
3264 * SCSI Wide Type definition.
3265 */
3266#define ADV_SCSI_BIT_ID_TYPE ushort
3267
3268/*
3269 * AdvInitScsiTarget() 'cntl_flag' options.
3270 */
3271#define ADV_SCAN_LUN 0x01
3272#define ADV_CAPINFO_NOLUN 0x02
3273
3274/*
3275 * Convert target id to target id bit mask.
3276 */
3277#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
3278
3279/*
3280 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
3281 */
3282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003283#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284#define QD_NO_ERROR 0x01
3285#define QD_ABORTED_BY_HOST 0x02
3286#define QD_WITH_ERROR 0x04
3287
3288#define QHSTA_NO_ERROR 0x00
3289#define QHSTA_M_SEL_TIMEOUT 0x11
3290#define QHSTA_M_DATA_OVER_RUN 0x12
3291#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
3292#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003293#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
3294#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
3295#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
3296#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
3297#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
3298#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
3299#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003301#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
3302#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
3303#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
3304#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
3305#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
3306#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
3307#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
3308#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309#define QHSTA_M_WTM_TIMEOUT 0x41
3310#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
3311#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
3312#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003313#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
3314#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
3315#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316
3317/*
3318 * Default EEPROM Configuration structure defined in a_init.c.
3319 */
3320static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
3321static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
3322static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
3323
3324/*
3325 * DvcGetPhyAddr() flag arguments
3326 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003327#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
3328#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
3329#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
3330#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
3331#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
3332#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
3334/* Return the address that is aligned at the next doubleword >= to 'addr'. */
3335#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
3336#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
3337#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
3338
3339/*
3340 * Total contiguous memory needed for driver SG blocks.
3341 *
3342 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
3343 * number of scatter-gather elements the driver supports in a
3344 * single request.
3345 */
3346
3347#define ADV_SG_LIST_MAX_BYTE_SIZE \
3348 (sizeof(ADV_SG_BLOCK) * \
3349 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
3350
3351/*
3352 * Inquiry data structure and bitfield macros
3353 *
3354 * Using bitfields to access the subchar data isn't portable across
3355 * endianness, so instead mask and shift. Only quantities of more
3356 * than 1 bit are shifted, since the others are just tested for true
3357 * or false.
3358 */
3359
3360#define ADV_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f)
3361#define ADV_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5)
3362#define ADV_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f)
3363#define ADV_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80)
3364#define ADV_INQ_ANSI_VER(inq) ((inq)->ver & 0x07)
3365#define ADV_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3)
3366#define ADV_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6)
3367#define ADV_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f)
3368#define ADV_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40)
3369#define ADV_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80)
3370#define ADV_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01)
3371#define ADV_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02)
3372#define ADV_INQ_LINK_CMD(inq) ((inq)->flags & 0x08)
3373#define ADV_INQ_SYNC(inq) ((inq)->flags & 0x10)
3374#define ADV_INQ_WIDE16(inq) ((inq)->flags & 0x20)
3375#define ADV_INQ_WIDE32(inq) ((inq)->flags & 0x40)
3376#define ADV_INQ_REL_ADDR(inq) ((inq)->flags & 0x80)
3377#define ADV_INQ_INFO_UNIT(inq) ((inq)->info & 0x01)
3378#define ADV_INQ_QUICK_ARB(inq) ((inq)->info & 0x02)
3379#define ADV_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2)
3380
3381typedef struct {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003382 uchar periph; /* peripheral device type [0:4] */
3383 /* peripheral qualifier [5:7] */
3384 uchar devtype; /* device type modifier (for SCSI I) [0:6] */
3385 /* RMB - removable medium bit [7] */
3386 uchar ver; /* ANSI approved version [0:2] */
3387 /* ECMA version [3:5] */
3388 /* ISO version [6:7] */
3389 uchar byte3; /* response data format [0:3] */
3390 /* 0 SCSI 1 */
3391 /* 1 CCS */
3392 /* 2 SCSI-2 */
3393 /* 3-F reserved */
3394 /* reserved [4:5] */
3395 /* terminate I/O process bit (see 5.6.22) [6] */
3396 /* asynch. event notification (processor) [7] */
3397 uchar add_len; /* additional length */
3398 uchar res1; /* reserved */
3399 uchar res2; /* reserved */
3400 uchar flags; /* soft reset implemented [0] */
3401 /* command queuing [1] */
3402 /* reserved [2] */
3403 /* linked command for this logical unit [3] */
3404 /* synchronous data transfer [4] */
3405 /* wide bus 16 bit data transfer [5] */
3406 /* wide bus 32 bit data transfer [6] */
3407 /* relative addressing mode [7] */
3408 uchar vendor_id[8]; /* vendor identification */
3409 uchar product_id[16]; /* product identification */
3410 uchar product_rev_level[4]; /* product revision level */
3411 uchar vendor_specific[20]; /* vendor specific */
3412 uchar info; /* information unit supported [0] */
3413 /* quick arbitrate supported [1] */
3414 /* clocking field [2:3] */
3415 /* reserved [4:7] */
3416 uchar res3; /* reserved */
3417} ADV_SCSI_INQUIRY; /* 58 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418
3419/*
3420 * --- Driver Constants and Macros
3421 */
3422
3423#define ASC_NUM_BOARD_SUPPORTED 16
3424#define ASC_NUM_IOPORT_PROBE 4
3425#define ASC_NUM_BUS 4
3426
3427/* Reference Scsi_Host hostdata */
3428#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
3429
3430/* asc_board_t flags */
3431#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003432#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433#define ASC_SELECT_QUEUE_DEPTHS 0x08
3434
3435#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
3436#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
3437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003438#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003440#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441
3442#ifdef CONFIG_PROC_FS
3443/* /proc/scsi/advansys/[0...] related definitions */
3444#define ASC_PRTBUF_SIZE 2048
3445#define ASC_PRTLINE_SIZE 160
3446
3447#define ASC_PRT_NEXT() \
3448 if (cp) { \
3449 totlen += len; \
3450 leftlen -= len; \
3451 if (leftlen == 0) { \
3452 return totlen; \
3453 } \
3454 cp += len; \
3455 }
3456#endif /* CONFIG_PROC_FS */
3457
3458/* Asc Library return codes */
3459#define ASC_TRUE 1
3460#define ASC_FALSE 0
3461#define ASC_NOERROR 1
3462#define ASC_BUSY 0
3463#define ASC_ERROR (-1)
3464
3465/* struct scsi_cmnd function return codes */
3466#define STATUS_BYTE(byte) (byte)
3467#define MSG_BYTE(byte) ((byte) << 8)
3468#define HOST_BYTE(byte) ((byte) << 16)
3469#define DRIVER_BYTE(byte) ((byte) << 24)
3470
3471/*
3472 * The following definitions and macros are OS independent interfaces to
3473 * the queue functions:
3474 * REQ - SCSI request structure
3475 * REQP - pointer to SCSI request structure
3476 * REQPTID(reqp) - reqp's target id
3477 * REQPNEXT(reqp) - reqp's next pointer
3478 * REQPNEXTP(reqp) - pointer to reqp's next pointer
3479 * REQPTIME(reqp) - reqp's time stamp value
3480 * REQTIMESTAMP() - system time stamp value
3481 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003482typedef struct scsi_cmnd REQ, *REQP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483#define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
3484#define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
3485#define REQPTID(reqp) ((reqp)->device->id)
3486#define REQPTIME(reqp) ((reqp)->SCp.this_residual)
3487#define REQTIMESTAMP() (jiffies)
3488
3489#define REQTIMESTAT(function, ascq, reqp, tid) \
3490{ \
3491 /*
3492 * If the request time stamp is less than the system time stamp, then \
3493 * maybe the system time stamp wrapped. Set the request time to zero.\
3494 */ \
3495 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
3496 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
3497 } else { \
3498 /* Indicate an error occurred with the assertion. */ \
3499 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
3500 REQPTIME(reqp) = 0; \
3501 } \
3502 /* Handle first minimum time case without external initialization. */ \
3503 if (((ascq)->q_tot_cnt[tid] == 1) || \
3504 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
3505 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
3506 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
3507 (function), (tid), (ascq)->q_min_tim[tid]); \
3508 } \
3509 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
3510 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
3511 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
3512 (function), tid, (ascq)->q_max_tim[tid]); \
3513 } \
3514 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
3515 /* Reset the time stamp field. */ \
3516 REQPTIME(reqp) = 0; \
3517}
3518
3519/* asc_enqueue() flags */
3520#define ASC_FRONT 1
3521#define ASC_BACK 2
3522
3523/* asc_dequeue_list() argument */
3524#define ASC_TID_ALL (-1)
3525
3526/* Return non-zero, if the queue is empty. */
3527#define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
3528
3529#define PCI_MAX_SLOT 0x1F
3530#define PCI_MAX_BUS 0xFF
3531#define PCI_IOADDRESS_MASK 0xFFFE
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003532#define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
3534#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003535#define ASC_STATS(shost, counter)
3536#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003538#define ASC_STATS(shost, counter) \
3539 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003541#define ASC_STATS_ADD(shost, counter, count) \
3542 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543#endif /* ADVANSYS_STATS */
3544
3545#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
3546
3547/* If the result wraps when calculating tenths, return 0. */
3548#define ASC_TENTHS(num, den) \
3549 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
3550 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
3551
3552/*
3553 * Display a message to the console.
3554 */
3555#define ASC_PRINT(s) \
3556 { \
3557 printk("advansys: "); \
3558 printk(s); \
3559 }
3560
3561#define ASC_PRINT1(s, a1) \
3562 { \
3563 printk("advansys: "); \
3564 printk((s), (a1)); \
3565 }
3566
3567#define ASC_PRINT2(s, a1, a2) \
3568 { \
3569 printk("advansys: "); \
3570 printk((s), (a1), (a2)); \
3571 }
3572
3573#define ASC_PRINT3(s, a1, a2, a3) \
3574 { \
3575 printk("advansys: "); \
3576 printk((s), (a1), (a2), (a3)); \
3577 }
3578
3579#define ASC_PRINT4(s, a1, a2, a3, a4) \
3580 { \
3581 printk("advansys: "); \
3582 printk((s), (a1), (a2), (a3), (a4)); \
3583 }
3584
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585#ifndef ADVANSYS_DEBUG
3586
3587#define ASC_DBG(lvl, s)
3588#define ASC_DBG1(lvl, s, a1)
3589#define ASC_DBG2(lvl, s, a1, a2)
3590#define ASC_DBG3(lvl, s, a1, a2, a3)
3591#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
3592#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
3593#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
3594#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
3595#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3596#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
3597#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3598#define ASC_DBG_PRT_HEX(lvl, name, start, length)
3599#define ASC_DBG_PRT_CDB(lvl, cdb, len)
3600#define ASC_DBG_PRT_SENSE(lvl, sense, len)
3601#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
3602
3603#else /* ADVANSYS_DEBUG */
3604
3605/*
3606 * Debugging Message Levels:
3607 * 0: Errors Only
3608 * 1: High-Level Tracing
3609 * 2-N: Verbose Tracing
3610 */
3611
3612#define ASC_DBG(lvl, s) \
3613 { \
3614 if (asc_dbglvl >= (lvl)) { \
3615 printk(s); \
3616 } \
3617 }
3618
3619#define ASC_DBG1(lvl, s, a1) \
3620 { \
3621 if (asc_dbglvl >= (lvl)) { \
3622 printk((s), (a1)); \
3623 } \
3624 }
3625
3626#define ASC_DBG2(lvl, s, a1, a2) \
3627 { \
3628 if (asc_dbglvl >= (lvl)) { \
3629 printk((s), (a1), (a2)); \
3630 } \
3631 }
3632
3633#define ASC_DBG3(lvl, s, a1, a2, a3) \
3634 { \
3635 if (asc_dbglvl >= (lvl)) { \
3636 printk((s), (a1), (a2), (a3)); \
3637 } \
3638 }
3639
3640#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
3641 { \
3642 if (asc_dbglvl >= (lvl)) { \
3643 printk((s), (a1), (a2), (a3), (a4)); \
3644 } \
3645 }
3646
3647#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
3648 { \
3649 if (asc_dbglvl >= (lvl)) { \
3650 asc_prt_scsi_host(s); \
3651 } \
3652 }
3653
3654#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
3655 { \
3656 if (asc_dbglvl >= (lvl)) { \
3657 asc_prt_scsi_cmnd(s); \
3658 } \
3659 }
3660
3661#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
3662 { \
3663 if (asc_dbglvl >= (lvl)) { \
3664 asc_prt_asc_scsi_q(scsiqp); \
3665 } \
3666 }
3667
3668#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
3669 { \
3670 if (asc_dbglvl >= (lvl)) { \
3671 asc_prt_asc_qdone_info(qdone); \
3672 } \
3673 }
3674
3675#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
3676 { \
3677 if (asc_dbglvl >= (lvl)) { \
3678 asc_prt_adv_scsi_req_q(scsiqp); \
3679 } \
3680 }
3681
3682#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
3683 { \
3684 if (asc_dbglvl >= (lvl)) { \
3685 asc_prt_hex((name), (start), (length)); \
3686 } \
3687 }
3688
3689#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
3690 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
3691
3692#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
3693 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
3694
3695#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
3696 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
3697#endif /* ADVANSYS_DEBUG */
3698
3699#ifndef ADVANSYS_ASSERT
3700#define ASC_ASSERT(a)
3701#else /* ADVANSYS_ASSERT */
3702
3703#define ASC_ASSERT(a) \
3704 { \
3705 if (!(a)) { \
3706 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
3707 __FILE__, __LINE__); \
3708 } \
3709 }
3710
3711#endif /* ADVANSYS_ASSERT */
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713/*
3714 * --- Driver Structures
3715 */
3716
3717#ifdef ADVANSYS_STATS
3718
3719/* Per board statistics structure */
3720struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003721 /* Driver Entrypoint Statistics */
3722 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
3723 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
3724 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
3725 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
3726 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
3727 ADV_DCNT done; /* # calls to request's scsi_done function */
3728 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
3729 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
3730 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
3731 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
3732 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
3733 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
3734 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
3735 ADV_DCNT exe_unknown; /* # unknown returns. */
3736 /* Data Transfer Statistics */
3737 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
3738 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
3739 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
3740 ADV_DCNT sg_elem; /* # scatter-gather elements */
3741 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742};
3743#endif /* ADVANSYS_STATS */
3744
3745/*
3746 * Request queuing structure
3747 */
3748typedef struct asc_queue {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003749 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
3750 REQP q_first[ADV_MAX_TID + 1]; /* first queued request */
3751 REQP q_last[ADV_MAX_TID + 1]; /* last queued request */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003753 short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */
3754 short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */
3755 ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */
3756 ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */
3757 ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */
3758 ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */
3759#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760} asc_queue_t;
3761
3762/*
3763 * Adv Library Request Structures
3764 *
3765 * The following two structures are used to process Wide Board requests.
3766 *
3767 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
3768 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
3769 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
3770 * Mid-Level SCSI request structure.
3771 *
3772 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
3773 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
3774 * up to 255 scatter-gather elements may be used per request or
3775 * ADV_SCSI_REQ_Q.
3776 *
3777 * Both structures must be 32 byte aligned.
3778 */
3779typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003780 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
3781 uchar align[32]; /* Sgblock structure padding. */
3782 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783} adv_sgblk_t;
3784
3785typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003786 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
3787 uchar align[32]; /* Request structure padding. */
3788 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
3789 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
3790 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791} adv_req_t;
3792
3793/*
3794 * Structure allocated for each board.
3795 *
3796 * This structure is allocated by scsi_register() at the end
3797 * of the 'Scsi_Host' structure starting at the 'hostdata'
3798 * field. It is guaranteed to be allocated from DMA-able memory.
3799 */
3800typedef struct asc_board {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003801 int id; /* Board Id */
3802 uint flags; /* Board flags */
3803 union {
3804 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
3805 ADV_DVC_VAR adv_dvc_var; /* Wide board */
3806 } dvc_var;
3807 union {
3808 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
3809 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
3810 } dvc_cfg;
3811 ushort asc_n_io_port; /* Number I/O ports. */
3812 asc_queue_t active; /* Active command queue */
3813 asc_queue_t waiting; /* Waiting command queue */
3814 asc_queue_t done; /* Done command queue */
3815 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
3816 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
3817 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
3818 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
3819 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
3820 union {
3821 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
3822 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
3823 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
3824 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
3825 } eep_config;
3826 ulong last_reset; /* Saved last reset time */
3827 spinlock_t lock; /* Board spinlock */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003829 /* /proc/scsi/advansys/[0...] */
3830 char *prtbuf; /* /proc print buffer */
3831#endif /* CONFIG_PROC_FS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003833 struct asc_stats asc_stats; /* Board statistics */
3834#endif /* ADVANSYS_STATS */
3835 /*
3836 * The following fields are used only for Narrow Boards.
3837 */
3838 /* The following three structures must be in DMA-able memory. */
3839 ASC_SCSI_REQ_Q scsireqq;
3840 ASC_CAP_INFO cap_info;
3841 ASC_SCSI_INQUIRY inquiry;
3842 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
3843 /*
3844 * The following fields are used only for Wide Boards.
3845 */
3846 void __iomem *ioremap_addr; /* I/O Memory remap address. */
3847 ushort ioport; /* I/O Port address. */
3848 ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */
3849 adv_req_t *orig_reqp; /* adv_req_t memory block. */
3850 adv_req_t *adv_reqp; /* Request structures. */
3851 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
3852 ushort bios_signature; /* BIOS Signature. */
3853 ushort bios_version; /* BIOS Version. */
3854 ushort bios_codeseg; /* BIOS Code Segment. */
3855 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856} asc_board_t;
3857
3858/*
3859 * PCI configuration structures
3860 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003861typedef struct _PCI_DATA_ {
3862 uchar type;
3863 uchar bus;
3864 uchar slot;
3865 uchar func;
3866 uchar offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867} PCI_DATA;
3868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003869typedef struct _PCI_DEVICE_ {
3870 ushort vendorID;
3871 ushort deviceID;
3872 ushort slotNumber;
3873 ushort slotFound;
3874 uchar busNumber;
3875 uchar maxBusNumber;
3876 uchar devFunc;
3877 ushort startSlot;
3878 ushort endSlot;
3879 uchar bridge;
3880 uchar type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881} PCI_DEVICE;
3882
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003883typedef struct _PCI_CONFIG_SPACE_ {
3884 ushort vendorID;
3885 ushort deviceID;
3886 ushort command;
3887 ushort status;
3888 uchar revision;
3889 uchar classCode[3];
3890 uchar cacheSize;
3891 uchar latencyTimer;
3892 uchar headerType;
3893 uchar bist;
3894 ADV_PADDR baseAddress[6];
3895 ushort reserved[4];
3896 ADV_PADDR optionRomAddr;
3897 ushort reserved2[4];
3898 uchar irqLine;
3899 uchar irqPin;
3900 uchar minGnt;
3901 uchar maxLatency;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902} PCI_CONFIG_SPACE;
3903
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904/*
3905 * --- Driver Data
3906 */
3907
3908/* Note: All driver global data should be initialized. */
3909
3910/* Number of boards detected in system. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003911static int asc_board_count = 0;
3912static struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
3914/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003915static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
3917/*
3918 * Global structures required to issue a command.
3919 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003920static ASC_SCSI_Q asc_scsi_q = { {0} };
3921static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923/* List of supported bus types. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003924static ushort asc_bus[ASC_NUM_BUS] __initdata = {
3925 ASC_IS_ISA,
3926 ASC_IS_VL,
3927 ASC_IS_EISA,
3928 ASC_IS_PCI,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929};
3930
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003931static int asc_iopflag = ASC_FALSE;
3932static int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
3934#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003935static char *asc_bus_name[ASC_NUM_BUS] = {
3936 "ASC_IS_ISA",
3937 "ASC_IS_VL",
3938 "ASC_IS_EISA",
3939 "ASC_IS_PCI",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940};
3941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003942static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943#endif /* ADVANSYS_DEBUG */
3944
3945/* Declaration for Asc Library internal data referenced by driver. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003946static PortAddr _asc_def_iop_base[];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947
3948/*
3949 * --- Driver Function Prototypes
3950 *
3951 * advansys.h contains function prototypes for functions global to Linux.
3952 */
3953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003954static irqreturn_t advansys_interrupt(int, void *);
3955static int advansys_slave_configure(struct scsi_device *);
3956static void asc_scsi_done_list(struct scsi_cmnd *);
3957static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
3958static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
3959static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
3960static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
3961static void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
3962static void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3963static void adv_async_callback(ADV_DVC_VAR *, uchar);
3964static void asc_enqueue(asc_queue_t *, REQP, int);
3965static REQP asc_dequeue(asc_queue_t *, int);
3966static REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
3967static int asc_rmqueue(asc_queue_t *, REQP);
3968static void asc_execute_queue(asc_queue_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003970static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
3971static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
3972static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
3973static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
3974static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
3975static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
3976static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
3977static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
3978static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
3979static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980#endif /* CONFIG_PROC_FS */
3981
3982/* Declaration for Asc Library internal functions referenced by driver. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003983static int AscFindSignature(PortAddr);
3984static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
3986/* Statistics function prototypes. */
3987#ifdef ADVANSYS_STATS
3988#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003989static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
3990static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991#endif /* CONFIG_PROC_FS */
3992#endif /* ADVANSYS_STATS */
3993
3994/* Debug function prototypes. */
3995#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003996static void asc_prt_scsi_host(struct Scsi_Host *);
3997static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
3998static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
3999static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
4000static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
4001static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
4002static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
4003static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
4004static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
4005static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
4006static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007#endif /* ADVANSYS_DEBUG */
4008
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009#ifdef CONFIG_PROC_FS
4010/*
4011 * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
4012 *
4013 * *buffer: I/O buffer
4014 * **start: if inout == FALSE pointer into buffer where user read should start
4015 * offset: current offset into a /proc/scsi/advansys/[0...] file
4016 * length: length of buffer
4017 * hostno: Scsi_Host host_no
4018 * inout: TRUE - user is writing; FALSE - user is reading
4019 *
4020 * Return the number of bytes read from or written to a
4021 * /proc/scsi/advansys/[0...] file.
4022 *
4023 * Note: This function uses the per board buffer 'prtbuf' which is
4024 * allocated when the board is initialized in advansys_detect(). The
4025 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4026 * used to write to the buffer. The way asc_proc_copy() is written
4027 * if 'prtbuf' is too small it will not be overwritten. Instead the
4028 * user just won't get all the available statistics.
4029 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004030static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004032 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004034 struct Scsi_Host *shp;
4035 asc_board_t *boardp;
4036 int i;
4037 char *cp;
4038 int cplen;
4039 int cnt;
4040 int totcnt;
4041 int leftlen;
4042 char *curbuf;
4043 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004045 int tgt_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046#endif /* ADVANSYS_STATS */
4047
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004048 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004050 /*
4051 * User write not supported.
4052 */
4053 if (inout == TRUE) {
4054 return (-ENOSYS);
4055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004057 /*
4058 * User read of /proc/scsi/advansys/[0...] file.
4059 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004061 /* Find the specified board. */
4062 for (i = 0; i < asc_board_count; i++) {
4063 if (asc_host[i]->host_no == shost->host_no) {
4064 break;
4065 }
4066 }
4067 if (i == asc_board_count) {
4068 return (-ENOENT);
4069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004071 shp = asc_host[i];
4072 boardp = ASC_BOARDP(shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004074 /* Copy read data starting at the beginning of the buffer. */
4075 *start = buffer;
4076 curbuf = buffer;
4077 advoffset = 0;
4078 totcnt = 0;
4079 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004081 /*
4082 * Get board configuration information.
4083 *
4084 * advansys_info() returns the board string from its own static buffer.
4085 */
4086 cp = (char *)advansys_info(shp);
4087 strcat(cp, "\n");
4088 cplen = strlen(cp);
4089 /* Copy board information. */
4090 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4091 totcnt += cnt;
4092 leftlen -= cnt;
4093 if (leftlen == 0) {
4094 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4095 return totcnt;
4096 }
4097 advoffset += cplen;
4098 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004100 /*
4101 * Display Wide Board BIOS Information.
4102 */
4103 if (ASC_WIDE_BOARD(boardp)) {
4104 cp = boardp->prtbuf;
4105 cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
4106 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4107 cnt =
4108 asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4109 cplen);
4110 totcnt += cnt;
4111 leftlen -= cnt;
4112 if (leftlen == 0) {
4113 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4114 return totcnt;
4115 }
4116 advoffset += cplen;
4117 curbuf += cnt;
4118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004120 /*
4121 * Display driver information for each device attached to the board.
4122 */
4123 cp = boardp->prtbuf;
4124 cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
4125 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4126 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4127 totcnt += cnt;
4128 leftlen -= cnt;
4129 if (leftlen == 0) {
4130 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4131 return totcnt;
4132 }
4133 advoffset += cplen;
4134 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004136 /*
4137 * Display EEPROM configuration for the board.
4138 */
4139 cp = boardp->prtbuf;
4140 if (ASC_NARROW_BOARD(boardp)) {
4141 cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4142 } else {
4143 cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4144 }
4145 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4146 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4147 totcnt += cnt;
4148 leftlen -= cnt;
4149 if (leftlen == 0) {
4150 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4151 return totcnt;
4152 }
4153 advoffset += cplen;
4154 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004156 /*
4157 * Display driver configuration and information for the board.
4158 */
4159 cp = boardp->prtbuf;
4160 cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
4161 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4162 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4163 totcnt += cnt;
4164 leftlen -= cnt;
4165 if (leftlen == 0) {
4166 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4167 return totcnt;
4168 }
4169 advoffset += cplen;
4170 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171
4172#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004173 /*
4174 * Display driver statistics for the board.
4175 */
4176 cp = boardp->prtbuf;
4177 cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
4178 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
4179 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4180 totcnt += cnt;
4181 leftlen -= cnt;
4182 if (leftlen == 0) {
4183 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4184 return totcnt;
4185 }
4186 advoffset += cplen;
4187 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004189 /*
4190 * Display driver statistics for each target.
4191 */
4192 for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
4193 cp = boardp->prtbuf;
4194 cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE);
4195 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
4196 cnt =
4197 asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4198 cplen);
4199 totcnt += cnt;
4200 leftlen -= cnt;
4201 if (leftlen == 0) {
4202 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4203 return totcnt;
4204 }
4205 advoffset += cplen;
4206 curbuf += cnt;
4207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208#endif /* ADVANSYS_STATS */
4209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004210 /*
4211 * Display Asc Library dynamic configuration information
4212 * for the board.
4213 */
4214 cp = boardp->prtbuf;
4215 if (ASC_NARROW_BOARD(boardp)) {
4216 cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
4217 } else {
4218 cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
4219 }
4220 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4221 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4222 totcnt += cnt;
4223 leftlen -= cnt;
4224 if (leftlen == 0) {
4225 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4226 return totcnt;
4227 }
4228 advoffset += cplen;
4229 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004231 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004233 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234}
4235#endif /* CONFIG_PROC_FS */
4236
4237/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 * advansys_info()
4239 *
4240 * Return suitable for printing on the console with the argument
4241 * adapter's configuration information.
4242 *
4243 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
4244 * otherwise the static 'info' array will be overrun.
4245 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004246static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004248 static char info[ASC_INFO_SIZE];
4249 asc_board_t *boardp;
4250 ASC_DVC_VAR *asc_dvc_varp;
4251 ADV_DVC_VAR *adv_dvc_varp;
4252 char *busname;
4253 int iolen;
4254 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004256 boardp = ASC_BOARDP(shost);
4257 if (ASC_NARROW_BOARD(boardp)) {
4258 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4259 ASC_DBG(1, "advansys_info: begin\n");
4260 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4261 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
4262 ASC_IS_ISAPNP) {
4263 busname = "ISA PnP";
4264 } else {
4265 busname = "ISA";
4266 }
4267 /* Don't reference 'shost->n_io_port'; It may be truncated. */
4268 sprintf(info,
4269 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
4270 ASC_VERSION, busname,
4271 (ulong)shost->io_port,
4272 (ulong)shost->io_port + boardp->asc_n_io_port -
4273 1, shost->irq, shost->dma_channel);
4274 } else {
4275 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
4276 busname = "VL";
4277 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
4278 busname = "EISA";
4279 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
4280 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
4281 == ASC_IS_PCI_ULTRA) {
4282 busname = "PCI Ultra";
4283 } else {
4284 busname = "PCI";
4285 }
4286 } else {
4287 busname = "?";
4288 ASC_PRINT2
4289 ("advansys_info: board %d: unknown bus type %d\n",
4290 boardp->id, asc_dvc_varp->bus_type);
4291 }
4292 /* Don't reference 'shost->n_io_port'; It may be truncated. */
4293 sprintf(info,
4294 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
4295 ASC_VERSION, busname,
4296 (ulong)shost->io_port,
4297 (ulong)shost->io_port + boardp->asc_n_io_port -
4298 1, shost->irq);
4299 }
4300 } else {
4301 /*
4302 * Wide Adapter Information
4303 *
4304 * Memory-mapped I/O is used instead of I/O space to access
4305 * the adapter, but display the I/O Port range. The Memory
4306 * I/O address is displayed through the driver /proc file.
4307 */
4308 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4309 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4310 iolen = ADV_3550_IOLEN;
4311 widename = "Ultra-Wide";
4312 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4313 iolen = ADV_38C0800_IOLEN;
4314 widename = "Ultra2-Wide";
4315 } else {
4316 iolen = ADV_38C1600_IOLEN;
4317 widename = "Ultra3-Wide";
4318 }
4319 sprintf(info,
4320 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
4321 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
4322 (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq);
4323 }
4324 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
4325 ASC_DBG(1, "advansys_info: end\n");
4326 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327}
4328
4329/*
4330 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
4331 *
4332 * This function always returns 0. Command return status is saved
4333 * in the 'scp' result field.
4334 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004335static int
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004336advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004338 struct Scsi_Host *shost;
4339 asc_board_t *boardp;
4340 ulong flags;
4341 struct scsi_cmnd *done_scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004343 shost = scp->device->host;
4344 boardp = ASC_BOARDP(shost);
4345 ASC_STATS(shost, queuecommand);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004347 /* host_lock taken by mid-level prior to call but need to protect */
4348 /* against own ISR */
4349 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004351 /*
4352 * Block new commands while handling a reset or abort request.
4353 */
4354 if (boardp->flags & ASC_HOST_IN_RESET) {
4355 ASC_DBG1(1,
4356 "advansys_queuecommand: scp 0x%lx blocked for reset request\n",
4357 (ulong)scp);
4358 scp->result = HOST_BYTE(DID_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004360 /*
4361 * Add blocked requests to the board's 'done' queue. The queued
4362 * requests will be completed at the end of the abort or reset
4363 * handling.
4364 */
4365 asc_enqueue(&boardp->done, scp, ASC_BACK);
4366 spin_unlock_irqrestore(&boardp->lock, flags);
4367 return 0;
4368 }
4369
4370 /*
4371 * Attempt to execute any waiting commands for the board.
4372 */
4373 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4374 ASC_DBG(1,
4375 "advansys_queuecommand: before asc_execute_queue() waiting\n");
4376 asc_execute_queue(&boardp->waiting);
4377 }
4378
4379 /*
4380 * Save the function pointer to Linux mid-level 'done' function
4381 * and attempt to execute the command.
4382 *
4383 * If ASC_NOERROR is returned the request has been added to the
4384 * board's 'active' queue and will be completed by the interrupt
4385 * handler.
4386 *
4387 * If ASC_BUSY is returned add the request to the board's per
4388 * target waiting list. This is the first time the request has
4389 * been tried. Add it to the back of the waiting list. It will be
4390 * retried later.
4391 *
4392 * If an error occurred, the request will have been placed on the
4393 * board's 'done' queue and must be completed before returning.
4394 */
4395 scp->scsi_done = done;
4396 switch (asc_execute_scsi_cmnd(scp)) {
4397 case ASC_NOERROR:
4398 break;
4399 case ASC_BUSY:
4400 asc_enqueue(&boardp->waiting, scp, ASC_BACK);
4401 break;
4402 case ASC_ERROR:
4403 default:
4404 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
4405 /* Interrupts could be enabled here. */
4406 asc_scsi_done_list(done_scp);
4407 break;
4408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004411 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412}
4413
4414/*
4415 * advansys_reset()
4416 *
4417 * Reset the bus associated with the command 'scp'.
4418 *
4419 * This function runs its own thread. Interrupts must be blocked but
4420 * sleeping is allowed and no locking other than for host structures is
4421 * required. Returns SUCCESS or FAILED.
4422 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004423static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004425 struct Scsi_Host *shost;
4426 asc_board_t *boardp;
4427 ASC_DVC_VAR *asc_dvc_varp;
4428 ADV_DVC_VAR *adv_dvc_varp;
4429 ulong flags;
4430 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4431 struct scsi_cmnd *tscp, *new_last_scp;
4432 int status;
4433 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004435 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436
4437#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004438 if (scp->device->host != NULL) {
4439 ASC_STATS(scp->device->host, reset);
4440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441#endif /* ADVANSYS_STATS */
4442
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004443 if ((shost = scp->device->host) == NULL) {
4444 scp->result = HOST_BYTE(DID_ERROR);
4445 return FAILED;
4446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004448 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004450 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
4451 boardp->id);
4452 /*
4453 * Check for re-entrancy.
4454 */
4455 spin_lock_irqsave(&boardp->lock, flags);
4456 if (boardp->flags & ASC_HOST_IN_RESET) {
4457 spin_unlock_irqrestore(&boardp->lock, flags);
4458 return FAILED;
4459 }
4460 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004463 if (ASC_NARROW_BOARD(boardp)) {
4464 /*
4465 * Narrow Board
4466 */
4467 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004469 /*
4470 * Reset the chip and SCSI bus.
4471 */
4472 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
4473 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004475 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
4476 if (asc_dvc_varp->err_code) {
4477 ASC_PRINT2
4478 ("advansys_reset: board %d: SCSI bus reset error: 0x%x\n",
4479 boardp->id, asc_dvc_varp->err_code);
4480 ret = FAILED;
4481 } else if (status) {
4482 ASC_PRINT2
4483 ("advansys_reset: board %d: SCSI bus reset warning: 0x%x\n",
4484 boardp->id, status);
4485 } else {
4486 ASC_PRINT1
4487 ("advansys_reset: board %d: SCSI bus reset successful.\n",
4488 boardp->id);
4489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004491 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
4492 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004494 } else {
4495 /*
4496 * Wide Board
4497 *
4498 * If the suggest reset bus flags are set, then reset the bus.
4499 * Otherwise only reset the device.
4500 */
4501 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004503 /*
4504 * Reset the target's SCSI bus.
4505 */
4506 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
4507 switch (AdvResetChipAndSB(adv_dvc_varp)) {
4508 case ASC_TRUE:
4509 ASC_PRINT1
4510 ("advansys_reset: board %d: SCSI bus reset successful.\n",
4511 boardp->id);
4512 break;
4513 case ASC_FALSE:
4514 default:
4515 ASC_PRINT1
4516 ("advansys_reset: board %d: SCSI bus reset error.\n",
4517 boardp->id);
4518 ret = FAILED;
4519 break;
4520 }
4521 spin_lock_irqsave(&boardp->lock, flags);
4522 (void)AdvISR(adv_dvc_varp);
4523 }
4524 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004526 /*
4527 * Dequeue all board 'done' requests. A pointer to the last request
4528 * is returned in 'last_scp'.
4529 */
4530 done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004532 /*
4533 * Dequeue all board 'active' requests for all devices and set
4534 * the request status to DID_RESET. A pointer to the last request
4535 * is returned in 'last_scp'.
4536 */
4537 if (done_scp == NULL) {
4538 done_scp =
4539 asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL);
4540 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
4541 tscp->result = HOST_BYTE(DID_RESET);
4542 }
4543 } else {
4544 /* Append to 'done_scp' at the end with 'last_scp'. */
4545 ASC_ASSERT(last_scp != NULL);
4546 last_scp->host_scribble =
4547 (unsigned char *)asc_dequeue_list(&boardp->active,
4548 &new_last_scp,
4549 ASC_TID_ALL);
4550 if (new_last_scp != NULL) {
4551 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4552 for (tscp = REQPNEXT(last_scp); tscp;
4553 tscp = REQPNEXT(tscp)) {
4554 tscp->result = HOST_BYTE(DID_RESET);
4555 }
4556 last_scp = new_last_scp;
4557 }
4558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004560 /*
4561 * Dequeue all 'waiting' requests and set the request status
4562 * to DID_RESET.
4563 */
4564 if (done_scp == NULL) {
4565 done_scp =
4566 asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL);
4567 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
4568 tscp->result = HOST_BYTE(DID_RESET);
4569 }
4570 } else {
4571 /* Append to 'done_scp' at the end with 'last_scp'. */
4572 ASC_ASSERT(last_scp != NULL);
4573 last_scp->host_scribble =
4574 (unsigned char *)asc_dequeue_list(&boardp->waiting,
4575 &new_last_scp,
4576 ASC_TID_ALL);
4577 if (new_last_scp != NULL) {
4578 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4579 for (tscp = REQPNEXT(last_scp); tscp;
4580 tscp = REQPNEXT(tscp)) {
4581 tscp->result = HOST_BYTE(DID_RESET);
4582 }
4583 last_scp = new_last_scp;
4584 }
4585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004587 /* Save the time of the most recently completed reset. */
4588 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004590 /* Clear reset flag. */
4591 boardp->flags &= ~ASC_HOST_IN_RESET;
4592 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004594 /*
4595 * Complete all the 'done_scp' requests.
4596 */
4597 if (done_scp != NULL) {
4598 asc_scsi_done_list(done_scp);
4599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004601 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004603 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604}
4605
4606/*
4607 * advansys_biosparam()
4608 *
4609 * Translate disk drive geometry if the "BIOS greater than 1 GB"
4610 * support is enabled for a drive.
4611 *
4612 * ip (information pointer) is an int array with the following definition:
4613 * ip[0]: heads
4614 * ip[1]: sectors
4615 * ip[2]: cylinders
4616 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004617static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004619 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004621 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004623 ASC_DBG(1, "advansys_biosparam: begin\n");
4624 ASC_STATS(sdev->host, biosparam);
4625 boardp = ASC_BOARDP(sdev->host);
4626 if (ASC_NARROW_BOARD(boardp)) {
4627 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
4628 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
4629 ip[0] = 255;
4630 ip[1] = 63;
4631 } else {
4632 ip[0] = 64;
4633 ip[1] = 32;
4634 }
4635 } else {
4636 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
4637 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
4638 ip[0] = 255;
4639 ip[1] = 63;
4640 } else {
4641 ip[0] = 64;
4642 ip[1] = 32;
4643 }
4644 }
4645 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
4646 ASC_DBG(1, "advansys_biosparam: end\n");
4647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648}
4649
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004650static int __init advansys_detect(struct scsi_host_template *tpnt);
4651static int advansys_release(struct Scsi_Host *shp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652
4653static struct scsi_host_template driver_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004654 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004656 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004658 .name = "advansys",
4659 .detect = advansys_detect,
4660 .release = advansys_release,
4661 .info = advansys_info,
4662 .queuecommand = advansys_queuecommand,
4663 .eh_bus_reset_handler = advansys_reset,
4664 .bios_param = advansys_biosparam,
4665 .slave_configure = advansys_slave_configure,
4666 /*
4667 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
4668 * must be set. The flag will be cleared in advansys_detect for non-ISA
4669 * adapters. Refer to the comment in scsi_module.c for more information.
4670 */
4671 .unchecked_isa_dma = 1,
4672 /*
4673 * All adapters controlled by this driver are capable of large
4674 * scatter-gather lists. According to the mid-level SCSI documentation
4675 * this obviates any performance gain provided by setting
4676 * 'use_clustering'. But empirically while CPU utilization is increased
4677 * by enabling clustering, I/O throughput increases as well.
4678 */
4679 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004680};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004682#include "scsi_module.c"
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683
4684/*
4685 * --- Miscellaneous Driver Functions
4686 */
4687
4688/*
4689 * First-level interrupt handler.
4690 *
4691 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
4692 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
4693 * is not referenced. 'dev_id' could be used to identify an interrupt passed
4694 * to the AdvanSys driver which is for a device sharing an interrupt with
4695 * an AdvanSys adapter.
4696 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004697static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004699 ulong flags;
4700 int i;
4701 asc_board_t *boardp;
4702 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4703 struct scsi_cmnd *new_last_scp;
4704 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004706 ASC_DBG(1, "advansys_interrupt: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004708 /*
4709 * Check for interrupts on all boards.
4710 * AscISR() will call asc_isr_callback().
4711 */
4712 for (i = 0; i < asc_board_count; i++) {
4713 shost = asc_host[i];
4714 boardp = ASC_BOARDP(shost);
4715 ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
4716 i, (ulong)boardp);
4717 spin_lock_irqsave(&boardp->lock, flags);
4718 if (ASC_NARROW_BOARD(boardp)) {
4719 /*
4720 * Narrow Board
4721 */
4722 if (AscIsIntPending(shost->io_port)) {
4723 ASC_STATS(shost, interrupt);
4724 ASC_DBG(1,
4725 "advansys_interrupt: before AscISR()\n");
4726 AscISR(&boardp->dvc_var.asc_dvc_var);
4727 }
4728 } else {
4729 /*
4730 * Wide Board
4731 */
4732 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
4733 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
4734 ASC_STATS(shost, interrupt);
4735 }
4736 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004738 /*
4739 * Start waiting requests and create a list of completed requests.
4740 *
4741 * If a reset request is being performed for the board, the reset
4742 * handler will complete pending requests after it has completed.
4743 */
4744 if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
4745 ASC_DBG2(1,
4746 "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n",
4747 (ulong)done_scp, (ulong)last_scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004749 /* Start any waiting commands for the board. */
4750 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4751 ASC_DBG(1,
4752 "advansys_interrupt: before asc_execute_queue()\n");
4753 asc_execute_queue(&boardp->waiting);
4754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004755
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004756 /*
4757 * Add to the list of requests that must be completed.
4758 *
4759 * 'done_scp' will always be NULL on the first iteration
4760 * of this loop. 'last_scp' is set at the same time as
4761 * 'done_scp'.
4762 */
4763 if (done_scp == NULL) {
4764 done_scp =
4765 asc_dequeue_list(&boardp->done, &last_scp,
4766 ASC_TID_ALL);
4767 } else {
4768 ASC_ASSERT(last_scp != NULL);
4769 last_scp->host_scribble =
4770 (unsigned char *)asc_dequeue_list(&boardp->
4771 done,
4772 &new_last_scp,
4773 ASC_TID_ALL);
4774 if (new_last_scp != NULL) {
4775 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4776 last_scp = new_last_scp;
4777 }
4778 }
4779 }
4780 spin_unlock_irqrestore(&boardp->lock, flags);
4781 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004783 /*
4784 * If interrupts were enabled on entry, then they
4785 * are now enabled here.
4786 *
4787 * Complete all requests on the done list.
4788 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004790 asc_scsi_done_list(done_scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004792 ASC_DBG(1, "advansys_interrupt: end\n");
4793 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794}
4795
4796/*
4797 * Set the number of commands to queue per device for the
4798 * specified host adapter.
4799 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004800static int advansys_slave_configure(struct scsi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004802 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004804 boardp = ASC_BOARDP(device->host);
4805 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
4806 /*
4807 * Save a pointer to the device and set its initial/maximum
4808 * queue depth. Only save the pointer for a lun0 dev though.
4809 */
4810 if (device->lun == 0)
4811 boardp->device[device->id] = device;
4812 if (device->tagged_supported) {
4813 if (ASC_NARROW_BOARD(boardp)) {
4814 scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
4815 boardp->dvc_var.asc_dvc_var.
4816 max_dvc_qng[device->id]);
4817 } else {
4818 scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
4819 boardp->dvc_var.adv_dvc_var.
4820 max_dvc_qng);
4821 }
4822 } else {
4823 scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun);
4824 }
4825 ASC_DBG4(1,
4826 "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n",
4827 (ulong)device, (ulong)boardp, device->id, device->queue_depth);
4828 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829}
4830
4831/*
4832 * Complete all requests on the singly linked list pointed
4833 * to by 'scp'.
4834 *
4835 * Interrupts can be enabled on entry.
4836 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004837static void asc_scsi_done_list(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004839 struct scsi_cmnd *tscp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004841 ASC_DBG(2, "asc_scsi_done_list: begin\n");
4842 while (scp != NULL) {
4843 asc_board_t *boardp;
4844 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004846 ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
4847 tscp = REQPNEXT(scp);
4848 scp->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004850 boardp = ASC_BOARDP(scp->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004852 if (ASC_NARROW_BOARD(boardp))
4853 dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
4854 else
4855 dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004856
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004857 if (scp->use_sg)
4858 dma_unmap_sg(dev,
4859 (struct scatterlist *)scp->request_buffer,
4860 scp->use_sg, scp->sc_data_direction);
4861 else if (scp->request_bufflen)
4862 dma_unmap_single(dev, scp->SCp.dma_handle,
4863 scp->request_bufflen,
4864 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004866 ASC_STATS(scp->device->host, done);
4867 ASC_ASSERT(scp->scsi_done != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004869 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004871 scp = tscp;
4872 }
4873 ASC_DBG(2, "asc_scsi_done_list: done\n");
4874 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004875}
4876
4877/*
4878 * Execute a single 'Scsi_Cmnd'.
4879 *
4880 * The function 'done' is called when the request has been completed.
4881 *
4882 * Scsi_Cmnd:
4883 *
4884 * host - board controlling device
4885 * device - device to send command
4886 * target - target of device
4887 * lun - lun of device
4888 * cmd_len - length of SCSI CDB
4889 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
4890 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
4891 *
4892 * if (use_sg == 0) {
4893 * request_buffer - buffer address for request
4894 * request_bufflen - length of request buffer
4895 * } else {
4896 * request_buffer - pointer to scatterlist structure
4897 * }
4898 *
4899 * sense_buffer - sense command buffer
4900 *
4901 * result (4 bytes of an int):
4902 * Byte Meaning
4903 * 0 SCSI Status Byte Code
4904 * 1 SCSI One Byte Message Code
4905 * 2 Host Error Code
4906 * 3 Mid-Level Error Code
4907 *
4908 * host driver fields:
4909 * SCp - Scsi_Pointer used for command processing status
4910 * scsi_done - used to save caller's done function
4911 * host_scribble - used for pointer to another struct scsi_cmnd
4912 *
4913 * If this function returns ASC_NOERROR the request has been enqueued
4914 * on the board's 'active' queue and will be completed from the
4915 * interrupt handler.
4916 *
4917 * If this function returns ASC_NOERROR the request has been enqueued
4918 * on the board's 'done' queue and must be completed by the caller.
4919 *
4920 * If ASC_BUSY is returned the request will be enqueued by the
4921 * caller on the target's waiting queue and re-tried later.
4922 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004923static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004925 asc_board_t *boardp;
4926 ASC_DVC_VAR *asc_dvc_varp;
4927 ADV_DVC_VAR *adv_dvc_varp;
4928 ADV_SCSI_REQ_Q *adv_scsiqp;
4929 struct scsi_device *device;
4930 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004932 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
4933 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004935 boardp = ASC_BOARDP(scp->device->host);
4936 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004938 if (ASC_NARROW_BOARD(boardp)) {
4939 /*
4940 * Build and execute Narrow Board request.
4941 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004943 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004944
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004945 /*
4946 * Build Asc Library request structure using the
4947 * global structures 'asc_scsi_req' and 'asc_sg_head'.
4948 *
4949 * If an error is returned, then the request has been
4950 * queued on the board done queue. It will be completed
4951 * by the caller.
4952 *
4953 * asc_build_req() can not return ASC_BUSY.
4954 */
4955 if (asc_build_req(boardp, scp) == ASC_ERROR) {
4956 ASC_STATS(scp->device->host, build_error);
4957 return ASC_ERROR;
4958 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004960 /*
4961 * Execute the command. If there is no error, add the command
4962 * to the active queue.
4963 */
4964 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
4965 case ASC_NOERROR:
4966 ASC_STATS(scp->device->host, exe_noerror);
4967 /*
4968 * Increment monotonically increasing per device successful
4969 * request counter. Wrapping doesn't matter.
4970 */
4971 boardp->reqcnt[scp->device->id]++;
4972 asc_enqueue(&boardp->active, scp, ASC_BACK);
4973 ASC_DBG(1,
4974 "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
4975 break;
4976 case ASC_BUSY:
4977 /*
4978 * Caller will enqueue request on the target's waiting queue
4979 * and retry later.
4980 */
4981 ASC_STATS(scp->device->host, exe_busy);
4982 break;
4983 case ASC_ERROR:
4984 ASC_PRINT2
4985 ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
4986 boardp->id, asc_dvc_varp->err_code);
4987 ASC_STATS(scp->device->host, exe_error);
4988 scp->result = HOST_BYTE(DID_ERROR);
4989 asc_enqueue(&boardp->done, scp, ASC_BACK);
4990 break;
4991 default:
4992 ASC_PRINT2
4993 ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n",
4994 boardp->id, asc_dvc_varp->err_code);
4995 ASC_STATS(scp->device->host, exe_unknown);
4996 scp->result = HOST_BYTE(DID_ERROR);
4997 asc_enqueue(&boardp->done, scp, ASC_BACK);
4998 break;
4999 }
5000 } else {
5001 /*
5002 * Build and execute Wide Board request.
5003 */
5004 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005006 /*
5007 * Build and get a pointer to an Adv Library request structure.
5008 *
5009 * If the request is successfully built then send it below,
5010 * otherwise return with an error.
5011 */
5012 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
5013 case ASC_NOERROR:
5014 ASC_DBG(3,
5015 "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
5016 break;
5017 case ASC_BUSY:
5018 ASC_DBG(1,
5019 "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
5020 /*
5021 * If busy is returned the request has not been enqueued.
5022 * It will be enqueued by the caller on the target's waiting
5023 * queue and retried later.
5024 *
5025 * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg'
5026 * count wide board busy conditions. They are updated in
5027 * adv_build_req and adv_get_sglist, respectively.
5028 */
5029 return ASC_BUSY;
5030 case ASC_ERROR:
5031 /*
5032 * If an error is returned, then the request has been
5033 * queued on the board done queue. It will be completed
5034 * by the caller.
5035 */
5036 default:
5037 ASC_DBG(1,
5038 "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
5039 ASC_STATS(scp->device->host, build_error);
5040 return ASC_ERROR;
5041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005043 /*
5044 * Execute the command. If there is no error, add the command
5045 * to the active queue.
5046 */
5047 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
5048 case ASC_NOERROR:
5049 ASC_STATS(scp->device->host, exe_noerror);
5050 /*
5051 * Increment monotonically increasing per device successful
5052 * request counter. Wrapping doesn't matter.
5053 */
5054 boardp->reqcnt[scp->device->id]++;
5055 asc_enqueue(&boardp->active, scp, ASC_BACK);
5056 ASC_DBG(1,
5057 "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
5058 break;
5059 case ASC_BUSY:
5060 /*
5061 * Caller will enqueue request on the target's waiting queue
5062 * and retry later.
5063 */
5064 ASC_STATS(scp->device->host, exe_busy);
5065 break;
5066 case ASC_ERROR:
5067 ASC_PRINT2
5068 ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
5069 boardp->id, adv_dvc_varp->err_code);
5070 ASC_STATS(scp->device->host, exe_error);
5071 scp->result = HOST_BYTE(DID_ERROR);
5072 asc_enqueue(&boardp->done, scp, ASC_BACK);
5073 break;
5074 default:
5075 ASC_PRINT2
5076 ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n",
5077 boardp->id, adv_dvc_varp->err_code);
5078 ASC_STATS(scp->device->host, exe_unknown);
5079 scp->result = HOST_BYTE(DID_ERROR);
5080 asc_enqueue(&boardp->done, scp, ASC_BACK);
5081 break;
5082 }
5083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005085 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
5086 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087}
5088
5089/*
5090 * Build a request structure for the Asc Library (Narrow Board).
5091 *
5092 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
5093 * used to build the request.
5094 *
5095 * If an error occurs, then queue the request on the board done
5096 * queue and return ASC_ERROR.
5097 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005098static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005100 struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005102 /*
5103 * Mutually exclusive access is required to 'asc_scsi_q' and
5104 * 'asc_sg_head' until after the request is started.
5105 */
5106 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005108 /*
5109 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
5110 */
5111 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005113 /*
5114 * Build the ASC_SCSI_Q request.
5115 *
5116 * For narrow boards a CDB length maximum of 12 bytes
5117 * is supported.
5118 */
5119 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
5120 ASC_PRINT3
5121 ("asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n",
5122 boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN);
5123 scp->result = HOST_BYTE(DID_ERROR);
5124 asc_enqueue(&boardp->done, scp, ASC_BACK);
5125 return ASC_ERROR;
5126 }
5127 asc_scsi_q.cdbptr = &scp->cmnd[0];
5128 asc_scsi_q.q2.cdb_len = scp->cmd_len;
5129 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
5130 asc_scsi_q.q1.target_lun = scp->device->lun;
5131 asc_scsi_q.q2.target_ix =
5132 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
5133 asc_scsi_q.q1.sense_addr =
5134 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
5135 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005137 /*
5138 * If there are any outstanding requests for the current target,
5139 * then every 255th request send an ORDERED request. This heuristic
5140 * tries to retain the benefit of request sorting while preventing
5141 * request starvation. 255 is the max number of tags or pending commands
5142 * a device may have outstanding.
5143 *
5144 * The request count is incremented below for every successfully
5145 * started request.
5146 *
5147 */
5148 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
5149 (boardp->reqcnt[scp->device->id] % 255) == 0) {
5150 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
5151 } else {
5152 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
5153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005155 /*
5156 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
5157 * buffer command.
5158 */
5159 if (scp->use_sg == 0) {
5160 /*
5161 * CDB request of single contiguous buffer.
5162 */
5163 ASC_STATS(scp->device->host, cont_cnt);
5164 scp->SCp.dma_handle = scp->request_bufflen ?
5165 dma_map_single(dev, scp->request_buffer,
5166 scp->request_bufflen,
5167 scp->sc_data_direction) : 0;
5168 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
5169 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
5170 ASC_STATS_ADD(scp->device->host, cont_xfer,
5171 ASC_CEILING(scp->request_bufflen, 512));
5172 asc_scsi_q.q1.sg_queue_cnt = 0;
5173 asc_scsi_q.sg_head = NULL;
5174 } else {
5175 /*
5176 * CDB scatter-gather request list.
5177 */
5178 int sgcnt;
5179 int use_sg;
5180 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005182 slp = (struct scatterlist *)scp->request_buffer;
5183 use_sg =
5184 dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005186 if (use_sg > scp->device->host->sg_tablesize) {
5187 ASC_PRINT3
5188 ("asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
5189 boardp->id, use_sg,
5190 scp->device->host->sg_tablesize);
5191 dma_unmap_sg(dev, slp, scp->use_sg,
5192 scp->sc_data_direction);
5193 scp->result = HOST_BYTE(DID_ERROR);
5194 asc_enqueue(&boardp->done, scp, ASC_BACK);
5195 return ASC_ERROR;
5196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005198 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005200 /*
5201 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
5202 * structure to point to it.
5203 */
5204 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005206 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
5207 asc_scsi_q.sg_head = &asc_sg_head;
5208 asc_scsi_q.q1.data_cnt = 0;
5209 asc_scsi_q.q1.data_addr = 0;
5210 /* This is a byte value, otherwise it would need to be swapped. */
5211 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
5212 ASC_STATS_ADD(scp->device->host, sg_elem,
5213 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005215 /*
5216 * Convert scatter-gather list into ASC_SG_HEAD list.
5217 */
5218 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
5219 asc_sg_head.sg_list[sgcnt].addr =
5220 cpu_to_le32(sg_dma_address(slp));
5221 asc_sg_head.sg_list[sgcnt].bytes =
5222 cpu_to_le32(sg_dma_len(slp));
5223 ASC_STATS_ADD(scp->device->host, sg_xfer,
5224 ASC_CEILING(sg_dma_len(slp), 512));
5225 }
5226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005228 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
5229 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005231 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232}
5233
5234/*
5235 * Build a request structure for the Adv Library (Wide Board).
5236 *
5237 * If an adv_req_t can not be allocated to issue the request,
5238 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
5239 *
5240 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
5241 * microcode for DMA addresses or math operations are byte swapped
5242 * to little-endian order.
5243 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005244static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005246 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005248 adv_req_t *reqp;
5249 ADV_SCSI_REQ_Q *scsiqp;
5250 int i;
5251 int ret;
5252 struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005254 /*
5255 * Allocate an adv_req_t structure from the board to execute
5256 * the command.
5257 */
5258 if (boardp->adv_reqp == NULL) {
5259 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
5260 ASC_STATS(scp->device->host, adv_build_noreq);
5261 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005263 reqp = boardp->adv_reqp;
5264 boardp->adv_reqp = reqp->next_reqp;
5265 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005268 /*
5269 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
5270 */
5271 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005273 /*
5274 * Initialize the structure.
5275 */
5276 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005278 /*
5279 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
5280 */
5281 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005283 /*
5284 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
5285 */
5286 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005288 /*
5289 * Build the ADV_SCSI_REQ_Q request.
5290 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005292 /*
5293 * Set CDB length and copy it to the request structure.
5294 * For wide boards a CDB length maximum of 16 bytes
5295 * is supported.
5296 */
5297 if (scp->cmd_len > ADV_MAX_CDB_LEN) {
5298 ASC_PRINT3
5299 ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
5300 boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
5301 scp->result = HOST_BYTE(DID_ERROR);
5302 asc_enqueue(&boardp->done, scp, ASC_BACK);
5303 return ASC_ERROR;
5304 }
5305 scsiqp->cdb_len = scp->cmd_len;
5306 /* Copy first 12 CDB bytes to cdb[]. */
5307 for (i = 0; i < scp->cmd_len && i < 12; i++) {
5308 scsiqp->cdb[i] = scp->cmnd[i];
5309 }
5310 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
5311 for (; i < scp->cmd_len; i++) {
5312 scsiqp->cdb16[i - 12] = scp->cmnd[i];
5313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005315 scsiqp->target_id = scp->device->id;
5316 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005318 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
5319 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005321 /*
5322 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
5323 * buffer command.
5324 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005326 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
5327 scsiqp->vdata_addr = scp->request_buffer;
5328 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
5329
5330 if (scp->use_sg == 0) {
5331 /*
5332 * CDB request of single contiguous buffer.
5333 */
5334 reqp->sgblkp = NULL;
5335 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
5336 if (scp->request_bufflen) {
5337 scsiqp->vdata_addr = scp->request_buffer;
5338 scp->SCp.dma_handle =
5339 dma_map_single(dev, scp->request_buffer,
5340 scp->request_bufflen,
5341 scp->sc_data_direction);
5342 } else {
5343 scsiqp->vdata_addr = NULL;
5344 scp->SCp.dma_handle = 0;
5345 }
5346 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
5347 scsiqp->sg_list_ptr = NULL;
5348 scsiqp->sg_real_addr = 0;
5349 ASC_STATS(scp->device->host, cont_cnt);
5350 ASC_STATS_ADD(scp->device->host, cont_xfer,
5351 ASC_CEILING(scp->request_bufflen, 512));
5352 } else {
5353 /*
5354 * CDB scatter-gather request list.
5355 */
5356 struct scatterlist *slp;
5357 int use_sg;
5358
5359 slp = (struct scatterlist *)scp->request_buffer;
5360 use_sg =
5361 dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
5362
5363 if (use_sg > ADV_MAX_SG_LIST) {
5364 ASC_PRINT3
5365 ("adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
5366 boardp->id, use_sg,
5367 scp->device->host->sg_tablesize);
5368 dma_unmap_sg(dev, slp, scp->use_sg,
5369 scp->sc_data_direction);
5370 scp->result = HOST_BYTE(DID_ERROR);
5371 asc_enqueue(&boardp->done, scp, ASC_BACK);
5372
5373 /*
5374 * Free the 'adv_req_t' structure by adding it back to the
5375 * board free list.
5376 */
5377 reqp->next_reqp = boardp->adv_reqp;
5378 boardp->adv_reqp = reqp;
5379
5380 return ASC_ERROR;
5381 }
5382
5383 if ((ret =
5384 adv_get_sglist(boardp, reqp, scp,
5385 use_sg)) != ADV_SUCCESS) {
5386 /*
5387 * Free the adv_req_t structure by adding it back to the
5388 * board free list.
5389 */
5390 reqp->next_reqp = boardp->adv_reqp;
5391 boardp->adv_reqp = reqp;
5392
5393 return ret;
5394 }
5395
5396 ASC_STATS(scp->device->host, sg_cnt);
5397 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
5398 }
5399
5400 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
5401 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
5402
5403 *adv_scsiqpp = scsiqp;
5404
5405 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406}
5407
5408/*
5409 * Build scatter-gather list for Adv Library (Wide Board).
5410 *
5411 * Additional ADV_SG_BLOCK structures will need to be allocated
5412 * if the total number of scatter-gather elements exceeds
5413 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
5414 * assumed to be physically contiguous.
5415 *
5416 * Return:
5417 * ADV_SUCCESS(1) - SG List successfully created
5418 * ADV_ERROR(-1) - SG List creation failed
5419 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005420static int
5421adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
5422 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005424 adv_sgblk_t *sgblkp;
5425 ADV_SCSI_REQ_Q *scsiqp;
5426 struct scatterlist *slp;
5427 int sg_elem_cnt;
5428 ADV_SG_BLOCK *sg_block, *prev_sg_block;
5429 ADV_PADDR sg_block_paddr;
5430 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005432 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
5433 slp = (struct scatterlist *)scp->request_buffer;
5434 sg_elem_cnt = use_sg;
5435 prev_sg_block = NULL;
5436 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005438 do {
5439 /*
5440 * Allocate a 'adv_sgblk_t' structure from the board free
5441 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
5442 * (15) scatter-gather elements.
5443 */
5444 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
5445 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
5446 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005448 /*
5449 * Allocation failed. Free 'adv_sgblk_t' structures already
5450 * allocated for the request.
5451 */
5452 while ((sgblkp = reqp->sgblkp) != NULL) {
5453 /* Remove 'sgblkp' from the request list. */
5454 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005456 /* Add 'sgblkp' to the board free list. */
5457 sgblkp->next_sgblkp = boardp->adv_sgblkp;
5458 boardp->adv_sgblkp = sgblkp;
5459 }
5460 return ASC_BUSY;
5461 } else {
5462 /* Complete 'adv_sgblk_t' board allocation. */
5463 boardp->adv_sgblkp = sgblkp->next_sgblkp;
5464 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005466 /*
5467 * Get 8 byte aligned virtual and physical addresses for
5468 * the allocated ADV_SG_BLOCK structure.
5469 */
5470 sg_block =
5471 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
5472 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005474 /*
5475 * Check if this is the first 'adv_sgblk_t' for the request.
5476 */
5477 if (reqp->sgblkp == NULL) {
5478 /* Request's first scatter-gather block. */
5479 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005480
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005481 /*
5482 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
5483 * address pointers.
5484 */
5485 scsiqp->sg_list_ptr = sg_block;
5486 scsiqp->sg_real_addr =
5487 cpu_to_le32(sg_block_paddr);
5488 } else {
5489 /* Request's second or later scatter-gather block. */
5490 sgblkp->next_sgblkp = reqp->sgblkp;
5491 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005493 /*
5494 * Point the previous ADV_SG_BLOCK structure to
5495 * the newly allocated ADV_SG_BLOCK structure.
5496 */
5497 ASC_ASSERT(prev_sg_block != NULL);
5498 prev_sg_block->sg_ptr =
5499 cpu_to_le32(sg_block_paddr);
5500 }
5501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005502
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005503 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
5504 sg_block->sg_list[i].sg_addr =
5505 cpu_to_le32(sg_dma_address(slp));
5506 sg_block->sg_list[i].sg_count =
5507 cpu_to_le32(sg_dma_len(slp));
5508 ASC_STATS_ADD(scp->device->host, sg_xfer,
5509 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005511 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
5512 sg_block->sg_cnt = i + 1;
5513 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
5514 return ADV_SUCCESS;
5515 }
5516 slp++;
5517 }
5518 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
5519 prev_sg_block = sg_block;
5520 }
5521 while (1);
5522 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523}
5524
5525/*
5526 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
5527 *
5528 * Interrupt callback function for the Narrow SCSI Asc Library.
5529 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005530static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005532 asc_board_t *boardp;
5533 struct scsi_cmnd *scp;
5534 struct Scsi_Host *shost;
5535 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005537 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
5538 (ulong)asc_dvc_varp, (ulong)qdonep);
5539 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005541 /*
5542 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
5543 * command that has been completed.
5544 */
5545 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
5546 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005548 if (scp == NULL) {
5549 ASC_PRINT("asc_isr_callback: scp is NULL\n");
5550 return;
5551 }
5552 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005554 /*
5555 * If the request's host pointer is not valid, display a
5556 * message and return.
5557 */
5558 shost = scp->device->host;
5559 for (i = 0; i < asc_board_count; i++) {
5560 if (asc_host[i] == shost) {
5561 break;
5562 }
5563 }
5564 if (i == asc_board_count) {
5565 ASC_PRINT2
5566 ("asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n",
5567 (ulong)scp, (ulong)shost);
5568 return;
5569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005571 ASC_STATS(shost, callback);
5572 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005574 /*
5575 * If the request isn't found on the active queue, it may
5576 * have been removed to handle a reset request.
5577 * Display a message and return.
5578 */
5579 boardp = ASC_BOARDP(shost);
5580 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
5581 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
5582 ASC_PRINT2
5583 ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n",
5584 boardp->id, (ulong)scp);
5585 return;
5586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005588 /*
5589 * 'qdonep' contains the command's ending status.
5590 */
5591 switch (qdonep->d3.done_stat) {
5592 case QD_NO_ERROR:
5593 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
5594 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005596 /*
5597 * If an INQUIRY command completed successfully, then call
5598 * the AscInquiryHandling() function to set-up the device.
5599 */
5600 if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 &&
5601 (scp->request_bufflen - qdonep->remain_bytes) >= 8) {
5602 AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7,
5603 (ASC_SCSI_INQUIRY *)scp->
5604 request_buffer);
5605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005607 /*
5608 * Check for an underrun condition.
5609 *
5610 * If there was no error and an underrun condition, then
5611 * then return the number of underrun bytes.
5612 */
5613 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
5614 qdonep->remain_bytes <= scp->request_bufflen) {
5615 ASC_DBG1(1,
5616 "asc_isr_callback: underrun condition %u bytes\n",
5617 (unsigned)qdonep->remain_bytes);
5618 scp->resid = qdonep->remain_bytes;
5619 }
5620 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005622 case QD_WITH_ERROR:
5623 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
5624 switch (qdonep->d3.host_stat) {
5625 case QHSTA_NO_ERROR:
5626 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
5627 ASC_DBG(2,
5628 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
5629 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
5630 sizeof(scp->sense_buffer));
5631 /*
5632 * Note: The 'status_byte()' macro used by target drivers
5633 * defined in scsi.h shifts the status byte returned by
5634 * host drivers right by 1 bit. This is why target drivers
5635 * also use right shifted status byte definitions. For
5636 * instance target drivers use CHECK_CONDITION, defined to
5637 * 0x1, instead of the SCSI defined check condition value
5638 * of 0x2. Host drivers are supposed to return the status
5639 * byte as it is defined by SCSI.
5640 */
5641 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
5642 STATUS_BYTE(qdonep->d3.scsi_stat);
5643 } else {
5644 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
5645 }
5646 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005648 default:
5649 /* QHSTA error occurred */
5650 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
5651 qdonep->d3.host_stat);
5652 scp->result = HOST_BYTE(DID_BAD_TARGET);
5653 break;
5654 }
5655 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005657 case QD_ABORTED_BY_HOST:
5658 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
5659 scp->result =
5660 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
5661 scsi_msg) |
5662 STATUS_BYTE(qdonep->d3.scsi_stat);
5663 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005665 default:
5666 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
5667 qdonep->d3.done_stat);
5668 scp->result =
5669 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
5670 scsi_msg) |
5671 STATUS_BYTE(qdonep->d3.scsi_stat);
5672 break;
5673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005675 /*
5676 * If the 'init_tidmask' bit isn't already set for the target and the
5677 * current request finished normally, then set the bit for the target
5678 * to indicate that a device is present.
5679 */
5680 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
5681 qdonep->d3.done_stat == QD_NO_ERROR &&
5682 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
5683 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
5684 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005686 /*
5687 * Because interrupts may be enabled by the 'struct scsi_cmnd' done
5688 * function, add the command to the end of the board's done queue.
5689 * The done function for the command will be called from
5690 * advansys_interrupt().
5691 */
5692 asc_enqueue(&boardp->done, scp, ASC_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005694 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695}
5696
5697/*
5698 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
5699 *
5700 * Callback function for the Wide SCSI Adv Library.
5701 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005702static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005704 asc_board_t *boardp;
5705 adv_req_t *reqp;
5706 adv_sgblk_t *sgblkp;
5707 struct scsi_cmnd *scp;
5708 struct Scsi_Host *shost;
5709 int i;
5710 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005712 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
5713 (ulong)adv_dvc_varp, (ulong)scsiqp);
5714 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005716 /*
5717 * Get the adv_req_t structure for the command that has been
5718 * completed. The adv_req_t structure actually contains the
5719 * completed ADV_SCSI_REQ_Q structure.
5720 */
5721 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
5722 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
5723 if (reqp == NULL) {
5724 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
5725 return;
5726 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005727
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005728 /*
5729 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
5730 * command that has been completed.
5731 *
5732 * Note: The adv_req_t request structure and adv_sgblk_t structure,
5733 * if any, are dropped, because a board structure pointer can not be
5734 * determined.
5735 */
5736 scp = reqp->cmndp;
5737 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
5738 if (scp == NULL) {
5739 ASC_PRINT
5740 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
5741 return;
5742 }
5743 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005745 /*
5746 * If the request's host pointer is not valid, display a message
5747 * and return.
5748 */
5749 shost = scp->device->host;
5750 for (i = 0; i < asc_board_count; i++) {
5751 if (asc_host[i] == shost) {
5752 break;
5753 }
5754 }
5755 /*
5756 * Note: If the host structure is not found, the adv_req_t request
5757 * structure and adv_sgblk_t structure, if any, is dropped.
5758 */
5759 if (i == asc_board_count) {
5760 ASC_PRINT2
5761 ("adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n",
5762 (ulong)scp, (ulong)shost);
5763 return;
5764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005766 ASC_STATS(shost, callback);
5767 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005769 /*
5770 * If the request isn't found on the active queue, it may have been
5771 * removed to handle a reset request. Display a message and return.
5772 *
5773 * Note: Because the structure may still be in use don't attempt
5774 * to free the adv_req_t and adv_sgblk_t, if any, structures.
5775 */
5776 boardp = ASC_BOARDP(shost);
5777 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
5778 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
5779 ASC_PRINT2
5780 ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n",
5781 boardp->id, (ulong)scp);
5782 return;
5783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005785 /*
5786 * 'done_status' contains the command's ending status.
5787 */
5788 switch (scsiqp->done_status) {
5789 case QD_NO_ERROR:
5790 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
5791 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005793 /*
5794 * Check for an underrun condition.
5795 *
5796 * If there was no error and an underrun condition, then
5797 * then return the number of underrun bytes.
5798 */
5799 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
5800 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
5801 resid_cnt <= scp->request_bufflen) {
5802 ASC_DBG1(1,
5803 "adv_isr_callback: underrun condition %lu bytes\n",
5804 (ulong)resid_cnt);
5805 scp->resid = resid_cnt;
5806 }
5807 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005809 case QD_WITH_ERROR:
5810 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
5811 switch (scsiqp->host_status) {
5812 case QHSTA_NO_ERROR:
5813 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
5814 ASC_DBG(2,
5815 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
5816 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
5817 sizeof(scp->sense_buffer));
5818 /*
5819 * Note: The 'status_byte()' macro used by target drivers
5820 * defined in scsi.h shifts the status byte returned by
5821 * host drivers right by 1 bit. This is why target drivers
5822 * also use right shifted status byte definitions. For
5823 * instance target drivers use CHECK_CONDITION, defined to
5824 * 0x1, instead of the SCSI defined check condition value
5825 * of 0x2. Host drivers are supposed to return the status
5826 * byte as it is defined by SCSI.
5827 */
5828 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
5829 STATUS_BYTE(scsiqp->scsi_status);
5830 } else {
5831 scp->result = STATUS_BYTE(scsiqp->scsi_status);
5832 }
5833 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005835 default:
5836 /* Some other QHSTA error occurred. */
5837 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
5838 scsiqp->host_status);
5839 scp->result = HOST_BYTE(DID_BAD_TARGET);
5840 break;
5841 }
5842 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005844 case QD_ABORTED_BY_HOST:
5845 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
5846 scp->result =
5847 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
5848 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005850 default:
5851 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
5852 scsiqp->done_status);
5853 scp->result =
5854 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
5855 break;
5856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005858 /*
5859 * If the 'init_tidmask' bit isn't already set for the target and the
5860 * current request finished normally, then set the bit for the target
5861 * to indicate that a device is present.
5862 */
5863 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
5864 scsiqp->done_status == QD_NO_ERROR &&
5865 scsiqp->host_status == QHSTA_NO_ERROR) {
5866 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
5867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005869 /*
5870 * Because interrupts may be enabled by the 'struct scsi_cmnd' done
5871 * function, add the command to the end of the board's done queue.
5872 * The done function for the command will be called from
5873 * advansys_interrupt().
5874 */
5875 asc_enqueue(&boardp->done, scp, ASC_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005877 /*
5878 * Free all 'adv_sgblk_t' structures allocated for the request.
5879 */
5880 while ((sgblkp = reqp->sgblkp) != NULL) {
5881 /* Remove 'sgblkp' from the request list. */
5882 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005884 /* Add 'sgblkp' to the board free list. */
5885 sgblkp->next_sgblkp = boardp->adv_sgblkp;
5886 boardp->adv_sgblkp = sgblkp;
5887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005889 /*
5890 * Free the adv_req_t structure used with the command by adding
5891 * it back to the board free list.
5892 */
5893 reqp->next_reqp = boardp->adv_reqp;
5894 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005896 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005898 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899}
5900
5901/*
5902 * adv_async_callback() - Adv Library asynchronous event callback function.
5903 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005904static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005906 switch (code) {
5907 case ADV_ASYNC_SCSI_BUS_RESET_DET:
5908 /*
5909 * The firmware detected a SCSI Bus reset.
5910 */
5911 ASC_DBG(0,
5912 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
5913 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005915 case ADV_ASYNC_RDMA_FAILURE:
5916 /*
5917 * Handle RDMA failure by resetting the SCSI Bus and
5918 * possibly the chip if it is unresponsive. Log the error
5919 * with a unique code.
5920 */
5921 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
5922 AdvResetChipAndSB(adv_dvc_varp);
5923 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005925 case ADV_HOST_SCSI_BUS_RESET:
5926 /*
5927 * Host generated SCSI bus reset occurred.
5928 */
5929 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
5930 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005932 default:
5933 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
5934 break;
5935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936}
5937
5938/*
5939 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
5940 * to indicate a command is queued for the device.
5941 *
5942 * 'flag' may be either ASC_FRONT or ASC_BACK.
5943 *
5944 * 'REQPNEXT(reqp)' returns reqp's next pointer.
5945 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005946static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005948 int tid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005950 ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n",
5951 (ulong)ascq, (ulong)reqp, flag);
5952 ASC_ASSERT(reqp != NULL);
5953 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
5954 tid = REQPTID(reqp);
5955 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
5956 if (flag == ASC_FRONT) {
5957 reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
5958 ascq->q_first[tid] = reqp;
5959 /* If the queue was empty, set the last pointer. */
5960 if (ascq->q_last[tid] == NULL) {
5961 ascq->q_last[tid] = reqp;
5962 }
5963 } else { /* ASC_BACK */
5964 if (ascq->q_last[tid] != NULL) {
5965 ascq->q_last[tid]->host_scribble =
5966 (unsigned char *)reqp;
5967 }
5968 ascq->q_last[tid] = reqp;
5969 reqp->host_scribble = NULL;
5970 /* If the queue was empty, set the first pointer. */
5971 if (ascq->q_first[tid] == NULL) {
5972 ascq->q_first[tid] = reqp;
5973 }
5974 }
5975 /* The queue has at least one entry, set its bit. */
5976 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005978 /* Maintain request queue statistics. */
5979 ascq->q_tot_cnt[tid]++;
5980 ascq->q_cur_cnt[tid]++;
5981 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
5982 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
5983 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
5984 tid, ascq->q_max_cnt[tid]);
5985 }
5986 REQPTIME(reqp) = REQTIMESTAMP();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005988 ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp);
5989 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005990}
5991
5992/*
5993 * Return first queued 'REQP' on the specified queue for
5994 * the specified target device. Clear the 'tidmask' bit for
5995 * the device if no more commands are left queued for it.
5996 *
5997 * 'REQPNEXT(reqp)' returns reqp's next pointer.
5998 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005999static REQP asc_dequeue(asc_queue_t *ascq, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006001 REQP reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006003 ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
6004 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
6005 if ((reqp = ascq->q_first[tid]) != NULL) {
6006 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
6007 ascq->q_first[tid] = REQPNEXT(reqp);
6008 /* If the queue is empty, clear its bit and the last pointer. */
6009 if (ascq->q_first[tid] == NULL) {
6010 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
6011 ASC_ASSERT(ascq->q_last[tid] == reqp);
6012 ascq->q_last[tid] = NULL;
6013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006015 /* Maintain request queue statistics. */
6016 ascq->q_cur_cnt[tid]--;
6017 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
6018 REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006020 }
6021 ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp);
6022 return reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023}
6024
6025/*
6026 * Return a pointer to a singly linked list of all the requests queued
6027 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
6028 *
6029 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
6030 * the last request returned in the singly linked list.
6031 *
6032 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
6033 * then all queued requests are concatenated into one list and
6034 * returned.
6035 *
6036 * Note: If 'lastpp' is used to append a new list to the end of
6037 * an old list, only change the old list last pointer if '*lastpp'
6038 * (or the function return value) is not NULL, i.e. use a temporary
6039 * variable for 'lastpp' and check its value after the function return
6040 * before assigning it to the list last pointer.
6041 *
6042 * Unfortunately collecting queuing time statistics adds overhead to
6043 * the function that isn't inherent to the function's algorithm.
6044 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006045static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006047 REQP firstp, lastp;
6048 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006050 ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
6051 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006053 /*
6054 * If 'tid' is not ASC_TID_ALL, return requests only for
6055 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
6056 * requests for all tids.
6057 */
6058 if (tid != ASC_TID_ALL) {
6059 /* Return all requests for the specified 'tid'. */
6060 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
6061 /* List is empty; Set first and last return pointers to NULL. */
6062 firstp = lastp = NULL;
6063 } else {
6064 firstp = ascq->q_first[tid];
6065 lastp = ascq->q_last[tid];
6066 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
6067 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006069 {
6070 REQP reqp;
6071 ascq->q_cur_cnt[tid] = 0;
6072 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
6073 REQTIMESTAT("asc_dequeue_list", ascq,
6074 reqp, tid);
6075 }
6076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006078 }
6079 } else {
6080 /* Return all requests for all tids. */
6081 firstp = lastp = NULL;
6082 for (i = 0; i <= ADV_MAX_TID; i++) {
6083 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
6084 if (firstp == NULL) {
6085 firstp = ascq->q_first[i];
6086 lastp = ascq->q_last[i];
6087 } else {
6088 ASC_ASSERT(lastp != NULL);
6089 lastp->host_scribble =
6090 (unsigned char *)ascq->q_first[i];
6091 lastp = ascq->q_last[i];
6092 }
6093 ascq->q_first[i] = ascq->q_last[i] = NULL;
6094 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006096 ascq->q_cur_cnt[i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006098 }
6099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006101 {
6102 REQP reqp;
6103 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
6104 REQTIMESTAT("asc_dequeue_list", ascq, reqp,
6105 reqp->device->id);
6106 }
6107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006109 }
6110 if (lastpp) {
6111 *lastpp = lastp;
6112 }
6113 ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp);
6114 return firstp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115}
6116
6117/*
6118 * Remove the specified 'REQP' from the specified queue for
6119 * the specified target device. Clear the 'tidmask' bit for the
6120 * device if no more commands are left queued for it.
6121 *
6122 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
6123 *
6124 * Return ASC_TRUE if the command was found and removed,
6125 * otherwise return ASC_FALSE.
6126 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006127static int asc_rmqueue(asc_queue_t *ascq, REQP reqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006129 REQP currp, prevp;
6130 int tid;
6131 int ret = ASC_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006133 ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n",
6134 (ulong)ascq, (ulong)reqp);
6135 ASC_ASSERT(reqp != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006137 tid = REQPTID(reqp);
6138 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006140 /*
6141 * Handle the common case of 'reqp' being the first
6142 * entry on the queue.
6143 */
6144 if (reqp == ascq->q_first[tid]) {
6145 ret = ASC_TRUE;
6146 ascq->q_first[tid] = REQPNEXT(reqp);
6147 /* If the queue is now empty, clear its bit and the last pointer. */
6148 if (ascq->q_first[tid] == NULL) {
6149 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
6150 ASC_ASSERT(ascq->q_last[tid] == reqp);
6151 ascq->q_last[tid] = NULL;
6152 }
6153 } else if (ascq->q_first[tid] != NULL) {
6154 ASC_ASSERT(ascq->q_last[tid] != NULL);
6155 /*
6156 * Because the case of 'reqp' being the first entry has been
6157 * handled above and it is known the queue is not empty, if
6158 * 'reqp' is found on the queue it is guaranteed the queue will
6159 * not become empty and that 'q_first[tid]' will not be changed.
6160 *
6161 * Set 'prevp' to the first entry, 'currp' to the second entry,
6162 * and search for 'reqp'.
6163 */
6164 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
6165 currp; prevp = currp, currp = REQPNEXT(currp)) {
6166 if (currp == reqp) {
6167 ret = ASC_TRUE;
6168 prevp->host_scribble =
6169 (unsigned char *)REQPNEXT(currp);
6170 reqp->host_scribble = NULL;
6171 if (ascq->q_last[tid] == reqp) {
6172 ascq->q_last[tid] = prevp;
6173 }
6174 break;
6175 }
6176 }
6177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006179 /* Maintain request queue statistics. */
6180 if (ret == ASC_TRUE) {
6181 ascq->q_cur_cnt[tid]--;
6182 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
6183 }
6184 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006185#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006186 ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret);
6187 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006188}
6189
6190/*
6191 * Execute as many queued requests as possible for the specified queue.
6192 *
6193 * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd.
6194 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006195static void asc_execute_queue(asc_queue_t *ascq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006196{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006197 ADV_SCSI_BIT_ID_TYPE scan_tidmask;
6198 REQP reqp;
6199 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006201 ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq);
6202 /*
6203 * Execute queued commands for devices attached to
6204 * the current board in round-robin fashion.
6205 */
6206 scan_tidmask = ascq->q_tidmask;
6207 do {
6208 for (i = 0; i <= ADV_MAX_TID; i++) {
6209 if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
6210 if ((reqp = asc_dequeue(ascq, i)) == NULL) {
6211 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
6212 } else
6213 if (asc_execute_scsi_cmnd
6214 ((struct scsi_cmnd *)reqp)
6215 == ASC_BUSY) {
6216 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
6217 /*
6218 * The request returned ASC_BUSY. Enqueue at the front of
6219 * target's waiting list to maintain correct ordering.
6220 */
6221 asc_enqueue(ascq, reqp, ASC_FRONT);
6222 }
6223 }
6224 }
6225 } while (scan_tidmask);
6226 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006227}
6228
6229#ifdef CONFIG_PROC_FS
6230/*
6231 * asc_prt_board_devices()
6232 *
6233 * Print driver information for devices attached to the board.
6234 *
6235 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6236 * cf. asc_prt_line().
6237 *
6238 * Return the number of characters copied into 'cp'. No more than
6239 * 'cplen' characters will be copied to 'cp'.
6240 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006241static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006243 asc_board_t *boardp;
6244 int leftlen;
6245 int totlen;
6246 int len;
6247 int chip_scsi_id;
6248 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006250 boardp = ASC_BOARDP(shost);
6251 leftlen = cplen;
6252 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006254 len = asc_prt_line(cp, leftlen,
6255 "\nDevice Information for AdvanSys SCSI Host %d:\n",
6256 shost->host_no);
6257 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006259 if (ASC_NARROW_BOARD(boardp)) {
6260 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6261 } else {
6262 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006265 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
6266 ASC_PRT_NEXT();
6267 for (i = 0; i <= ADV_MAX_TID; i++) {
6268 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
6269 len = asc_prt_line(cp, leftlen, " %X,", i);
6270 ASC_PRT_NEXT();
6271 }
6272 }
6273 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
6274 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006276 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277}
6278
6279/*
6280 * Display Wide Board BIOS Information.
6281 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006282static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006283{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006284 asc_board_t *boardp;
6285 int leftlen;
6286 int totlen;
6287 int len;
6288 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006290 boardp = ASC_BOARDP(shost);
6291 leftlen = cplen;
6292 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006294 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
6295 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006297 /*
6298 * If the BIOS saved a valid signature, then fill in
6299 * the BIOS code segment base address.
6300 */
6301 if (boardp->bios_signature != 0x55AA) {
6302 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
6303 ASC_PRT_NEXT();
6304 len = asc_prt_line(cp, leftlen,
6305 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
6306 ASC_PRT_NEXT();
6307 len = asc_prt_line(cp, leftlen,
6308 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
6309 ASC_PRT_NEXT();
6310 } else {
6311 major = (boardp->bios_version >> 12) & 0xF;
6312 minor = (boardp->bios_version >> 8) & 0xF;
6313 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006315 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
6316 major, minor,
6317 letter >= 26 ? '?' : letter + 'A');
6318 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320 /*
6321 * Current available ROM BIOS release is 3.1I for UW
6322 * and 3.2I for U2W. This code doesn't differentiate
6323 * UW and U2W boards.
6324 */
6325 if (major < 3 || (major <= 3 && minor < 1) ||
6326 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
6327 len = asc_prt_line(cp, leftlen,
6328 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
6329 ASC_PRT_NEXT();
6330 len = asc_prt_line(cp, leftlen,
6331 "ftp://ftp.connectcom.net/pub\n");
6332 ASC_PRT_NEXT();
6333 }
6334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006336 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337}
6338
6339/*
6340 * Add serial number to information bar if signature AAh
6341 * is found in at bit 15-9 (7 bits) of word 1.
6342 *
6343 * Serial Number consists fo 12 alpha-numeric digits.
6344 *
6345 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
6346 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
6347 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
6348 * 5 - Product revision (A-J) Word0: " "
6349 *
6350 * Signature Word1: 15-9 (7 bits)
6351 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
6352 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
6353 *
6354 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
6355 *
6356 * Note 1: Only production cards will have a serial number.
6357 *
6358 * Note 2: Signature is most significant 7 bits (0xFE).
6359 *
6360 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
6361 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006362static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006363{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006364 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006366 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
6367 return ASC_FALSE;
6368 } else {
6369 /*
6370 * First word - 6 digits.
6371 */
6372 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006374 /* Product type - 1st digit. */
6375 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
6376 /* Product type is P=Prototype */
6377 *cp += 0x8;
6378 }
6379 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006381 /* Manufacturing location - 2nd digit. */
6382 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006383
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006384 /* Product ID - 3rd, 4th digits. */
6385 num = w & 0x3FF;
6386 *cp++ = '0' + (num / 100);
6387 num %= 100;
6388 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006389
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006390 /* Product revision - 5th digit. */
6391 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006392
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006393 /*
6394 * Second word
6395 */
6396 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006397
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006398 /*
6399 * Year - 6th digit.
6400 *
6401 * If bit 15 of third word is set, then the
6402 * last digit of the year is greater than 7.
6403 */
6404 if (serialnum[2] & 0x8000) {
6405 *cp++ = '8' + ((w & 0x1C0) >> 6);
6406 } else {
6407 *cp++ = '0' + ((w & 0x1C0) >> 6);
6408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006409
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006410 /* Week of year - 7th, 8th digits. */
6411 num = w & 0x003F;
6412 *cp++ = '0' + num / 10;
6413 num %= 10;
6414 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006415
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006416 /*
6417 * Third word
6418 */
6419 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006420
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006421 /* Serial number - 9th digit. */
6422 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006424 /* 10th, 11th, 12th digits. */
6425 num = w % 1000;
6426 *cp++ = '0' + num / 100;
6427 num %= 100;
6428 *cp++ = '0' + num / 10;
6429 num %= 10;
6430 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006432 *cp = '\0'; /* Null Terminate the string. */
6433 return ASC_TRUE;
6434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435}
6436
6437/*
6438 * asc_prt_asc_board_eeprom()
6439 *
6440 * Print board EEPROM configuration.
6441 *
6442 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6443 * cf. asc_prt_line().
6444 *
6445 * Return the number of characters copied into 'cp'. No more than
6446 * 'cplen' characters will be copied to 'cp'.
6447 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006448static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006450 asc_board_t *boardp;
6451 ASC_DVC_VAR *asc_dvc_varp;
6452 int leftlen;
6453 int totlen;
6454 int len;
6455 ASCEEP_CONFIG *ep;
6456 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006458 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07006459#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006460 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006462 boardp = ASC_BOARDP(shost);
6463 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6464 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006466 leftlen = cplen;
6467 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006468
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006469 len = asc_prt_line(cp, leftlen,
6470 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
6471 shost->host_no);
6472 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006473
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006474 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
6475 == ASC_TRUE) {
6476 len =
6477 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
6478 serialstr);
6479 ASC_PRT_NEXT();
6480 } else {
6481 if (ep->adapter_info[5] == 0xBB) {
6482 len = asc_prt_line(cp, leftlen,
6483 " Default Settings Used for EEPROM-less Adapter.\n");
6484 ASC_PRT_NEXT();
6485 } else {
6486 len = asc_prt_line(cp, leftlen,
6487 " Serial Number Signature Not Present.\n");
6488 ASC_PRT_NEXT();
6489 }
6490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006492 len = asc_prt_line(cp, leftlen,
6493 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6494 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
6495 ep->max_tag_qng);
6496 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006497
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006498 len = asc_prt_line(cp, leftlen,
6499 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
6500 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006501
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006502 len = asc_prt_line(cp, leftlen, " Target ID: ");
6503 ASC_PRT_NEXT();
6504 for (i = 0; i <= ASC_MAX_TID; i++) {
6505 len = asc_prt_line(cp, leftlen, " %d", i);
6506 ASC_PRT_NEXT();
6507 }
6508 len = asc_prt_line(cp, leftlen, "\n");
6509 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006510
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006511 len = asc_prt_line(cp, leftlen, " Disconnects: ");
6512 ASC_PRT_NEXT();
6513 for (i = 0; i <= ASC_MAX_TID; i++) {
6514 len = asc_prt_line(cp, leftlen, " %c",
6515 (ep->
6516 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6517 'N');
6518 ASC_PRT_NEXT();
6519 }
6520 len = asc_prt_line(cp, leftlen, "\n");
6521 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006523 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
6524 ASC_PRT_NEXT();
6525 for (i = 0; i <= ASC_MAX_TID; i++) {
6526 len = asc_prt_line(cp, leftlen, " %c",
6527 (ep->
6528 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6529 'N');
6530 ASC_PRT_NEXT();
6531 }
6532 len = asc_prt_line(cp, leftlen, "\n");
6533 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006535 len = asc_prt_line(cp, leftlen, " Start Motor: ");
6536 ASC_PRT_NEXT();
6537 for (i = 0; i <= ASC_MAX_TID; i++) {
6538 len = asc_prt_line(cp, leftlen, " %c",
6539 (ep->
6540 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6541 'N');
6542 ASC_PRT_NEXT();
6543 }
6544 len = asc_prt_line(cp, leftlen, "\n");
6545 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006546
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006547 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6548 ASC_PRT_NEXT();
6549 for (i = 0; i <= ASC_MAX_TID; i++) {
6550 len = asc_prt_line(cp, leftlen, " %c",
6551 (ep->
6552 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6553 'N');
6554 ASC_PRT_NEXT();
6555 }
6556 len = asc_prt_line(cp, leftlen, "\n");
6557 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006558
6559#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006560 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
6561 len = asc_prt_line(cp, leftlen,
6562 " Host ISA DMA speed: %d MB/S\n",
6563 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
6564 ASC_PRT_NEXT();
6565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006566#endif /* CONFIG_ISA */
6567
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006568 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006569}
6570
6571/*
6572 * asc_prt_adv_board_eeprom()
6573 *
6574 * Print board EEPROM configuration.
6575 *
6576 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6577 * cf. asc_prt_line().
6578 *
6579 * Return the number of characters copied into 'cp'. No more than
6580 * 'cplen' characters will be copied to 'cp'.
6581 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006582static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006583{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006584 asc_board_t *boardp;
6585 ADV_DVC_VAR *adv_dvc_varp;
6586 int leftlen;
6587 int totlen;
6588 int len;
6589 int i;
6590 char *termstr;
6591 uchar serialstr[13];
6592 ADVEEP_3550_CONFIG *ep_3550 = NULL;
6593 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
6594 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
6595 ushort word;
6596 ushort *wordp;
6597 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006598
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006599 boardp = ASC_BOARDP(shost);
6600 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6601 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6602 ep_3550 = &boardp->eep_config.adv_3550_eep;
6603 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6604 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
6605 } else {
6606 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
6607 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006608
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006609 leftlen = cplen;
6610 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006612 len = asc_prt_line(cp, leftlen,
6613 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
6614 shost->host_no);
6615 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006616
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006617 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6618 wordp = &ep_3550->serial_number_word1;
6619 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6620 wordp = &ep_38C0800->serial_number_word1;
6621 } else {
6622 wordp = &ep_38C1600->serial_number_word1;
6623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006624
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006625 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
6626 len =
6627 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
6628 serialstr);
6629 ASC_PRT_NEXT();
6630 } else {
6631 len = asc_prt_line(cp, leftlen,
6632 " Serial Number Signature Not Present.\n");
6633 ASC_PRT_NEXT();
6634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006636 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6637 len = asc_prt_line(cp, leftlen,
6638 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6639 ep_3550->adapter_scsi_id,
6640 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
6641 ASC_PRT_NEXT();
6642 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6643 len = asc_prt_line(cp, leftlen,
6644 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6645 ep_38C0800->adapter_scsi_id,
6646 ep_38C0800->max_host_qng,
6647 ep_38C0800->max_dvc_qng);
6648 ASC_PRT_NEXT();
6649 } else {
6650 len = asc_prt_line(cp, leftlen,
6651 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6652 ep_38C1600->adapter_scsi_id,
6653 ep_38C1600->max_host_qng,
6654 ep_38C1600->max_dvc_qng);
6655 ASC_PRT_NEXT();
6656 }
6657 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6658 word = ep_3550->termination;
6659 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6660 word = ep_38C0800->termination_lvd;
6661 } else {
6662 word = ep_38C1600->termination_lvd;
6663 }
6664 switch (word) {
6665 case 1:
6666 termstr = "Low Off/High Off";
6667 break;
6668 case 2:
6669 termstr = "Low Off/High On";
6670 break;
6671 case 3:
6672 termstr = "Low On/High On";
6673 break;
6674 default:
6675 case 0:
6676 termstr = "Automatic";
6677 break;
6678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006679
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006680 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6681 len = asc_prt_line(cp, leftlen,
6682 " termination: %u (%s), bios_ctrl: 0x%x\n",
6683 ep_3550->termination, termstr,
6684 ep_3550->bios_ctrl);
6685 ASC_PRT_NEXT();
6686 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6687 len = asc_prt_line(cp, leftlen,
6688 " termination: %u (%s), bios_ctrl: 0x%x\n",
6689 ep_38C0800->termination_lvd, termstr,
6690 ep_38C0800->bios_ctrl);
6691 ASC_PRT_NEXT();
6692 } else {
6693 len = asc_prt_line(cp, leftlen,
6694 " termination: %u (%s), bios_ctrl: 0x%x\n",
6695 ep_38C1600->termination_lvd, termstr,
6696 ep_38C1600->bios_ctrl);
6697 ASC_PRT_NEXT();
6698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006699
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006700 len = asc_prt_line(cp, leftlen, " Target ID: ");
6701 ASC_PRT_NEXT();
6702 for (i = 0; i <= ADV_MAX_TID; i++) {
6703 len = asc_prt_line(cp, leftlen, " %X", i);
6704 ASC_PRT_NEXT();
6705 }
6706 len = asc_prt_line(cp, leftlen, "\n");
6707 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006709 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6710 word = ep_3550->disc_enable;
6711 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6712 word = ep_38C0800->disc_enable;
6713 } else {
6714 word = ep_38C1600->disc_enable;
6715 }
6716 len = asc_prt_line(cp, leftlen, " Disconnects: ");
6717 ASC_PRT_NEXT();
6718 for (i = 0; i <= ADV_MAX_TID; i++) {
6719 len = asc_prt_line(cp, leftlen, " %c",
6720 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6721 ASC_PRT_NEXT();
6722 }
6723 len = asc_prt_line(cp, leftlen, "\n");
6724 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006725
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006726 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6727 word = ep_3550->tagqng_able;
6728 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6729 word = ep_38C0800->tagqng_able;
6730 } else {
6731 word = ep_38C1600->tagqng_able;
6732 }
6733 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
6734 ASC_PRT_NEXT();
6735 for (i = 0; i <= ADV_MAX_TID; i++) {
6736 len = asc_prt_line(cp, leftlen, " %c",
6737 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6738 ASC_PRT_NEXT();
6739 }
6740 len = asc_prt_line(cp, leftlen, "\n");
6741 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006742
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006743 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6744 word = ep_3550->start_motor;
6745 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6746 word = ep_38C0800->start_motor;
6747 } else {
6748 word = ep_38C1600->start_motor;
6749 }
6750 len = asc_prt_line(cp, leftlen, " Start Motor: ");
6751 ASC_PRT_NEXT();
6752 for (i = 0; i <= ADV_MAX_TID; i++) {
6753 len = asc_prt_line(cp, leftlen, " %c",
6754 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6755 ASC_PRT_NEXT();
6756 }
6757 len = asc_prt_line(cp, leftlen, "\n");
6758 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006759
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006760 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6761 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6762 ASC_PRT_NEXT();
6763 for (i = 0; i <= ADV_MAX_TID; i++) {
6764 len = asc_prt_line(cp, leftlen, " %c",
6765 (ep_3550->
6766 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
6767 'Y' : 'N');
6768 ASC_PRT_NEXT();
6769 }
6770 len = asc_prt_line(cp, leftlen, "\n");
6771 ASC_PRT_NEXT();
6772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006773
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006774 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6775 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
6776 ASC_PRT_NEXT();
6777 for (i = 0; i <= ADV_MAX_TID; i++) {
6778 len = asc_prt_line(cp, leftlen, " %c",
6779 (ep_3550->
6780 ultra_able & ADV_TID_TO_TIDMASK(i))
6781 ? 'Y' : 'N');
6782 ASC_PRT_NEXT();
6783 }
6784 len = asc_prt_line(cp, leftlen, "\n");
6785 ASC_PRT_NEXT();
6786 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006787
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006788 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6789 word = ep_3550->wdtr_able;
6790 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6791 word = ep_38C0800->wdtr_able;
6792 } else {
6793 word = ep_38C1600->wdtr_able;
6794 }
6795 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
6796 ASC_PRT_NEXT();
6797 for (i = 0; i <= ADV_MAX_TID; i++) {
6798 len = asc_prt_line(cp, leftlen, " %c",
6799 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6800 ASC_PRT_NEXT();
6801 }
6802 len = asc_prt_line(cp, leftlen, "\n");
6803 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006804
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006805 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
6806 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
6807 len = asc_prt_line(cp, leftlen,
6808 " Synchronous Transfer Speed (Mhz):\n ");
6809 ASC_PRT_NEXT();
6810 for (i = 0; i <= ADV_MAX_TID; i++) {
6811 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006813 if (i == 0) {
6814 sdtr_speed = adv_dvc_varp->sdtr_speed1;
6815 } else if (i == 4) {
6816 sdtr_speed = adv_dvc_varp->sdtr_speed2;
6817 } else if (i == 8) {
6818 sdtr_speed = adv_dvc_varp->sdtr_speed3;
6819 } else if (i == 12) {
6820 sdtr_speed = adv_dvc_varp->sdtr_speed4;
6821 }
6822 switch (sdtr_speed & ADV_MAX_TID) {
6823 case 0:
6824 speed_str = "Off";
6825 break;
6826 case 1:
6827 speed_str = " 5";
6828 break;
6829 case 2:
6830 speed_str = " 10";
6831 break;
6832 case 3:
6833 speed_str = " 20";
6834 break;
6835 case 4:
6836 speed_str = " 40";
6837 break;
6838 case 5:
6839 speed_str = " 80";
6840 break;
6841 default:
6842 speed_str = "Unk";
6843 break;
6844 }
6845 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
6846 ASC_PRT_NEXT();
6847 if (i == 7) {
6848 len = asc_prt_line(cp, leftlen, "\n ");
6849 ASC_PRT_NEXT();
6850 }
6851 sdtr_speed >>= 4;
6852 }
6853 len = asc_prt_line(cp, leftlen, "\n");
6854 ASC_PRT_NEXT();
6855 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006856
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006857 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006858}
6859
6860/*
6861 * asc_prt_driver_conf()
6862 *
6863 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6864 * cf. asc_prt_line().
6865 *
6866 * Return the number of characters copied into 'cp'. No more than
6867 * 'cplen' characters will be copied to 'cp'.
6868 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006869static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006870{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006871 asc_board_t *boardp;
6872 int leftlen;
6873 int totlen;
6874 int len;
6875 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006877 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006879 leftlen = cplen;
6880 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006882 len = asc_prt_line(cp, leftlen,
6883 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
6884 shost->host_no);
6885 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006887 len = asc_prt_line(cp, leftlen,
6888 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
6889 shost->host_busy, shost->last_reset, shost->max_id,
6890 shost->max_lun, shost->max_channel);
6891 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006892
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006893 len = asc_prt_line(cp, leftlen,
6894 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
6895 shost->unique_id, shost->can_queue, shost->this_id,
6896 shost->sg_tablesize, shost->cmd_per_lun);
6897 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006899 len = asc_prt_line(cp, leftlen,
6900 " unchecked_isa_dma %d, use_clustering %d\n",
6901 shost->unchecked_isa_dma, shost->use_clustering);
6902 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006903
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006904 len = asc_prt_line(cp, leftlen,
6905 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
6906 boardp->flags, boardp->last_reset, jiffies,
6907 boardp->asc_n_io_port);
6908 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006910 /* 'shost->n_io_port' may be truncated because it is only one byte. */
6911 len = asc_prt_line(cp, leftlen,
6912 " io_port 0x%x, n_io_port 0x%x\n",
6913 shost->io_port, shost->n_io_port);
6914 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006916 if (ASC_NARROW_BOARD(boardp)) {
6917 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6918 } else {
6919 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006922 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006923}
6924
6925/*
6926 * asc_prt_asc_board_info()
6927 *
6928 * Print dynamic board configuration information.
6929 *
6930 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6931 * cf. asc_prt_line().
6932 *
6933 * Return the number of characters copied into 'cp'. No more than
6934 * 'cplen' characters will be copied to 'cp'.
6935 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006936static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006937{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006938 asc_board_t *boardp;
6939 int chip_scsi_id;
6940 int leftlen;
6941 int totlen;
6942 int len;
6943 ASC_DVC_VAR *v;
6944 ASC_DVC_CFG *c;
6945 int i;
6946 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006948 boardp = ASC_BOARDP(shost);
6949 v = &boardp->dvc_var.asc_dvc_var;
6950 c = &boardp->dvc_cfg.asc_dvc_cfg;
6951 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006953 leftlen = cplen;
6954 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006955
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006956 len = asc_prt_line(cp, leftlen,
6957 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
6958 shost->host_no);
6959 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006960
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006961 len = asc_prt_line(cp, leftlen,
6962 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
6963 c->chip_version, c->lib_version, c->lib_serial_no,
6964 c->mcode_date);
6965 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006967 len = asc_prt_line(cp, leftlen,
6968 " mcode_version 0x%x, err_code %u\n",
6969 c->mcode_version, v->err_code);
6970 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006972 /* Current number of commands waiting for the host. */
6973 len = asc_prt_line(cp, leftlen,
6974 " Total Command Pending: %d\n", v->cur_total_qng);
6975 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006977 len = asc_prt_line(cp, leftlen, " Command Queuing:");
6978 ASC_PRT_NEXT();
6979 for (i = 0; i <= ASC_MAX_TID; i++) {
6980 if ((chip_scsi_id == i) ||
6981 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6982 continue;
6983 }
6984 len = asc_prt_line(cp, leftlen, " %X:%c",
6985 i,
6986 (v->
6987 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
6988 'Y' : 'N');
6989 ASC_PRT_NEXT();
6990 }
6991 len = asc_prt_line(cp, leftlen, "\n");
6992 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006994 /* Current number of commands waiting for a device. */
6995 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
6996 ASC_PRT_NEXT();
6997 for (i = 0; i <= ASC_MAX_TID; i++) {
6998 if ((chip_scsi_id == i) ||
6999 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7000 continue;
7001 }
7002 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
7003 ASC_PRT_NEXT();
7004 }
7005 len = asc_prt_line(cp, leftlen, "\n");
7006 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007008 /* Current limit on number of commands that can be sent to a device. */
7009 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
7010 ASC_PRT_NEXT();
7011 for (i = 0; i <= ASC_MAX_TID; i++) {
7012 if ((chip_scsi_id == i) ||
7013 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7014 continue;
7015 }
7016 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
7017 ASC_PRT_NEXT();
7018 }
7019 len = asc_prt_line(cp, leftlen, "\n");
7020 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007021
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007022 /* Indicate whether the device has returned queue full status. */
7023 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
7024 ASC_PRT_NEXT();
7025 for (i = 0; i <= ASC_MAX_TID; i++) {
7026 if ((chip_scsi_id == i) ||
7027 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7028 continue;
7029 }
7030 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
7031 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
7032 i, boardp->queue_full_cnt[i]);
7033 } else {
7034 len = asc_prt_line(cp, leftlen, " %X:N", i);
7035 }
7036 ASC_PRT_NEXT();
7037 }
7038 len = asc_prt_line(cp, leftlen, "\n");
7039 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007040
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007041 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
7042 ASC_PRT_NEXT();
7043 for (i = 0; i <= ASC_MAX_TID; i++) {
7044 if ((chip_scsi_id == i) ||
7045 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7046 continue;
7047 }
7048 len = asc_prt_line(cp, leftlen, " %X:%c",
7049 i,
7050 (v->
7051 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7052 'N');
7053 ASC_PRT_NEXT();
7054 }
7055 len = asc_prt_line(cp, leftlen, "\n");
7056 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007057
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007058 for (i = 0; i <= ASC_MAX_TID; i++) {
7059 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007061 if ((chip_scsi_id == i) ||
7062 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
7063 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
7064 continue;
7065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007067 len = asc_prt_line(cp, leftlen, " %X:", i);
7068 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007070 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
7071 len = asc_prt_line(cp, leftlen, " Asynchronous");
7072 ASC_PRT_NEXT();
7073 } else {
7074 syn_period_ix =
7075 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
7076 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007077
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007078 len = asc_prt_line(cp, leftlen,
7079 " Transfer Period Factor: %d (%d.%d Mhz),",
7080 v->sdtr_period_tbl[syn_period_ix],
7081 250 /
7082 v->sdtr_period_tbl[syn_period_ix],
7083 ASC_TENTHS(250,
7084 v->
7085 sdtr_period_tbl
7086 [syn_period_ix]));
7087 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007089 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
7090 boardp->
7091 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
7092 ASC_PRT_NEXT();
7093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007095 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7096 len = asc_prt_line(cp, leftlen, "*\n");
7097 renegotiate = 1;
7098 } else {
7099 len = asc_prt_line(cp, leftlen, "\n");
7100 }
7101 ASC_PRT_NEXT();
7102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007104 if (renegotiate) {
7105 len = asc_prt_line(cp, leftlen,
7106 " * = Re-negotiation pending before next command.\n");
7107 ASC_PRT_NEXT();
7108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007109
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007110 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111}
7112
7113/*
7114 * asc_prt_adv_board_info()
7115 *
7116 * Print dynamic board configuration information.
7117 *
7118 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7119 * cf. asc_prt_line().
7120 *
7121 * Return the number of characters copied into 'cp'. No more than
7122 * 'cplen' characters will be copied to 'cp'.
7123 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007124static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007125{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007126 asc_board_t *boardp;
7127 int leftlen;
7128 int totlen;
7129 int len;
7130 int i;
7131 ADV_DVC_VAR *v;
7132 ADV_DVC_CFG *c;
7133 AdvPortAddr iop_base;
7134 ushort chip_scsi_id;
7135 ushort lramword;
7136 uchar lrambyte;
7137 ushort tagqng_able;
7138 ushort sdtr_able, wdtr_able;
7139 ushort wdtr_done, sdtr_done;
7140 ushort period = 0;
7141 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007143 boardp = ASC_BOARDP(shost);
7144 v = &boardp->dvc_var.adv_dvc_var;
7145 c = &boardp->dvc_cfg.adv_dvc_cfg;
7146 iop_base = v->iop_base;
7147 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007149 leftlen = cplen;
7150 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007151
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007152 len = asc_prt_line(cp, leftlen,
7153 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
7154 shost->host_no);
7155 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007156
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007157 len = asc_prt_line(cp, leftlen,
7158 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
7159 v->iop_base,
7160 AdvReadWordRegister(iop_base,
7161 IOPW_SCSI_CFG1) & CABLE_DETECT,
7162 v->err_code);
7163 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007164
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007165 len = asc_prt_line(cp, leftlen,
7166 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
7167 c->chip_version, c->lib_version, c->mcode_date,
7168 c->mcode_version);
7169 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007171 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7172 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
7173 ASC_PRT_NEXT();
7174 for (i = 0; i <= ADV_MAX_TID; i++) {
7175 if ((chip_scsi_id == i) ||
7176 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7177 continue;
7178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007180 len = asc_prt_line(cp, leftlen, " %X:%c",
7181 i,
7182 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7183 'N');
7184 ASC_PRT_NEXT();
7185 }
7186 len = asc_prt_line(cp, leftlen, "\n");
7187 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007189 len = asc_prt_line(cp, leftlen, " Queue Limit:");
7190 ASC_PRT_NEXT();
7191 for (i = 0; i <= ADV_MAX_TID; i++) {
7192 if ((chip_scsi_id == i) ||
7193 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7194 continue;
7195 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007196
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007197 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
7198 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007200 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
7201 ASC_PRT_NEXT();
7202 }
7203 len = asc_prt_line(cp, leftlen, "\n");
7204 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007205
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007206 len = asc_prt_line(cp, leftlen, " Command Pending:");
7207 ASC_PRT_NEXT();
7208 for (i = 0; i <= ADV_MAX_TID; i++) {
7209 if ((chip_scsi_id == i) ||
7210 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7211 continue;
7212 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007213
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007214 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
7215 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007216
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007217 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
7218 ASC_PRT_NEXT();
7219 }
7220 len = asc_prt_line(cp, leftlen, "\n");
7221 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007222
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007223 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7224 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
7225 ASC_PRT_NEXT();
7226 for (i = 0; i <= ADV_MAX_TID; i++) {
7227 if ((chip_scsi_id == i) ||
7228 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7229 continue;
7230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007231
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007232 len = asc_prt_line(cp, leftlen, " %X:%c",
7233 i,
7234 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7235 'N');
7236 ASC_PRT_NEXT();
7237 }
7238 len = asc_prt_line(cp, leftlen, "\n");
7239 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007240
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007241 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
7242 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
7243 ASC_PRT_NEXT();
7244 for (i = 0; i <= ADV_MAX_TID; i++) {
7245 if ((chip_scsi_id == i) ||
7246 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7247 continue;
7248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007249
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007250 AdvReadWordLram(iop_base,
7251 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
7252 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007254 len = asc_prt_line(cp, leftlen, " %X:%d",
7255 i, (lramword & 0x8000) ? 16 : 8);
7256 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007258 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
7259 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7260 len = asc_prt_line(cp, leftlen, "*");
7261 ASC_PRT_NEXT();
7262 renegotiate = 1;
7263 }
7264 }
7265 len = asc_prt_line(cp, leftlen, "\n");
7266 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007267
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007268 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7269 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
7270 ASC_PRT_NEXT();
7271 for (i = 0; i <= ADV_MAX_TID; i++) {
7272 if ((chip_scsi_id == i) ||
7273 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7274 continue;
7275 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007277 len = asc_prt_line(cp, leftlen, " %X:%c",
7278 i,
7279 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7280 'N');
7281 ASC_PRT_NEXT();
7282 }
7283 len = asc_prt_line(cp, leftlen, "\n");
7284 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007286 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
7287 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007289 AdvReadWordLram(iop_base,
7290 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
7291 lramword);
7292 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007294 if ((chip_scsi_id == i) ||
7295 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
7296 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
7297 continue;
7298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007300 len = asc_prt_line(cp, leftlen, " %X:", i);
7301 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007303 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
7304 len = asc_prt_line(cp, leftlen, " Asynchronous");
7305 ASC_PRT_NEXT();
7306 } else {
7307 len =
7308 asc_prt_line(cp, leftlen,
7309 " Transfer Period Factor: ");
7310 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007311
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007312 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
7313 len =
7314 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
7315 ASC_PRT_NEXT();
7316 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
7317 len =
7318 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
7319 ASC_PRT_NEXT();
7320 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007321
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007322 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007323
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007324 if (period == 0) { /* Should never happen. */
7325 len =
7326 asc_prt_line(cp, leftlen,
7327 "%d (? Mhz), ");
7328 ASC_PRT_NEXT();
7329 } else {
7330 len = asc_prt_line(cp, leftlen,
7331 "%d (%d.%d Mhz),",
7332 period, 250 / period,
7333 ASC_TENTHS(250,
7334 period));
7335 ASC_PRT_NEXT();
7336 }
7337 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007338
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007339 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
7340 lramword & 0x1F);
7341 ASC_PRT_NEXT();
7342 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007343
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007344 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7345 len = asc_prt_line(cp, leftlen, "*\n");
7346 renegotiate = 1;
7347 } else {
7348 len = asc_prt_line(cp, leftlen, "\n");
7349 }
7350 ASC_PRT_NEXT();
7351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007352
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007353 if (renegotiate) {
7354 len = asc_prt_line(cp, leftlen,
7355 " * = Re-negotiation pending before next command.\n");
7356 ASC_PRT_NEXT();
7357 }
7358
7359 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007360}
7361
7362/*
7363 * asc_proc_copy()
7364 *
7365 * Copy proc information to a read buffer taking into account the current
7366 * read offset in the file and the remaining space in the read buffer.
7367 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007368static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07007369asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007370 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007374 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
7375 (unsigned)offset, (unsigned)advoffset, cplen);
7376 if (offset <= advoffset) {
7377 /* Read offset below current offset, copy everything. */
7378 cnt = min(cplen, leftlen);
7379 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
7380 (ulong)curbuf, (ulong)cp, cnt);
7381 memcpy(curbuf, cp, cnt);
7382 } else if (offset < advoffset + cplen) {
7383 /* Read offset within current range, partial copy. */
7384 cnt = (advoffset + cplen) - offset;
7385 cp = (cp + cplen) - cnt;
7386 cnt = min(cnt, leftlen);
7387 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
7388 (ulong)curbuf, (ulong)cp, cnt);
7389 memcpy(curbuf, cp, cnt);
7390 }
7391 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007392}
7393
7394/*
7395 * asc_prt_line()
7396 *
7397 * If 'cp' is NULL print to the console, otherwise print to a buffer.
7398 *
7399 * Return 0 if printing to the console, otherwise return the number of
7400 * bytes written to the buffer.
7401 *
7402 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
7403 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
7404 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007405static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007406{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007407 va_list args;
7408 int ret;
7409 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007411 va_start(args, fmt);
7412 ret = vsprintf(s, fmt, args);
7413 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
7414 if (buf == NULL) {
7415 (void)printk(s);
7416 ret = 0;
7417 } else {
7418 ret = min(buflen, ret);
7419 memcpy(buf, s, ret);
7420 }
7421 va_end(args);
7422 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007423}
7424#endif /* CONFIG_PROC_FS */
7425
Linus Torvalds1da177e2005-04-16 15:20:36 -07007426/*
7427 * --- Functions Required by the Asc Library
7428 */
7429
7430/*
7431 * Delay for 'n' milliseconds. Don't use the 'jiffies'
7432 * global variable which is incremented once every 5 ms
7433 * from a timer interrupt, because this function may be
7434 * called when interrupts are disabled.
7435 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007436static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007437{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007438 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
7439 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007440}
7441
7442/*
7443 * Currently and inline noop but leave as a placeholder.
7444 * Leave DvcEnterCritical() as a noop placeholder.
7445 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007446static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007447{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007448 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007449}
7450
7451/*
7452 * Critical sections are all protected by the board spinlock.
7453 * Leave DvcLeaveCritical() as a noop placeholder.
7454 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007455static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007456{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007457 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007458}
7459
7460/*
7461 * void
7462 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
7463 *
7464 * Calling/Exit State:
7465 * none
7466 *
7467 * Description:
7468 * Output an ASC_SCSI_Q structure to the chip
7469 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007470static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07007471DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
7472{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007473 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007474
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007475 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
7476 AscSetChipLramAddr(iop_base, s_addr);
7477 for (i = 0; i < 2 * words; i += 2) {
7478 if (i == 4 || i == 20) {
7479 continue;
7480 }
7481 outpw(iop_base + IOP_RAM_DATA,
7482 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
7483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007484}
7485
7486/*
7487 * void
7488 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
7489 *
7490 * Calling/Exit State:
7491 * none
7492 *
7493 * Description:
7494 * Input an ASC_QDONE_INFO structure from the chip
7495 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007496static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07007497DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
7498{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007499 int i;
7500 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007501
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007502 AscSetChipLramAddr(iop_base, s_addr);
7503 for (i = 0; i < 2 * words; i += 2) {
7504 if (i == 10) {
7505 continue;
7506 }
7507 word = inpw(iop_base + IOP_RAM_DATA);
7508 inbuf[i] = word & 0xff;
7509 inbuf[i + 1] = (word >> 8) & 0xff;
7510 }
7511 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007512}
7513
7514/*
7515 * Read a PCI configuration byte.
7516 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007517static uchar __init DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007518{
7519#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007520 uchar byte_data;
7521 pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
7522 return byte_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523#else /* !defined(CONFIG_PCI) */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007524 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007525#endif /* !defined(CONFIG_PCI) */
7526}
7527
7528/*
7529 * Write a PCI configuration byte.
7530 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007531static void __init
7532DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007533{
7534#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007535 pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536#endif /* CONFIG_PCI */
7537}
7538
7539/*
7540 * Return the BIOS address of the adapter at the specified
7541 * I/O port and with the specified bus type.
7542 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007543static ushort __init AscGetChipBiosAddress(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007545 ushort cfg_lsw;
7546 ushort bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007548 /*
7549 * The PCI BIOS is re-located by the motherboard BIOS. Because
7550 * of this the driver can not determine where a PCI BIOS is
7551 * loaded and executes.
7552 */
7553 if (bus_type & ASC_IS_PCI) {
7554 return (0);
7555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007556#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007557 if ((bus_type & ASC_IS_EISA) != 0) {
7558 cfg_lsw = AscGetEisaChipCfg(iop_base);
7559 cfg_lsw &= 0x000F;
7560 bios_addr = (ushort)(ASC_BIOS_MIN_ADDR +
7561 (cfg_lsw * ASC_BIOS_BANK_SIZE));
7562 return (bios_addr);
7563 } /* if */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007564#endif /* CONFIG_ISA */
7565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007566 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007567
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007568 /*
7569 * ISA PnP uses the top bit as the 32K BIOS flag
7570 */
7571 if (bus_type == ASC_IS_ISAPNP) {
7572 cfg_lsw &= 0x7FFF;
7573 }
7574 /* if */
7575 bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
7576 ASC_BIOS_MIN_ADDR);
7577 return (bios_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007578}
7579
Linus Torvalds1da177e2005-04-16 15:20:36 -07007580/*
7581 * --- Functions Required by the Adv Library
7582 */
7583
7584/*
7585 * DvcGetPhyAddr()
7586 *
7587 * Return the physical address of 'vaddr' and set '*lenp' to the
7588 * number of physically contiguous bytes that follow 'vaddr'.
7589 * 'flag' indicates the type of structure whose physical address
7590 * is being translated.
7591 *
7592 * Note: Because Linux currently doesn't page the kernel and all
7593 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
7594 */
7595ADV_PADDR
7596DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007597 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007598{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007599 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007600
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007601 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007602
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007603 ASC_DBG4(4,
7604 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
7605 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
7606 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007607
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007608 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007609}
7610
7611/*
7612 * Read a PCI configuration byte.
7613 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007614static uchar __init DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007615{
7616#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007617 uchar byte_data;
7618 pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
7619 return byte_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007620#else /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007621 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007622#endif /* CONFIG_PCI */
7623}
7624
7625/*
7626 * Write a PCI configuration byte.
7627 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007628static void __init
7629DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007630{
7631#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007632 pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007633#else /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007634 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007635#endif /* CONFIG_PCI */
7636}
7637
7638/*
7639 * --- Tracing and Debugging Functions
7640 */
7641
7642#ifdef ADVANSYS_STATS
7643#ifdef CONFIG_PROC_FS
7644/*
7645 * asc_prt_board_stats()
7646 *
7647 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7648 * cf. asc_prt_line().
7649 *
7650 * Return the number of characters copied into 'cp'. No more than
7651 * 'cplen' characters will be copied to 'cp'.
7652 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007653static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007654{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007655 int leftlen;
7656 int totlen;
7657 int len;
7658 struct asc_stats *s;
7659 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007660
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007661 leftlen = cplen;
7662 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007663
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007664 boardp = ASC_BOARDP(shost);
7665 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007667 len = asc_prt_line(cp, leftlen,
7668 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
7669 shost->host_no);
7670 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007672 len = asc_prt_line(cp, leftlen,
7673 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
7674 s->queuecommand, s->reset, s->biosparam,
7675 s->interrupt);
7676 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007677
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007678 len = asc_prt_line(cp, leftlen,
7679 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
7680 s->callback, s->done, s->build_error,
7681 s->adv_build_noreq, s->adv_build_nosg);
7682 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007683
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007684 len = asc_prt_line(cp, leftlen,
7685 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
7686 s->exe_noerror, s->exe_busy, s->exe_error,
7687 s->exe_unknown);
7688 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007689
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007690 /*
7691 * Display data transfer statistics.
7692 */
7693 if (s->cont_cnt > 0) {
7694 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
7695 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007697 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
7698 s->cont_xfer / 2,
7699 ASC_TENTHS(s->cont_xfer, 2));
7700 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007702 /* Contiguous transfer average size */
7703 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
7704 (s->cont_xfer / 2) / s->cont_cnt,
7705 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
7706 ASC_PRT_NEXT();
7707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007708
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007709 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007711 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
7712 s->sg_cnt, s->sg_elem);
7713 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007714
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007715 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
7716 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
7717 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007719 /* Scatter gather transfer statistics */
7720 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
7721 s->sg_elem / s->sg_cnt,
7722 ASC_TENTHS(s->sg_elem, s->sg_cnt));
7723 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007724
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007725 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
7726 (s->sg_xfer / 2) / s->sg_elem,
7727 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
7728 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007729
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007730 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
7731 (s->sg_xfer / 2) / s->sg_cnt,
7732 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
7733 ASC_PRT_NEXT();
7734 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007735
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007736 /*
7737 * Display request queuing statistics.
7738 */
7739 len = asc_prt_line(cp, leftlen,
7740 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
7741 HZ);
7742 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007744 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007745}
7746
7747/*
7748 * asc_prt_target_stats()
7749 *
7750 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7751 * cf. asc_prt_line().
7752 *
7753 * This is separated from asc_prt_board_stats because a full set
7754 * of targets will overflow ASC_PRTBUF_SIZE.
7755 *
7756 * Return the number of characters copied into 'cp'. No more than
7757 * 'cplen' characters will be copied to 'cp'.
7758 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007759static int
7760asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007761{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007762 int leftlen;
7763 int totlen;
7764 int len;
7765 struct asc_stats *s;
7766 ushort chip_scsi_id;
7767 asc_board_t *boardp;
7768 asc_queue_t *active;
7769 asc_queue_t *waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007770
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007771 leftlen = cplen;
7772 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007773
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007774 boardp = ASC_BOARDP(shost);
7775 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007776
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007777 active = &ASC_BOARDP(shost)->active;
7778 waiting = &ASC_BOARDP(shost)->waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007779
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007780 if (ASC_NARROW_BOARD(boardp)) {
7781 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
7782 } else {
7783 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
7784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007785
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007786 if ((chip_scsi_id == tgt_id) ||
7787 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) {
7788 return 0;
7789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007790
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007791 do {
7792 if (active->q_tot_cnt[tgt_id] > 0
7793 || waiting->q_tot_cnt[tgt_id] > 0) {
7794 len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id);
7795 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007796
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007797 len = asc_prt_line(cp, leftlen,
7798 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
7799 active->q_cur_cnt[tgt_id],
7800 active->q_max_cnt[tgt_id],
7801 active->q_tot_cnt[tgt_id],
7802 active->q_min_tim[tgt_id],
7803 active->q_max_tim[tgt_id],
7804 (active->q_tot_cnt[tgt_id] ==
7805 0) ? 0 : (active->
7806 q_tot_tim[tgt_id] /
7807 active->
7808 q_tot_cnt[tgt_id]),
7809 (active->q_tot_cnt[tgt_id] ==
7810 0) ? 0 : ASC_TENTHS(active->
7811 q_tot_tim
7812 [tgt_id],
7813 active->
7814 q_tot_cnt
7815 [tgt_id]));
7816 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007817
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007818 len = asc_prt_line(cp, leftlen,
7819 " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
7820 waiting->q_cur_cnt[tgt_id],
7821 waiting->q_max_cnt[tgt_id],
7822 waiting->q_tot_cnt[tgt_id],
7823 waiting->q_min_tim[tgt_id],
7824 waiting->q_max_tim[tgt_id],
7825 (waiting->q_tot_cnt[tgt_id] ==
7826 0) ? 0 : (waiting->
7827 q_tot_tim[tgt_id] /
7828 waiting->
7829 q_tot_cnt[tgt_id]),
7830 (waiting->q_tot_cnt[tgt_id] ==
7831 0) ? 0 : ASC_TENTHS(waiting->
7832 q_tot_tim
7833 [tgt_id],
7834 waiting->
7835 q_tot_cnt
7836 [tgt_id]));
7837 ASC_PRT_NEXT();
7838 }
7839 } while (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007840
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007841 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007842}
7843#endif /* CONFIG_PROC_FS */
7844#endif /* ADVANSYS_STATS */
7845
7846#ifdef ADVANSYS_DEBUG
7847/*
7848 * asc_prt_scsi_host()
7849 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007850static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007851{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007852 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007853
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007854 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007855
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007856 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
7857 printk(" host_busy %u, host_no %d, last_reset %d,\n",
7858 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007860 printk(" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n",
7861 (ulong)s->base, (ulong)s->io_port, s->n_io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007863 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
7864 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007866 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
7867 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007869 if (ASC_NARROW_BOARD(boardp)) {
7870 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
7871 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
7872 } else {
7873 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
7874 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
7875 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007876}
7877
7878/*
7879 * asc_prt_scsi_cmnd()
7880 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007881static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007882{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007883 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007884
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007885 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
7886 (ulong)s->device->host, (ulong)s->device, s->device->id,
7887 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007889 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007890
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007891 printk("sc_data_direction %u, resid %d\n",
7892 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007893
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007894 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007896 printk(" serial_number 0x%x, retries %d, allowed %d\n",
7897 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007899 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007900
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007901 printk
7902 (" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
7903 (ulong)s->scsi_done, (ulong)s->done, (ulong)s->host_scribble,
7904 s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007906 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007907}
7908
7909/*
7910 * asc_prt_asc_dvc_var()
7911 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007912static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007913{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007914 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007916 printk
7917 (" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n",
7918 h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007920 printk
7921 (" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n",
7922 h->bus_type, (ulong)h->isr_callback, (ulong)h->exe_callback,
7923 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007925 printk
7926 (" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n",
7927 (unsigned)h->sdtr_done, (unsigned)h->use_tagged_qng,
7928 (unsigned)h->unit_not_ready, (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007930 printk
7931 (" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n",
7932 (unsigned)h->queue_full_or_busy, (unsigned)h->start_motor,
7933 (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007935 printk
7936 (" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n",
7937 (unsigned)h->is_in_int, (unsigned)h->max_total_qng,
7938 (unsigned)h->cur_total_qng, (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007940 printk
7941 (" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n",
7942 (unsigned)h->last_q_shortage, (unsigned)h->init_state,
7943 (unsigned)h->no_scam, (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007944
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007945 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007946}
7947
7948/*
7949 * asc_prt_asc_dvc_cfg()
7950 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007951static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007952{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007953 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007954
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007955 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
7956 h->can_tagged_qng, h->cmd_qng_enabled);
7957 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
7958 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007960 printk
7961 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
7962 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
7963 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007964
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007965 printk
7966 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
7967 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
7968 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007970 printk(" mcode_version %d, overrun_buf 0x%lx\n",
7971 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007972}
7973
7974/*
7975 * asc_prt_asc_scsi_q()
7976 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007977static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007978{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007979 ASC_SG_HEAD *sgp;
7980 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007982 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007983
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007984 printk
7985 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
7986 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
7987 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007989 printk
7990 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
7991 (ulong)le32_to_cpu(q->q1.data_addr),
7992 (ulong)le32_to_cpu(q->q1.data_cnt),
7993 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007995 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
7996 (ulong)q->cdbptr, q->q2.cdb_len,
7997 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007999 if (q->sg_head) {
8000 sgp = q->sg_head;
8001 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
8002 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
8003 sgp->queue_cnt);
8004 for (i = 0; i < sgp->entry_cnt; i++) {
8005 printk(" [%u]: addr 0x%lx, bytes %lu\n",
8006 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
8007 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
8008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008009
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008011}
8012
8013/*
8014 * asc_prt_asc_qdone_info()
8015 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008016static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008017{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008018 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
8019 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
8020 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
8021 q->d2.tag_code);
8022 printk
8023 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
8024 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008025}
8026
8027/*
8028 * asc_prt_adv_dvc_var()
8029 *
8030 * Display an ADV_DVC_VAR structure.
8031 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008032static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008033{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008034 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008035
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008036 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
8037 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008039 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
8040 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
8041 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008043 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
8044 (unsigned)h->start_motor,
8045 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008047 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
8048 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
8049 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008050
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008051 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
8052 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008053
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008054 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
8055 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008057 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
8058 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008059}
8060
8061/*
8062 * asc_prt_adv_dvc_cfg()
8063 *
8064 * Display an ADV_DVC_CFG structure.
8065 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008066static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008067{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008068 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008070 printk(" disc_enable 0x%x, termination 0x%x\n",
8071 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008073 printk(" chip_version 0x%x, mcode_date 0x%x\n",
8074 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008076 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
8077 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008079 printk(" control_flag 0x%x, pci_slot_info 0x%x\n",
8080 h->control_flag, h->pci_slot_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008081}
8082
8083/*
8084 * asc_prt_adv_scsi_req_q()
8085 *
8086 * Display an ADV_SCSI_REQ_Q structure.
8087 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008088static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008089{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008090 int sg_blk_cnt;
8091 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008092
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008093 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008095 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
8096 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008097
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008098 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
8099 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008101 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
8102 (ulong)le32_to_cpu(q->data_cnt),
8103 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008105 printk
8106 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
8107 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008109 printk(" sg_working_ix 0x%x, target_cmd %u\n",
8110 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008112 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
8113 (ulong)le32_to_cpu(q->scsiq_rptr),
8114 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008115
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008116 /* Display the request's ADV_SG_BLOCK structures. */
8117 if (q->sg_list_ptr != NULL) {
8118 sg_blk_cnt = 0;
8119 while (1) {
8120 /*
8121 * 'sg_ptr' is a physical address. Convert it to a virtual
8122 * address by indexing 'sg_blk_cnt' into the virtual address
8123 * array 'sg_list_ptr'.
8124 *
8125 * XXX - Assumes all SG physical blocks are virtually contiguous.
8126 */
8127 sg_ptr =
8128 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
8129 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
8130 if (sg_ptr->sg_ptr == 0) {
8131 break;
8132 }
8133 sg_blk_cnt++;
8134 }
8135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008136}
8137
8138/*
8139 * asc_prt_adv_sgblock()
8140 *
8141 * Display an ADV_SG_BLOCK structure.
8142 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008143static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008144{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008145 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008146
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008147 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
8148 (ulong)b, sgblockno);
8149 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
8150 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
8151 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
8152 if (b->sg_ptr != 0) {
8153 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
8154 }
8155 for (i = 0; i < b->sg_cnt; i++) {
8156 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
8157 i, (ulong)b->sg_list[i].sg_addr,
8158 (ulong)b->sg_list[i].sg_count);
8159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008160}
8161
8162/*
8163 * asc_prt_hex()
8164 *
8165 * Print hexadecimal output in 4 byte groupings 32 bytes
8166 * or 8 double-words per line.
8167 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008168static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008169{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008170 int i;
8171 int j;
8172 int k;
8173 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008174
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008175 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008177 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008178
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008179 /* Display a maximum of 8 double-words per line. */
8180 if ((k = (l - i) / 4) >= 8) {
8181 k = 8;
8182 m = 0;
8183 } else {
8184 m = (l - i) % 4;
8185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008186
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008187 for (j = 0; j < k; j++) {
8188 printk(" %2.2X%2.2X%2.2X%2.2X",
8189 (unsigned)s[i + (j * 4)],
8190 (unsigned)s[i + (j * 4) + 1],
8191 (unsigned)s[i + (j * 4) + 2],
8192 (unsigned)s[i + (j * 4) + 3]);
8193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008194
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008195 switch (m) {
8196 case 0:
8197 default:
8198 break;
8199 case 1:
8200 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
8201 break;
8202 case 2:
8203 printk(" %2.2X%2.2X",
8204 (unsigned)s[i + (j * 4)],
8205 (unsigned)s[i + (j * 4) + 1]);
8206 break;
8207 case 3:
8208 printk(" %2.2X%2.2X%2.2X",
8209 (unsigned)s[i + (j * 4) + 1],
8210 (unsigned)s[i + (j * 4) + 2],
8211 (unsigned)s[i + (j * 4) + 3]);
8212 break;
8213 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008215 printk("\n");
8216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008217}
8218#endif /* ADVANSYS_DEBUG */
8219
8220/*
8221 * --- Asc Library Functions
8222 */
8223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008224static ushort __init AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008225{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008226 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008227
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008228 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
8229 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
8230 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008231}
8232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008233static uchar __init AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008234{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008235 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008237 if (AscGetChipScsiID(iop_base) == new_host_id) {
8238 return (new_host_id);
8239 }
8240 cfg_lsw = AscGetChipCfgLsw(iop_base);
8241 cfg_lsw &= 0xF8FF;
8242 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
8243 AscSetChipCfgLsw(iop_base, cfg_lsw);
8244 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008245}
8246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008247static uchar __init AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008248{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008249 uchar sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008251 AscSetBank(iop_base, 1);
8252 sc = inp(iop_base + IOP_REG_SC);
8253 AscSetBank(iop_base, 0);
8254 return (sc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008255}
8256
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008257static uchar __init AscGetChipVersion(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008258{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008259 if ((bus_type & ASC_IS_EISA) != 0) {
8260 PortAddr eisa_iop;
8261 uchar revision;
8262 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
8263 (PortAddr) ASC_EISA_REV_IOP_MASK;
8264 revision = inp(eisa_iop);
8265 return ((uchar)((ASC_CHIP_MIN_VER_EISA - 1) + revision));
8266 }
8267 return (AscGetChipVerNo(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008268}
8269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008270static ushort __init AscGetChipBusType(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008271{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008272 ushort chip_ver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008274 chip_ver = AscGetChipVerNo(iop_base);
8275 if ((chip_ver >= ASC_CHIP_MIN_VER_VL)
8276 && (chip_ver <= ASC_CHIP_MAX_VER_VL)
8277 ) {
8278 if (((iop_base & 0x0C30) == 0x0C30)
8279 || ((iop_base & 0x0C50) == 0x0C50)
8280 ) {
8281 return (ASC_IS_EISA);
8282 }
8283 return (ASC_IS_VL);
8284 }
8285 if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
8286 (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
8287 if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
8288 return (ASC_IS_ISAPNP);
8289 }
8290 return (ASC_IS_ISA);
8291 } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
8292 (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
8293 return (ASC_IS_PCI);
8294 }
8295 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008296}
8297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008298static ASC_DCNT
8299AscLoadMicroCode(PortAddr iop_base,
8300 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008301{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008302 ASC_DCNT chksum;
8303 ushort mcode_word_size;
8304 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008305
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008306 /* Write the microcode buffer starting at LRAM address 0. */
8307 mcode_word_size = (ushort)(mcode_size >> 1);
8308 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
8309 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008310
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008311 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
8312 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
8313 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
8314 (ushort)ASC_CODE_SEC_BEG,
8315 (ushort)((mcode_size -
8316 s_addr - (ushort)
8317 ASC_CODE_SEC_BEG) /
8318 2));
8319 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
8320 (ulong)mcode_chksum);
8321 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
8322 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
8323 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008324}
8325
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008326static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008327{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008328 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008329
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008330 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
8331 iop_base, AscGetChipSignatureByte(iop_base));
8332 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
8333 ASC_DBG2(1,
8334 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
8335 iop_base, AscGetChipSignatureWord(iop_base));
8336 sig_word = AscGetChipSignatureWord(iop_base);
8337 if ((sig_word == (ushort)ASC_1000_ID0W) ||
8338 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
8339 return (1);
8340 }
8341 }
8342 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008343}
8344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008345static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = {
8346 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
8347 ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
Linus Torvalds1da177e2005-04-16 15:20:36 -07008348};
8349
8350#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008351static uchar _isa_pnp_inited __initdata = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008352
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008353static PortAddr __init AscSearchIOPortAddr(PortAddr iop_beg, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008354{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008355 if (bus_type & ASC_IS_VL) {
8356 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
8357 if (AscGetChipVersion(iop_beg, bus_type) <=
8358 ASC_CHIP_MAX_VER_VL) {
8359 return (iop_beg);
8360 }
8361 }
8362 return (0);
8363 }
8364 if (bus_type & ASC_IS_ISA) {
8365 if (_isa_pnp_inited == 0) {
8366 AscSetISAPNPWaitForKey();
8367 _isa_pnp_inited++;
8368 }
8369 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
8370 if ((AscGetChipVersion(iop_beg, bus_type) &
8371 ASC_CHIP_VER_ISA_BIT) != 0) {
8372 return (iop_beg);
8373 }
8374 }
8375 return (0);
8376 }
8377 if (bus_type & ASC_IS_EISA) {
8378 if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
8379 return (iop_beg);
8380 }
8381 return (0);
8382 }
8383 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008384}
8385
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008386static PortAddr __init AscSearchIOPortAddr11(PortAddr s_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008387{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008388 int i;
8389 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008390
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008391 for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
8392 if (_asc_def_iop_base[i] > s_addr) {
8393 break;
8394 }
8395 }
8396 for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
8397 iop_base = _asc_def_iop_base[i];
8398 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
8399 ASC_DBG1(1,
8400 "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n",
8401 iop_base);
8402 continue;
8403 }
8404 ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n",
8405 iop_base);
8406 release_region(iop_base, ASC_IOADR_GAP);
8407 if (AscFindSignature(iop_base)) {
8408 return (iop_base);
8409 }
8410 }
8411 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008412}
8413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008414static void __init AscSetISAPNPWaitForKey(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008415{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008416 outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
8417 outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
8418 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008419}
8420#endif /* CONFIG_ISA */
8421
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008422static void __init AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008423{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008424 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
8425 AscSetChipStatus(iop_base, 0);
8426 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008427}
8428
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008429static uchar __init AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008430{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008431 ushort cfg_lsw;
8432 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008433
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008434 if ((bus_type & ASC_IS_EISA) != 0) {
8435 cfg_lsw = AscGetEisaChipCfg(iop_base);
8436 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
8437 if ((chip_irq == 13) || (chip_irq > 15)) {
8438 return (0);
8439 }
8440 return (chip_irq);
8441 }
8442 if ((bus_type & ASC_IS_VL) != 0) {
8443 cfg_lsw = AscGetChipCfgLsw(iop_base);
8444 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
8445 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
8446 return (0);
8447 }
8448 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
8449 }
8450 cfg_lsw = AscGetChipCfgLsw(iop_base);
8451 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
8452 if (chip_irq == 3)
8453 chip_irq += (uchar)2;
8454 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008455}
8456
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008457static uchar __init
8458AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008459{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008460 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008462 if ((bus_type & ASC_IS_VL) != 0) {
8463 if (irq_no != 0) {
8464 if ((irq_no < ASC_MIN_IRQ_NO)
8465 || (irq_no > ASC_MAX_IRQ_NO)) {
8466 irq_no = 0;
8467 } else {
8468 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
8469 }
8470 }
8471 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
8472 cfg_lsw |= (ushort)0x0010;
8473 AscSetChipCfgLsw(iop_base, cfg_lsw);
8474 AscToggleIRQAct(iop_base);
8475 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
8476 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
8477 AscSetChipCfgLsw(iop_base, cfg_lsw);
8478 AscToggleIRQAct(iop_base);
8479 return (AscGetChipIRQ(iop_base, bus_type));
8480 }
8481 if ((bus_type & (ASC_IS_ISA)) != 0) {
8482 if (irq_no == 15)
8483 irq_no -= (uchar)2;
8484 irq_no -= (uchar)ASC_MIN_IRQ_NO;
8485 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
8486 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
8487 AscSetChipCfgLsw(iop_base, cfg_lsw);
8488 return (AscGetChipIRQ(iop_base, bus_type));
8489 }
8490 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008491}
8492
8493#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008494static void __init AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008495{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008496 if (dma_channel < 4) {
8497 outp(0x000B, (ushort)(0xC0 | dma_channel));
8498 outp(0x000A, dma_channel);
8499 } else if (dma_channel < 8) {
8500 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
8501 outp(0x00D4, (ushort)(dma_channel - 4));
8502 }
8503 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008504}
8505#endif /* CONFIG_ISA */
8506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008507static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008508{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008509 EXT_MSG ext_msg;
8510 EXT_MSG out_msg;
8511 ushort halt_q_addr;
8512 int sdtr_accept;
8513 ushort int_halt_code;
8514 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8515 ASC_SCSI_BIT_ID_TYPE target_id;
8516 PortAddr iop_base;
8517 uchar tag_code;
8518 uchar q_status;
8519 uchar halt_qp;
8520 uchar sdtr_data;
8521 uchar target_ix;
8522 uchar q_cntl, tid_no;
8523 uchar cur_dvc_qng;
8524 uchar asyn_sdtr;
8525 uchar scsi_status;
8526 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008528 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
8529 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008530
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008531 iop_base = asc_dvc->iop_base;
8532 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008533
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008534 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8535 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8536 target_ix = AscReadLramByte(iop_base,
8537 (ushort)(halt_q_addr +
8538 (ushort)ASC_SCSIQ_B_TARGET_IX));
8539 q_cntl =
8540 AscReadLramByte(iop_base,
8541 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8542 tid_no = ASC_TIX_TO_TID(target_ix);
8543 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8544 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8545 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8546 } else {
8547 asyn_sdtr = 0;
8548 }
8549 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8550 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8551 AscSetChipSDTR(iop_base, 0, tid_no);
8552 boardp->sdtr_data[tid_no] = 0;
8553 }
8554 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8555 return (0);
8556 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8557 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8558 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8559 boardp->sdtr_data[tid_no] = asyn_sdtr;
8560 }
8561 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8562 return (0);
8563 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008564
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008565 AscMemWordCopyPtrFromLram(iop_base,
8566 ASCV_MSGIN_BEG,
8567 (uchar *)&ext_msg,
8568 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008569
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008570 if (ext_msg.msg_type == MS_EXTEND &&
8571 ext_msg.msg_req == MS_SDTR_CODE &&
8572 ext_msg.msg_len == MS_SDTR_LEN) {
8573 sdtr_accept = TRUE;
8574 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008575
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008576 sdtr_accept = FALSE;
8577 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8578 }
8579 if ((ext_msg.xfer_period <
8580 asc_dvc->sdtr_period_tbl[asc_dvc->
8581 host_init_sdtr_index])
8582 || (ext_msg.xfer_period >
8583 asc_dvc->sdtr_period_tbl[asc_dvc->
8584 max_sdtr_index])) {
8585 sdtr_accept = FALSE;
8586 ext_msg.xfer_period =
8587 asc_dvc->sdtr_period_tbl[asc_dvc->
8588 host_init_sdtr_index];
8589 }
8590 if (sdtr_accept) {
8591 sdtr_data =
8592 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8593 ext_msg.req_ack_offset);
8594 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008595
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008596 q_cntl |= QC_MSG_OUT;
8597 asc_dvc->init_sdtr &= ~target_id;
8598 asc_dvc->sdtr_done &= ~target_id;
8599 AscSetChipSDTR(iop_base, asyn_sdtr,
8600 tid_no);
8601 boardp->sdtr_data[tid_no] = asyn_sdtr;
8602 }
8603 }
8604 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008605
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008606 q_cntl &= ~QC_MSG_OUT;
8607 asc_dvc->init_sdtr &= ~target_id;
8608 asc_dvc->sdtr_done &= ~target_id;
8609 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8610 } else {
8611 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008612
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008613 q_cntl &= ~QC_MSG_OUT;
8614 asc_dvc->sdtr_done |= target_id;
8615 asc_dvc->init_sdtr |= target_id;
8616 asc_dvc->pci_fix_asyn_xfer &=
8617 ~target_id;
8618 sdtr_data =
8619 AscCalSDTRData(asc_dvc,
8620 ext_msg.xfer_period,
8621 ext_msg.
8622 req_ack_offset);
8623 AscSetChipSDTR(iop_base, sdtr_data,
8624 tid_no);
8625 boardp->sdtr_data[tid_no] = sdtr_data;
8626 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008627
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008628 q_cntl |= QC_MSG_OUT;
8629 AscMsgOutSDTR(asc_dvc,
8630 ext_msg.xfer_period,
8631 ext_msg.req_ack_offset);
8632 asc_dvc->pci_fix_asyn_xfer &=
8633 ~target_id;
8634 sdtr_data =
8635 AscCalSDTRData(asc_dvc,
8636 ext_msg.xfer_period,
8637 ext_msg.
8638 req_ack_offset);
8639 AscSetChipSDTR(iop_base, sdtr_data,
8640 tid_no);
8641 boardp->sdtr_data[tid_no] = sdtr_data;
8642 asc_dvc->sdtr_done |= target_id;
8643 asc_dvc->init_sdtr |= target_id;
8644 }
8645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008646
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008647 AscWriteLramByte(iop_base,
8648 (ushort)(halt_q_addr +
8649 (ushort)ASC_SCSIQ_B_CNTL),
8650 q_cntl);
8651 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8652 return (0);
8653 } else if (ext_msg.msg_type == MS_EXTEND &&
8654 ext_msg.msg_req == MS_WDTR_CODE &&
8655 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008657 ext_msg.wdtr_width = 0;
8658 AscMemWordCopyPtrToLram(iop_base,
8659 ASCV_MSGOUT_BEG,
8660 (uchar *)&ext_msg,
8661 sizeof(EXT_MSG) >> 1);
8662 q_cntl |= QC_MSG_OUT;
8663 AscWriteLramByte(iop_base,
8664 (ushort)(halt_q_addr +
8665 (ushort)ASC_SCSIQ_B_CNTL),
8666 q_cntl);
8667 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8668 return (0);
8669 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008671 ext_msg.msg_type = MESSAGE_REJECT;
8672 AscMemWordCopyPtrToLram(iop_base,
8673 ASCV_MSGOUT_BEG,
8674 (uchar *)&ext_msg,
8675 sizeof(EXT_MSG) >> 1);
8676 q_cntl |= QC_MSG_OUT;
8677 AscWriteLramByte(iop_base,
8678 (ushort)(halt_q_addr +
8679 (ushort)ASC_SCSIQ_B_CNTL),
8680 q_cntl);
8681 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8682 return (0);
8683 }
8684 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008685
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008686 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008687
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008688 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008689
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008690 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008692 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8693 q_cntl |= QC_MSG_OUT;
8694 AscMsgOutSDTR(asc_dvc,
8695 asc_dvc->
8696 sdtr_period_tbl[(sdtr_data >> 4) &
8697 (uchar)(asc_dvc->
8698 max_sdtr_index -
8699 1)],
8700 (uchar)(sdtr_data & (uchar)
8701 ASC_SYN_MAX_OFFSET));
8702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008703
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008704 AscWriteLramByte(iop_base,
8705 (ushort)(halt_q_addr +
8706 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008708 tag_code = AscReadLramByte(iop_base,
8709 (ushort)(halt_q_addr + (ushort)
8710 ASC_SCSIQ_B_TAG_CODE));
8711 tag_code &= 0xDC;
8712 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
8713 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
8714 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008716 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
8717 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008719 }
8720 AscWriteLramByte(iop_base,
8721 (ushort)(halt_q_addr +
8722 (ushort)ASC_SCSIQ_B_TAG_CODE),
8723 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008724
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008725 q_status = AscReadLramByte(iop_base,
8726 (ushort)(halt_q_addr + (ushort)
8727 ASC_SCSIQ_B_STATUS));
8728 q_status |= (QS_READY | QS_BUSY);
8729 AscWriteLramByte(iop_base,
8730 (ushort)(halt_q_addr +
8731 (ushort)ASC_SCSIQ_B_STATUS),
8732 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008733
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008734 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
8735 scsi_busy &= ~target_id;
8736 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008738 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8739 return (0);
8740 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008742 AscMemWordCopyPtrFromLram(iop_base,
8743 ASCV_MSGOUT_BEG,
8744 (uchar *)&out_msg,
8745 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008746
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008747 if ((out_msg.msg_type == MS_EXTEND) &&
8748 (out_msg.msg_len == MS_SDTR_LEN) &&
8749 (out_msg.msg_req == MS_SDTR_CODE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008750
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008751 asc_dvc->init_sdtr &= ~target_id;
8752 asc_dvc->sdtr_done &= ~target_id;
8753 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8754 boardp->sdtr_data[tid_no] = asyn_sdtr;
8755 }
8756 q_cntl &= ~QC_MSG_OUT;
8757 AscWriteLramByte(iop_base,
8758 (ushort)(halt_q_addr +
8759 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8760 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8761 return (0);
8762 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008764 scsi_status = AscReadLramByte(iop_base,
8765 (ushort)((ushort)halt_q_addr +
8766 (ushort)
8767 ASC_SCSIQ_SCSI_STATUS));
8768 cur_dvc_qng =
8769 AscReadLramByte(iop_base,
8770 (ushort)((ushort)ASC_QADR_BEG +
8771 (ushort)target_ix));
8772 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008773
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008774 scsi_busy = AscReadLramByte(iop_base,
8775 (ushort)ASCV_SCSIBUSY_B);
8776 scsi_busy |= target_id;
8777 AscWriteLramByte(iop_base,
8778 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8779 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008781 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
8782 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
8783 cur_dvc_qng -= 1;
8784 asc_dvc->max_dvc_qng[tid_no] =
8785 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008786
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008787 AscWriteLramByte(iop_base,
8788 (ushort)((ushort)
8789 ASCV_MAX_DVC_QNG_BEG
8790 + (ushort)
8791 tid_no),
8792 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008793
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008794 /*
8795 * Set the device queue depth to the number of
8796 * active requests when the QUEUE FULL condition
8797 * was encountered.
8798 */
8799 boardp->queue_full |= target_id;
8800 boardp->queue_full_cnt[tid_no] =
8801 cur_dvc_qng;
8802 }
8803 }
8804 }
8805 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8806 return (0);
8807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008808#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008809 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
8810 uchar q_no;
8811 ushort q_addr;
8812 uchar sg_wk_q_no;
8813 uchar first_sg_wk_q_no;
8814 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
8815 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
8816 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
8817 ushort sg_list_dwords;
8818 ushort sg_entry_cnt;
8819 uchar next_qp;
8820 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008821
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008822 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
8823 if (q_no == ASC_QLINK_END) {
8824 return (0);
8825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008826
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008827 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008828
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008829 /*
8830 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
8831 * structure pointer using a macro provided by the driver.
8832 * The ASC_SCSI_REQ pointer provides a pointer to the
8833 * host ASC_SG_HEAD structure.
8834 */
8835 /* Read request's SRB pointer. */
8836 scsiq = (ASC_SCSI_Q *)
8837 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
8838 (ushort)
8839 (q_addr +
8840 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008841
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008842 /*
8843 * Get request's first and working SG queue.
8844 */
8845 sg_wk_q_no = AscReadLramByte(iop_base,
8846 (ushort)(q_addr +
8847 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008848
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008849 first_sg_wk_q_no = AscReadLramByte(iop_base,
8850 (ushort)(q_addr +
8851 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008852
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008853 /*
8854 * Reset request's working SG queue back to the
8855 * first SG queue.
8856 */
8857 AscWriteLramByte(iop_base,
8858 (ushort)(q_addr +
8859 (ushort)ASC_SCSIQ_B_SG_WK_QP),
8860 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008861
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008862 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008863
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008864 /*
8865 * Set sg_entry_cnt to the number of SG elements
8866 * that will be completed on this interrupt.
8867 *
8868 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
8869 * SG elements. The data_cnt and data_addr fields which
8870 * add 1 to the SG element capacity are not used when
8871 * restarting SG handling after a halt.
8872 */
8873 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
8874 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008875
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008876 /*
8877 * Keep track of remaining number of SG elements that will
8878 * need to be handled on the next interrupt.
8879 */
8880 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
8881 } else {
8882 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
8883 scsiq->remain_sg_entry_cnt = 0;
8884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008885
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008886 /*
8887 * Copy SG elements into the list of allocated SG queues.
8888 *
8889 * Last index completed is saved in scsiq->next_sg_index.
8890 */
8891 next_qp = first_sg_wk_q_no;
8892 q_addr = ASC_QNO_TO_QADDR(next_qp);
8893 scsi_sg_q.sg_head_qp = q_no;
8894 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
8895 for (i = 0; i < sg_head->queue_cnt; i++) {
8896 scsi_sg_q.seq_no = i + 1;
8897 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
8898 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
8899 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8900 /*
8901 * After very first SG queue RISC FW uses next
8902 * SG queue first element then checks sg_list_cnt
8903 * against zero and then decrements, so set
8904 * sg_list_cnt 1 less than number of SG elements
8905 * in each SG queue.
8906 */
8907 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
8908 scsi_sg_q.sg_cur_list_cnt =
8909 ASC_SG_LIST_PER_Q - 1;
8910 } else {
8911 /*
8912 * This is the last SG queue in the list of
8913 * allocated SG queues. If there are more
8914 * SG elements than will fit in the allocated
8915 * queues, then set the QCSG_SG_XFER_MORE flag.
8916 */
8917 if (scsiq->remain_sg_entry_cnt != 0) {
8918 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8919 } else {
8920 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
8921 }
8922 /* equals sg_entry_cnt * 2 */
8923 sg_list_dwords = sg_entry_cnt << 1;
8924 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
8925 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
8926 sg_entry_cnt = 0;
8927 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008929 scsi_sg_q.q_no = next_qp;
8930 AscMemWordCopyPtrToLram(iop_base,
8931 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8932 (uchar *)&scsi_sg_q,
8933 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008935 AscMemDWordCopyPtrToLram(iop_base,
8936 q_addr + ASC_SGQ_LIST_BEG,
8937 (uchar *)&sg_head->
8938 sg_list[scsiq->next_sg_index],
8939 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008941 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008942
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008943 /*
8944 * If the just completed SG queue contained the
8945 * last SG element, then no more SG queues need
8946 * to be written.
8947 */
8948 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
8949 break;
8950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008951
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008952 next_qp = AscReadLramByte(iop_base,
8953 (ushort)(q_addr +
8954 ASC_SCSIQ_B_FWD));
8955 q_addr = ASC_QNO_TO_QADDR(next_qp);
8956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008958 /*
8959 * Clear the halt condition so the RISC will be restarted
8960 * after the return.
8961 */
8962 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8963 return (0);
8964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008965#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008966 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008967}
8968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008969static uchar
8970_AscCopyLramScsiDoneQ(PortAddr iop_base,
8971 ushort q_addr,
8972 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008973{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008974 ushort _val;
8975 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008977 DvcGetQinfo(iop_base,
8978 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
8979 (uchar *)scsiq,
8980 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008982 _val = AscReadLramWord(iop_base,
8983 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
8984 scsiq->q_status = (uchar)_val;
8985 scsiq->q_no = (uchar)(_val >> 8);
8986 _val = AscReadLramWord(iop_base,
8987 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8988 scsiq->cntl = (uchar)_val;
8989 sg_queue_cnt = (uchar)(_val >> 8);
8990 _val = AscReadLramWord(iop_base,
8991 (ushort)(q_addr +
8992 (ushort)ASC_SCSIQ_B_SENSE_LEN));
8993 scsiq->sense_len = (uchar)_val;
8994 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008996 /*
8997 * Read high word of remain bytes from alternate location.
8998 */
8999 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
9000 (ushort)(q_addr +
9001 (ushort)
9002 ASC_SCSIQ_W_ALT_DC1)))
9003 << 16);
9004 /*
9005 * Read low word of remain bytes from original location.
9006 */
9007 scsiq->remain_bytes += AscReadLramWord(iop_base,
9008 (ushort)(q_addr + (ushort)
9009 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009011 scsiq->remain_bytes &= max_dma_count;
9012 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009013}
9014
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009015static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009016{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009017 uchar next_qp;
9018 uchar n_q_used;
9019 uchar sg_list_qp;
9020 uchar sg_queue_cnt;
9021 uchar q_cnt;
9022 uchar done_q_tail;
9023 uchar tid_no;
9024 ASC_SCSI_BIT_ID_TYPE scsi_busy;
9025 ASC_SCSI_BIT_ID_TYPE target_id;
9026 PortAddr iop_base;
9027 ushort q_addr;
9028 ushort sg_q_addr;
9029 uchar cur_target_qng;
9030 ASC_QDONE_INFO scsiq_buf;
9031 ASC_QDONE_INFO *scsiq;
9032 int false_overrun;
9033 ASC_ISR_CALLBACK asc_isr_callback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009035 iop_base = asc_dvc->iop_base;
9036 asc_isr_callback = asc_dvc->isr_callback;
9037 n_q_used = 1;
9038 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
9039 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
9040 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
9041 next_qp = AscReadLramByte(iop_base,
9042 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
9043 if (next_qp != ASC_QLINK_END) {
9044 AscPutVarDoneQTail(iop_base, next_qp);
9045 q_addr = ASC_QNO_TO_QADDR(next_qp);
9046 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
9047 asc_dvc->max_dma_count);
9048 AscWriteLramByte(iop_base,
9049 (ushort)(q_addr +
9050 (ushort)ASC_SCSIQ_B_STATUS),
9051 (uchar)(scsiq->
9052 q_status & (uchar)~(QS_READY |
9053 QS_ABORTED)));
9054 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
9055 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
9056 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
9057 sg_q_addr = q_addr;
9058 sg_list_qp = next_qp;
9059 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
9060 sg_list_qp = AscReadLramByte(iop_base,
9061 (ushort)(sg_q_addr
9062 + (ushort)
9063 ASC_SCSIQ_B_FWD));
9064 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
9065 if (sg_list_qp == ASC_QLINK_END) {
9066 AscSetLibErrorCode(asc_dvc,
9067 ASCQ_ERR_SG_Q_LINKS);
9068 scsiq->d3.done_stat = QD_WITH_ERROR;
9069 scsiq->d3.host_stat =
9070 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
9071 goto FATAL_ERR_QDONE;
9072 }
9073 AscWriteLramByte(iop_base,
9074 (ushort)(sg_q_addr + (ushort)
9075 ASC_SCSIQ_B_STATUS),
9076 QS_FREE);
9077 }
9078 n_q_used = sg_queue_cnt + 1;
9079 AscPutVarDoneQTail(iop_base, sg_list_qp);
9080 }
9081 if (asc_dvc->queue_full_or_busy & target_id) {
9082 cur_target_qng = AscReadLramByte(iop_base,
9083 (ushort)((ushort)
9084 ASC_QADR_BEG
9085 + (ushort)
9086 scsiq->d2.
9087 target_ix));
9088 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
9089 scsi_busy = AscReadLramByte(iop_base, (ushort)
9090 ASCV_SCSIBUSY_B);
9091 scsi_busy &= ~target_id;
9092 AscWriteLramByte(iop_base,
9093 (ushort)ASCV_SCSIBUSY_B,
9094 scsi_busy);
9095 asc_dvc->queue_full_or_busy &= ~target_id;
9096 }
9097 }
9098 if (asc_dvc->cur_total_qng >= n_q_used) {
9099 asc_dvc->cur_total_qng -= n_q_used;
9100 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
9101 asc_dvc->cur_dvc_qng[tid_no]--;
9102 }
9103 } else {
9104 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
9105 scsiq->d3.done_stat = QD_WITH_ERROR;
9106 goto FATAL_ERR_QDONE;
9107 }
9108 if ((scsiq->d2.srb_ptr == 0UL) ||
9109 ((scsiq->q_status & QS_ABORTED) != 0)) {
9110 return (0x11);
9111 } else if (scsiq->q_status == QS_DONE) {
9112 false_overrun = FALSE;
9113 if (scsiq->extra_bytes != 0) {
9114 scsiq->remain_bytes +=
9115 (ADV_DCNT)scsiq->extra_bytes;
9116 }
9117 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
9118 if (scsiq->d3.host_stat ==
9119 QHSTA_M_DATA_OVER_RUN) {
9120 if ((scsiq->
9121 cntl & (QC_DATA_IN | QC_DATA_OUT))
9122 == 0) {
9123 scsiq->d3.done_stat =
9124 QD_NO_ERROR;
9125 scsiq->d3.host_stat =
9126 QHSTA_NO_ERROR;
9127 } else if (false_overrun) {
9128 scsiq->d3.done_stat =
9129 QD_NO_ERROR;
9130 scsiq->d3.host_stat =
9131 QHSTA_NO_ERROR;
9132 }
9133 } else if (scsiq->d3.host_stat ==
9134 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
9135 AscStopChip(iop_base);
9136 AscSetChipControl(iop_base,
9137 (uchar)(CC_SCSI_RESET
9138 | CC_HALT));
9139 DvcDelayNanoSecond(asc_dvc, 60000);
9140 AscSetChipControl(iop_base, CC_HALT);
9141 AscSetChipStatus(iop_base,
9142 CIW_CLR_SCSI_RESET_INT);
9143 AscSetChipStatus(iop_base, 0);
9144 AscSetChipControl(iop_base, 0);
9145 }
9146 }
9147 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9148 (*asc_isr_callback) (asc_dvc, scsiq);
9149 } else {
9150 if ((AscReadLramByte(iop_base,
9151 (ushort)(q_addr + (ushort)
9152 ASC_SCSIQ_CDB_BEG))
9153 == START_STOP)) {
9154 asc_dvc->unit_not_ready &= ~target_id;
9155 if (scsiq->d3.done_stat != QD_NO_ERROR) {
9156 asc_dvc->start_motor &=
9157 ~target_id;
9158 }
9159 }
9160 }
9161 return (1);
9162 } else {
9163 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
9164 FATAL_ERR_QDONE:
9165 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9166 (*asc_isr_callback) (asc_dvc, scsiq);
9167 }
9168 return (0x80);
9169 }
9170 }
9171 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009172}
9173
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009174static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009175{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009176 ASC_CS_TYPE chipstat;
9177 PortAddr iop_base;
9178 ushort saved_ram_addr;
9179 uchar ctrl_reg;
9180 uchar saved_ctrl_reg;
9181 int int_pending;
9182 int status;
9183 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009185 iop_base = asc_dvc->iop_base;
9186 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009188 if (AscIsIntPending(iop_base) == 0) {
9189 return int_pending;
9190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009191
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009192 if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
9193 || (asc_dvc->isr_callback == 0)
9194 ) {
9195 return (ERR);
9196 }
9197 if (asc_dvc->in_critical_cnt != 0) {
9198 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
9199 return (ERR);
9200 }
9201 if (asc_dvc->is_in_int) {
9202 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
9203 return (ERR);
9204 }
9205 asc_dvc->is_in_int = TRUE;
9206 ctrl_reg = AscGetChipControl(iop_base);
9207 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
9208 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
9209 chipstat = AscGetChipStatus(iop_base);
9210 if (chipstat & CSW_SCSI_RESET_LATCH) {
9211 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
9212 int i = 10;
9213 int_pending = TRUE;
9214 asc_dvc->sdtr_done = 0;
9215 saved_ctrl_reg &= (uchar)(~CC_HALT);
9216 while ((AscGetChipStatus(iop_base) &
9217 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
9218 DvcSleepMilliSecond(100);
9219 }
9220 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
9221 AscSetChipControl(iop_base, CC_HALT);
9222 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9223 AscSetChipStatus(iop_base, 0);
9224 chipstat = AscGetChipStatus(iop_base);
9225 }
9226 }
9227 saved_ram_addr = AscGetChipLramAddr(iop_base);
9228 host_flag = AscReadLramByte(iop_base,
9229 ASCV_HOST_FLAG_B) &
9230 (uchar)(~ASC_HOST_FLAG_IN_ISR);
9231 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
9232 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
9233 if ((chipstat & CSW_INT_PENDING)
9234 || (int_pending)
9235 ) {
9236 AscAckInterrupt(iop_base);
9237 int_pending = TRUE;
9238 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
9239 if (AscIsrChipHalted(asc_dvc) == ERR) {
9240 goto ISR_REPORT_QDONE_FATAL_ERROR;
9241 } else {
9242 saved_ctrl_reg &= (uchar)(~CC_HALT);
9243 }
9244 } else {
9245 ISR_REPORT_QDONE_FATAL_ERROR:
9246 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
9247 while (((status =
9248 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
9249 }
9250 } else {
9251 do {
9252 if ((status =
9253 AscIsrQDone(asc_dvc)) == 1) {
9254 break;
9255 }
9256 } while (status == 0x11);
9257 }
9258 if ((status & 0x80) != 0)
9259 int_pending = ERR;
9260 }
9261 }
9262 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9263 AscSetChipLramAddr(iop_base, saved_ram_addr);
9264 AscSetChipControl(iop_base, saved_ctrl_reg);
9265 asc_dvc->is_in_int = FALSE;
9266 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009267}
9268
9269/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009270static uchar _asc_mcode_buf[] = {
9271 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9272 0x00, 0x00, 0x00, 0x00,
9273 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
9274 0x00, 0x00, 0x00, 0x00,
9275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9276 0x00, 0x00, 0x00, 0x00,
9277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9278 0x00, 0x00, 0x00, 0x00,
9279 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00,
9280 0x00, 0xFF, 0x00, 0x00,
9281 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
9282 0x00, 0x00, 0x00, 0x00,
9283 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
9284 0x00, 0x00, 0x00, 0x00,
9285 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88,
9286 0x00, 0x00, 0x00, 0x00,
9287 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73,
9288 0x03, 0x23, 0x36, 0x40,
9289 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
9290 0xC2, 0x00, 0x92, 0x80,
9291 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60,
9292 0xB6, 0x00, 0x92, 0x80,
9293 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00,
9294 0x92, 0x80, 0x80, 0x62,
9295 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
9296 0xCD, 0x04, 0x4D, 0x00,
9297 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01,
9298 0xE6, 0x84, 0xD2, 0xC1,
9299 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97,
9300 0xC6, 0x81, 0xC2, 0x88,
9301 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
9302 0x84, 0x97, 0x07, 0xA6,
9303 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE,
9304 0xC2, 0x88, 0xCE, 0x00,
9305 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01,
9306 0x80, 0x63, 0x07, 0xA6,
9307 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
9308 0x34, 0x01, 0x00, 0x33,
9309 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23,
9310 0x68, 0x98, 0x4D, 0x04,
9311 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23,
9312 0xF8, 0x88, 0xFB, 0x23,
9313 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
9314 0x00, 0x33, 0x0A, 0x00,
9315 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00,
9316 0xC2, 0x88, 0xCD, 0x04,
9317 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81,
9318 0x06, 0xAB, 0x82, 0x01,
9319 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
9320 0x3C, 0x01, 0x00, 0x05,
9321 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01,
9322 0x15, 0x23, 0xA1, 0x01,
9323 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00,
9324 0x06, 0x61, 0x00, 0xA0,
9325 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
9326 0xC2, 0x88, 0x06, 0x23,
9327 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01,
9328 0x57, 0x60, 0x00, 0xA0,
9329 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73,
9330 0x4B, 0x00, 0x06, 0x61,
9331 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
9332 0x4F, 0x00, 0x84, 0x97,
9333 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97,
9334 0x48, 0x04, 0x84, 0x80,
9335 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00,
9336 0x81, 0x73, 0x06, 0x29,
9337 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
9338 0x04, 0x98, 0xF0, 0x80,
9339 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6,
9340 0x34, 0x02, 0x03, 0xA6,
9341 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96,
9342 0x46, 0x82, 0xFE, 0x95,
9343 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
9344 0x07, 0xA6, 0x5A, 0x02,
9345 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95,
9346 0x48, 0x82, 0x60, 0x96,
9347 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84,
9348 0x04, 0x01, 0x0C, 0xDC,
9349 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
9350 0x6F, 0x00, 0xA5, 0x01,
9351 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01,
9352 0x02, 0xA6, 0xAA, 0x02,
9353 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04,
9354 0x01, 0xA6, 0xB4, 0x02,
9355 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
9356 0x80, 0x63, 0x00, 0x43,
9357 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23,
9358 0x04, 0x61, 0x84, 0x01,
9359 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F,
9360 0x00, 0x00, 0xEA, 0x82,
9361 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
9362 0x00, 0x33, 0x1F, 0x00,
9363 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98,
9364 0xB6, 0x2D, 0x01, 0xA6,
9365 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6,
9366 0x10, 0x03, 0x03, 0xA6,
9367 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
9368 0x7C, 0x95, 0xEE, 0x82,
9369 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4,
9370 0x04, 0x01, 0x2D, 0xC8,
9371 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01,
9372 0x05, 0x05, 0x86, 0x98,
9373 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
9374 0x3C, 0x04, 0x06, 0xA6,
9375 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88,
9376 0x7C, 0x95, 0x32, 0x83,
9377 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05,
9378 0xEB, 0x04, 0x00, 0x33,
9379 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
9380 0xFF, 0xA2, 0x7A, 0x03,
9381 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01,
9382 0x00, 0xA2, 0x9A, 0x03,
9383 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
9384 0x01, 0xA6, 0x96, 0x03,
9385 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
9386 0xA4, 0x03, 0x00, 0xA6,
9387 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03,
9388 0x07, 0xA6, 0xB2, 0x03,
9389 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88,
9390 0xA8, 0x98, 0x80, 0x42,
9391 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
9392 0xC0, 0x83, 0x00, 0x33,
9393 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
9394 0xA0, 0x01, 0x12, 0x23,
9395 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B,
9396 0x80, 0x67, 0x05, 0x23,
9397 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
9398 0x06, 0xA6, 0x0A, 0x04,
9399 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96,
9400 0xF4, 0x83, 0x20, 0x84,
9401 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
9402 0x83, 0x03, 0x80, 0x63,
9403 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
9404 0x38, 0x04, 0x00, 0x33,
9405 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84,
9406 0x1D, 0x01, 0x06, 0xCC,
9407 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62,
9408 0xA2, 0x0D, 0x80, 0x63,
9409 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
9410 0x80, 0x63, 0xA3, 0x01,
9411 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0,
9412 0x76, 0x04, 0xE0, 0x00,
9413 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00,
9414 0x00, 0x33, 0x1E, 0x00,
9415 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
9416 0x08, 0x23, 0x22, 0xA3,
9417 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3,
9418 0xC4, 0x04, 0x42, 0x23,
9419 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23,
9420 0xF8, 0x88, 0x04, 0x98,
9421 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
9422 0x81, 0x62, 0xE8, 0x81,
9423 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98,
9424 0x00, 0x33, 0x00, 0x81,
9425 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23,
9426 0xF8, 0x88, 0x04, 0x23,
9427 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
9428 0xF4, 0x04, 0x00, 0x33,
9429 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01,
9430 0x04, 0x23, 0xA0, 0x01,
9431 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00,
9432 0x00, 0xA3, 0x22, 0x05,
9433 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
9434 0x46, 0x97, 0xCD, 0x04,
9435 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23,
9436 0x82, 0x01, 0x34, 0x85,
9437 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05,
9438 0x1D, 0x01, 0x04, 0xD6,
9439 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
9440 0x49, 0x00, 0x81, 0x01,
9441 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01,
9442 0x49, 0x04, 0x80, 0x01,
9443 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04,
9444 0x01, 0x23, 0xEA, 0x00,
9445 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
9446 0x07, 0xA4, 0xF8, 0x05,
9447 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00,
9448 0xC2, 0x88, 0x04, 0xA0,
9449 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61,
9450 0x00, 0xA2, 0xA4, 0x05,
9451 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
9452 0x62, 0x97, 0x04, 0x85,
9453 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05,
9454 0xF4, 0x85, 0x03, 0xA0,
9455 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63,
9456 0xCC, 0x86, 0x07, 0xA0,
9457 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
9458 0x80, 0x67, 0x80, 0x63,
9459 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23,
9460 0xF8, 0x88, 0x07, 0x23,
9461 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00,
9462 0x00, 0x63, 0x4A, 0x00,
9463 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
9464 0x07, 0x41, 0x83, 0x03,
9465 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88,
9466 0x1D, 0x01, 0x01, 0xD6,
9467 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00,
9468 0x07, 0xA6, 0x7C, 0x05,
9469 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
9470 0x52, 0x00, 0x06, 0x61,
9471 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41,
9472 0x00, 0x63, 0x1D, 0x01,
9473 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23,
9474 0x07, 0x41, 0x00, 0x63,
9475 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
9476 0xDF, 0x00, 0x06, 0xA6,
9477 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33,
9478 0x00, 0x40, 0xC0, 0x20,
9479 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63,
9480 0x06, 0xA6, 0x94, 0x06,
9481 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
9482 0x40, 0x0E, 0x80, 0x63,
9483 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E,
9484 0x80, 0x63, 0x00, 0x43,
9485 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05,
9486 0x80, 0x67, 0x40, 0x0E,
9487 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
9488 0x07, 0xA6, 0xD6, 0x06,
9489 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00,
9490 0x0A, 0x2B, 0x07, 0xA6,
9491 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2,
9492 0xF4, 0x06, 0xC0, 0x0E,
9493 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
9494 0x81, 0x62, 0x04, 0x01,
9495 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
9496 0x8C, 0x06, 0x00, 0x33,
9497 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03,
9498 0x80, 0x63, 0x06, 0xA6,
9499 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
9500 0x00, 0x00, 0x80, 0x67,
9501 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05,
9502 0xBF, 0x23, 0x04, 0x61,
9503 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00,
9504 0x00, 0x01, 0xF2, 0x00,
9505 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
9506 0x80, 0x05, 0x81, 0x05,
9507 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00,
9508 0x70, 0x00, 0x81, 0x01,
9509 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04,
9510 0x70, 0x00, 0x80, 0x01,
9511 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
9512 0xF1, 0x00, 0x70, 0x00,
9513 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01,
9514 0x71, 0x04, 0x70, 0x00,
9515 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05,
9516 0xA3, 0x01, 0xA2, 0x01,
9517 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
9518 0xC4, 0x07, 0x00, 0x33,
9519 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8,
9520 0x48, 0x00, 0xB0, 0x01,
9521 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43,
9522 0x00, 0xA2, 0xE4, 0x07,
9523 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
9524 0x05, 0x05, 0x00, 0x63,
9525 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43,
9526 0x76, 0x08, 0x80, 0x02,
9527 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
9528 0x00, 0x02, 0x00, 0xA0,
9529 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
9530 0x00, 0x63, 0xF3, 0x04,
9531 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40,
9532 0x00, 0xA2, 0x44, 0x08,
9533 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1,
9534 0x24, 0x08, 0x04, 0x98,
9535 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
9536 0x5A, 0x88, 0x02, 0x01,
9537 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00,
9538 0x00, 0xA3, 0x64, 0x08,
9539 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63,
9540 0x06, 0xA6, 0x76, 0x08,
9541 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
9542 0x00, 0x63, 0x38, 0x2B,
9543 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98,
9544 0x05, 0x05, 0xB2, 0x09,
9545 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63,
9546 0x80, 0x32, 0x80, 0x36,
9547 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
9548 0x40, 0x36, 0x40, 0x3A,
9549 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08,
9550 0x5D, 0x00, 0xFE, 0xC3,
9551 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73,
9552 0xFF, 0xFD, 0x80, 0x73,
9553 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
9554 0xA1, 0x23, 0xA1, 0x01,
9555 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2,
9556 0x80, 0x00, 0x03, 0xC2,
9557 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23,
9558 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009559};
9560
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009561static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
9562static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009563
9564#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009565static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
9566 INQUIRY,
9567 REQUEST_SENSE,
9568 READ_CAPACITY,
9569 READ_TOC,
9570 MODE_SELECT,
9571 MODE_SENSE,
9572 MODE_SELECT_10,
9573 MODE_SENSE_10,
9574 0xFF,
9575 0xFF,
9576 0xFF,
9577 0xFF,
9578 0xFF,
9579 0xFF,
9580 0xFF,
9581 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07009582};
9583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009584static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009585{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009586 PortAddr iop_base;
9587 ulong last_int_level;
9588 int sta;
9589 int n_q_required;
9590 int disable_syn_offset_one_fix;
9591 int i;
9592 ASC_PADDR addr;
9593 ASC_EXE_CALLBACK asc_exe_callback;
9594 ushort sg_entry_cnt = 0;
9595 ushort sg_entry_cnt_minus_one = 0;
9596 uchar target_ix;
9597 uchar tid_no;
9598 uchar sdtr_data;
9599 uchar extra_bytes;
9600 uchar scsi_cmd;
9601 uchar disable_cmd;
9602 ASC_SG_HEAD *sg_head;
9603 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009604
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009605 iop_base = asc_dvc->iop_base;
9606 sg_head = scsiq->sg_head;
9607 asc_exe_callback = asc_dvc->exe_callback;
9608 if (asc_dvc->err_code != 0)
9609 return (ERR);
9610 if (scsiq == (ASC_SCSI_Q *)0L) {
9611 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
9612 return (ERR);
9613 }
9614 scsiq->q1.q_no = 0;
9615 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
9616 scsiq->q1.extra_bytes = 0;
9617 }
9618 sta = 0;
9619 target_ix = scsiq->q2.target_ix;
9620 tid_no = ASC_TIX_TO_TID(target_ix);
9621 n_q_required = 1;
9622 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
9623 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
9624 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
9625 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9626 AscMsgOutSDTR(asc_dvc,
9627 asc_dvc->
9628 sdtr_period_tbl[(sdtr_data >> 4) &
9629 (uchar)(asc_dvc->
9630 max_sdtr_index -
9631 1)],
9632 (uchar)(sdtr_data & (uchar)
9633 ASC_SYN_MAX_OFFSET));
9634 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
9635 }
9636 }
9637 last_int_level = DvcEnterCritical();
9638 if (asc_dvc->in_critical_cnt != 0) {
9639 DvcLeaveCritical(last_int_level);
9640 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
9641 return (ERR);
9642 }
9643 asc_dvc->in_critical_cnt++;
9644 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
9645 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
9646 asc_dvc->in_critical_cnt--;
9647 DvcLeaveCritical(last_int_level);
9648 return (ERR);
9649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009650#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009651 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
9652 asc_dvc->in_critical_cnt--;
9653 DvcLeaveCritical(last_int_level);
9654 return (ERR);
9655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009656#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009657 if (sg_entry_cnt == 1) {
9658 scsiq->q1.data_addr =
9659 (ADV_PADDR)sg_head->sg_list[0].addr;
9660 scsiq->q1.data_cnt =
9661 (ADV_DCNT)sg_head->sg_list[0].bytes;
9662 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
9663 }
9664 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
9665 }
9666 scsi_cmd = scsiq->cdbptr[0];
9667 disable_syn_offset_one_fix = FALSE;
9668 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
9669 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
9670 if (scsiq->q1.cntl & QC_SG_HEAD) {
9671 data_cnt = 0;
9672 for (i = 0; i < sg_entry_cnt; i++) {
9673 data_cnt +=
9674 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
9675 bytes);
9676 }
9677 } else {
9678 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
9679 }
9680 if (data_cnt != 0UL) {
9681 if (data_cnt < 512UL) {
9682 disable_syn_offset_one_fix = TRUE;
9683 } else {
9684 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
9685 i++) {
9686 disable_cmd =
9687 _syn_offset_one_disable_cmd[i];
9688 if (disable_cmd == 0xFF) {
9689 break;
9690 }
9691 if (scsi_cmd == disable_cmd) {
9692 disable_syn_offset_one_fix =
9693 TRUE;
9694 break;
9695 }
9696 }
9697 }
9698 }
9699 }
9700 if (disable_syn_offset_one_fix) {
9701 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
9702 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
9703 ASC_TAG_FLAG_DISABLE_DISCONNECT);
9704 } else {
9705 scsiq->q2.tag_code &= 0x27;
9706 }
9707 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
9708 if (asc_dvc->bug_fix_cntl) {
9709 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
9710 if ((scsi_cmd == READ_6) ||
9711 (scsi_cmd == READ_10)) {
9712 addr =
9713 (ADV_PADDR)le32_to_cpu(sg_head->
9714 sg_list
9715 [sg_entry_cnt_minus_one].
9716 addr) +
9717 (ADV_DCNT)le32_to_cpu(sg_head->
9718 sg_list
9719 [sg_entry_cnt_minus_one].
9720 bytes);
9721 extra_bytes =
9722 (uchar)((ushort)addr & 0x0003);
9723 if ((extra_bytes != 0)
9724 &&
9725 ((scsiq->q2.
9726 tag_code &
9727 ASC_TAG_FLAG_EXTRA_BYTES)
9728 == 0)) {
9729 scsiq->q2.tag_code |=
9730 ASC_TAG_FLAG_EXTRA_BYTES;
9731 scsiq->q1.extra_bytes =
9732 extra_bytes;
9733 data_cnt =
9734 le32_to_cpu(sg_head->
9735 sg_list
9736 [sg_entry_cnt_minus_one].
9737 bytes);
9738 data_cnt -=
9739 (ASC_DCNT) extra_bytes;
9740 sg_head->
9741 sg_list
9742 [sg_entry_cnt_minus_one].
9743 bytes =
9744 cpu_to_le32(data_cnt);
9745 }
9746 }
9747 }
9748 }
9749 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009750#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009751 /*
9752 * Set the sg_entry_cnt to the maximum possible. The rest of
9753 * the SG elements will be copied when the RISC completes the
9754 * SG elements that fit and halts.
9755 */
9756 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
9757 sg_entry_cnt = ASC_MAX_SG_LIST;
9758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009759#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009760 n_q_required = AscSgListToQueue(sg_entry_cnt);
9761 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
9762 (uint) n_q_required)
9763 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
9764 if ((sta =
9765 AscSendScsiQueue(asc_dvc, scsiq,
9766 n_q_required)) == 1) {
9767 asc_dvc->in_critical_cnt--;
9768 if (asc_exe_callback != 0) {
9769 (*asc_exe_callback) (asc_dvc, scsiq);
9770 }
9771 DvcLeaveCritical(last_int_level);
9772 return (sta);
9773 }
9774 }
9775 } else {
9776 if (asc_dvc->bug_fix_cntl) {
9777 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
9778 if ((scsi_cmd == READ_6) ||
9779 (scsi_cmd == READ_10)) {
9780 addr =
9781 le32_to_cpu(scsiq->q1.data_addr) +
9782 le32_to_cpu(scsiq->q1.data_cnt);
9783 extra_bytes =
9784 (uchar)((ushort)addr & 0x0003);
9785 if ((extra_bytes != 0)
9786 &&
9787 ((scsiq->q2.
9788 tag_code &
9789 ASC_TAG_FLAG_EXTRA_BYTES)
9790 == 0)) {
9791 data_cnt =
9792 le32_to_cpu(scsiq->q1.
9793 data_cnt);
9794 if (((ushort)data_cnt & 0x01FF)
9795 == 0) {
9796 scsiq->q2.tag_code |=
9797 ASC_TAG_FLAG_EXTRA_BYTES;
9798 data_cnt -= (ASC_DCNT)
9799 extra_bytes;
9800 scsiq->q1.data_cnt =
9801 cpu_to_le32
9802 (data_cnt);
9803 scsiq->q1.extra_bytes =
9804 extra_bytes;
9805 }
9806 }
9807 }
9808 }
9809 }
9810 n_q_required = 1;
9811 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
9812 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
9813 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
9814 n_q_required)) == 1) {
9815 asc_dvc->in_critical_cnt--;
9816 if (asc_exe_callback != 0) {
9817 (*asc_exe_callback) (asc_dvc, scsiq);
9818 }
9819 DvcLeaveCritical(last_int_level);
9820 return (sta);
9821 }
9822 }
9823 }
9824 asc_dvc->in_critical_cnt--;
9825 DvcLeaveCritical(last_int_level);
9826 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009827}
9828
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009829static int
9830AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009831{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009832 PortAddr iop_base;
9833 uchar free_q_head;
9834 uchar next_qp;
9835 uchar tid_no;
9836 uchar target_ix;
9837 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009838
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009839 iop_base = asc_dvc->iop_base;
9840 target_ix = scsiq->q2.target_ix;
9841 tid_no = ASC_TIX_TO_TID(target_ix);
9842 sta = 0;
9843 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
9844 if (n_q_required > 1) {
9845 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
9846 free_q_head, (uchar)
9847 (n_q_required)))
9848 != (uchar)ASC_QLINK_END) {
9849 asc_dvc->last_q_shortage = 0;
9850 scsiq->sg_head->queue_cnt = n_q_required - 1;
9851 scsiq->q1.q_no = free_q_head;
9852 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
9853 free_q_head)) == 1) {
9854 AscPutVarFreeQHead(iop_base, next_qp);
9855 asc_dvc->cur_total_qng += (uchar)(n_q_required);
9856 asc_dvc->cur_dvc_qng[tid_no]++;
9857 }
9858 return (sta);
9859 }
9860 } else if (n_q_required == 1) {
9861 if ((next_qp = AscAllocFreeQueue(iop_base,
9862 free_q_head)) !=
9863 ASC_QLINK_END) {
9864 scsiq->q1.q_no = free_q_head;
9865 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
9866 free_q_head)) == 1) {
9867 AscPutVarFreeQHead(iop_base, next_qp);
9868 asc_dvc->cur_total_qng++;
9869 asc_dvc->cur_dvc_qng[tid_no]++;
9870 }
9871 return (sta);
9872 }
9873 }
9874 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009875}
9876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009877static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009878{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009879 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009881 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
9882 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
9883 n_sg_list_qs++;
9884 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009885}
9886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009887static uint
9888AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009889{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009890 uint cur_used_qs;
9891 uint cur_free_qs;
9892 ASC_SCSI_BIT_ID_TYPE target_id;
9893 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009894
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009895 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
9896 tid_no = ASC_TIX_TO_TID(target_ix);
9897 if ((asc_dvc->unit_not_ready & target_id) ||
9898 (asc_dvc->queue_full_or_busy & target_id)) {
9899 return (0);
9900 }
9901 if (n_qs == 1) {
9902 cur_used_qs = (uint) asc_dvc->cur_total_qng +
9903 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
9904 } else {
9905 cur_used_qs = (uint) asc_dvc->cur_total_qng +
9906 (uint) ASC_MIN_FREE_Q;
9907 }
9908 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
9909 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
9910 if (asc_dvc->cur_dvc_qng[tid_no] >=
9911 asc_dvc->max_dvc_qng[tid_no]) {
9912 return (0);
9913 }
9914 return (cur_free_qs);
9915 }
9916 if (n_qs > 1) {
9917 if ((n_qs > asc_dvc->last_q_shortage)
9918 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
9919 asc_dvc->last_q_shortage = n_qs;
9920 }
9921 }
9922 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009923}
9924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009925static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009926{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009927 ushort q_addr;
9928 uchar tid_no;
9929 uchar sdtr_data;
9930 uchar syn_period_ix;
9931 uchar syn_offset;
9932 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009933
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009934 iop_base = asc_dvc->iop_base;
9935 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
9936 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
9937 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
9938 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9939 syn_period_ix =
9940 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
9941 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
9942 AscMsgOutSDTR(asc_dvc,
9943 asc_dvc->sdtr_period_tbl[syn_period_ix],
9944 syn_offset);
9945 scsiq->q1.cntl |= QC_MSG_OUT;
9946 }
9947 q_addr = ASC_QNO_TO_QADDR(q_no);
9948 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
9949 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
9950 }
9951 scsiq->q1.status = QS_FREE;
9952 AscMemWordCopyPtrToLram(iop_base,
9953 q_addr + ASC_SCSIQ_CDB_BEG,
9954 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009955
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009956 DvcPutScsiQ(iop_base,
9957 q_addr + ASC_SCSIQ_CPY_BEG,
9958 (uchar *)&scsiq->q1.cntl,
9959 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
9960 AscWriteLramWord(iop_base,
9961 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
9962 (ushort)(((ushort)scsiq->q1.
9963 q_no << 8) | (ushort)QS_READY));
9964 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009965}
9966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009967static int
9968AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009969{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009970 int sta;
9971 int i;
9972 ASC_SG_HEAD *sg_head;
9973 ASC_SG_LIST_Q scsi_sg_q;
9974 ASC_DCNT saved_data_addr;
9975 ASC_DCNT saved_data_cnt;
9976 PortAddr iop_base;
9977 ushort sg_list_dwords;
9978 ushort sg_index;
9979 ushort sg_entry_cnt;
9980 ushort q_addr;
9981 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009982
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009983 iop_base = asc_dvc->iop_base;
9984 sg_head = scsiq->sg_head;
9985 saved_data_addr = scsiq->q1.data_addr;
9986 saved_data_cnt = scsiq->q1.data_cnt;
9987 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
9988 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009989#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009990 /*
9991 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
9992 * then not all SG elements will fit in the allocated queues.
9993 * The rest of the SG elements will be copied when the RISC
9994 * completes the SG elements that fit and halts.
9995 */
9996 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
9997 /*
9998 * Set sg_entry_cnt to be the number of SG elements that
9999 * will fit in the allocated SG queues. It is minus 1, because
10000 * the first SG element is handled above. ASC_MAX_SG_LIST is
10001 * already inflated by 1 to account for this. For example it
10002 * may be 50 which is 1 + 7 queues * 7 SG elements.
10003 */
10004 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010005
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010006 /*
10007 * Keep track of remaining number of SG elements that will
10008 * need to be handled from a_isr.c.
10009 */
10010 scsiq->remain_sg_entry_cnt =
10011 sg_head->entry_cnt - ASC_MAX_SG_LIST;
10012 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010013#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010014 /*
10015 * Set sg_entry_cnt to be the number of SG elements that
10016 * will fit in the allocated SG queues. It is minus 1, because
10017 * the first SG element is handled above.
10018 */
10019 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010020#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010022#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010023 if (sg_entry_cnt != 0) {
10024 scsiq->q1.cntl |= QC_SG_HEAD;
10025 q_addr = ASC_QNO_TO_QADDR(q_no);
10026 sg_index = 1;
10027 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
10028 scsi_sg_q.sg_head_qp = q_no;
10029 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
10030 for (i = 0; i < sg_head->queue_cnt; i++) {
10031 scsi_sg_q.seq_no = i + 1;
10032 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
10033 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
10034 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
10035 if (i == 0) {
10036 scsi_sg_q.sg_list_cnt =
10037 ASC_SG_LIST_PER_Q;
10038 scsi_sg_q.sg_cur_list_cnt =
10039 ASC_SG_LIST_PER_Q;
10040 } else {
10041 scsi_sg_q.sg_list_cnt =
10042 ASC_SG_LIST_PER_Q - 1;
10043 scsi_sg_q.sg_cur_list_cnt =
10044 ASC_SG_LIST_PER_Q - 1;
10045 }
10046 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010047#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010048 /*
10049 * This is the last SG queue in the list of
10050 * allocated SG queues. If there are more
10051 * SG elements than will fit in the allocated
10052 * queues, then set the QCSG_SG_XFER_MORE flag.
10053 */
10054 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10055 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
10056 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010057#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010058 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010059#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010060 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010061#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010062 sg_list_dwords = sg_entry_cnt << 1;
10063 if (i == 0) {
10064 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
10065 scsi_sg_q.sg_cur_list_cnt =
10066 sg_entry_cnt;
10067 } else {
10068 scsi_sg_q.sg_list_cnt =
10069 sg_entry_cnt - 1;
10070 scsi_sg_q.sg_cur_list_cnt =
10071 sg_entry_cnt - 1;
10072 }
10073 sg_entry_cnt = 0;
10074 }
10075 next_qp = AscReadLramByte(iop_base,
10076 (ushort)(q_addr +
10077 ASC_SCSIQ_B_FWD));
10078 scsi_sg_q.q_no = next_qp;
10079 q_addr = ASC_QNO_TO_QADDR(next_qp);
10080 AscMemWordCopyPtrToLram(iop_base,
10081 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
10082 (uchar *)&scsi_sg_q,
10083 sizeof(ASC_SG_LIST_Q) >> 1);
10084 AscMemDWordCopyPtrToLram(iop_base,
10085 q_addr + ASC_SGQ_LIST_BEG,
10086 (uchar *)&sg_head->
10087 sg_list[sg_index],
10088 sg_list_dwords);
10089 sg_index += ASC_SG_LIST_PER_Q;
10090 scsiq->next_sg_index = sg_index;
10091 }
10092 } else {
10093 scsiq->q1.cntl &= ~QC_SG_HEAD;
10094 }
10095 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
10096 scsiq->q1.data_addr = saved_data_addr;
10097 scsiq->q1.data_cnt = saved_data_cnt;
10098 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010099}
10100
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010101static int
10102AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010103{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010104 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010105
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010106 if (AscHostReqRiscHalt(iop_base)) {
10107 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
10108 AscStartChip(iop_base);
10109 return (sta);
10110 }
10111 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010112}
10113
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010114static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010115{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010116 ASC_SCSI_BIT_ID_TYPE org_id;
10117 int i;
10118 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010119
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010120 AscSetBank(iop_base, 1);
10121 org_id = AscReadChipDvcID(iop_base);
10122 for (i = 0; i <= ASC_MAX_TID; i++) {
10123 if (org_id == (0x01 << i))
10124 break;
10125 }
10126 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
10127 AscWriteChipDvcID(iop_base, id);
10128 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
10129 AscSetBank(iop_base, 0);
10130 AscSetChipSyn(iop_base, sdtr_data);
10131 if (AscGetChipSyn(iop_base) != sdtr_data) {
10132 sta = FALSE;
10133 }
10134 } else {
10135 sta = FALSE;
10136 }
10137 AscSetBank(iop_base, 1);
10138 AscWriteChipDvcID(iop_base, org_id);
10139 AscSetBank(iop_base, 0);
10140 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010141}
10142
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010143static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010144{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010145 uchar i;
10146 ushort s_addr;
10147 PortAddr iop_base;
10148 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010149
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010150 iop_base = asc_dvc->iop_base;
10151 warn_code = 0;
10152 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
10153 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
10154 64) >> 1)
10155 );
10156 i = ASC_MIN_ACTIVE_QNO;
10157 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
10158 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
10159 (uchar)(i + 1));
10160 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
10161 (uchar)(asc_dvc->max_total_qng));
10162 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
10163 (uchar)i);
10164 i++;
10165 s_addr += ASC_QBLK_SIZE;
10166 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
10167 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
10168 (uchar)(i + 1));
10169 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
10170 (uchar)(i - 1));
10171 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
10172 (uchar)i);
10173 }
10174 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
10175 (uchar)ASC_QLINK_END);
10176 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
10177 (uchar)(asc_dvc->max_total_qng - 1));
10178 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
10179 (uchar)asc_dvc->max_total_qng);
10180 i++;
10181 s_addr += ASC_QBLK_SIZE;
10182 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
10183 i++, s_addr += ASC_QBLK_SIZE) {
10184 AscWriteLramByte(iop_base,
10185 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
10186 AscWriteLramByte(iop_base,
10187 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
10188 AscWriteLramByte(iop_base,
10189 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
10190 }
10191 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010192}
10193
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010194static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010195{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010196 PortAddr iop_base;
10197 int i;
10198 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010200 iop_base = asc_dvc->iop_base;
10201 AscPutRiscVarFreeQHead(iop_base, 1);
10202 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
10203 AscPutVarFreeQHead(iop_base, 1);
10204 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
10205 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
10206 (uchar)((int)asc_dvc->max_total_qng + 1));
10207 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
10208 (uchar)((int)asc_dvc->max_total_qng + 2));
10209 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
10210 asc_dvc->max_total_qng);
10211 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
10212 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10213 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
10214 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
10215 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
10216 AscPutQDoneInProgress(iop_base, 0);
10217 lram_addr = ASC_QADR_BEG;
10218 for (i = 0; i < 32; i++, lram_addr += 2) {
10219 AscWriteLramWord(iop_base, lram_addr, 0);
10220 }
10221 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010222}
10223
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010224static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010225{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010226 if (asc_dvc->err_code == 0) {
10227 asc_dvc->err_code = err_code;
10228 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
10229 err_code);
10230 }
10231 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010232}
10233
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010234static uchar
10235AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010236{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010237 EXT_MSG sdtr_buf;
10238 uchar sdtr_period_index;
10239 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010241 iop_base = asc_dvc->iop_base;
10242 sdtr_buf.msg_type = MS_EXTEND;
10243 sdtr_buf.msg_len = MS_SDTR_LEN;
10244 sdtr_buf.msg_req = MS_SDTR_CODE;
10245 sdtr_buf.xfer_period = sdtr_period;
10246 sdtr_offset &= ASC_SYN_MAX_OFFSET;
10247 sdtr_buf.req_ack_offset = sdtr_offset;
10248 if ((sdtr_period_index =
10249 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
10250 asc_dvc->max_sdtr_index) {
10251 AscMemWordCopyPtrToLram(iop_base,
10252 ASCV_MSGOUT_BEG,
10253 (uchar *)&sdtr_buf,
10254 sizeof(EXT_MSG) >> 1);
10255 return ((sdtr_period_index << 4) | sdtr_offset);
10256 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010257
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010258 sdtr_buf.req_ack_offset = 0;
10259 AscMemWordCopyPtrToLram(iop_base,
10260 ASCV_MSGOUT_BEG,
10261 (uchar *)&sdtr_buf,
10262 sizeof(EXT_MSG) >> 1);
10263 return (0);
10264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010265}
10266
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010267static uchar
10268AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010269{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010270 uchar byte;
10271 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010272
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010273 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
10274 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
10275 ) {
10276 return (0xFF);
10277 }
10278 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
10279 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010280}
10281
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010282static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010283{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010284 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
10285 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
10286 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010287}
10288
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010289static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010290{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010291 uchar *period_table;
10292 int max_index;
10293 int min_index;
10294 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010295
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010296 period_table = asc_dvc->sdtr_period_tbl;
10297 max_index = (int)asc_dvc->max_sdtr_index;
10298 min_index = (int)asc_dvc->host_init_sdtr_index;
10299 if ((syn_time <= period_table[max_index])) {
10300 for (i = min_index; i < (max_index - 1); i++) {
10301 if (syn_time <= period_table[i]) {
10302 return ((uchar)i);
10303 }
10304 }
10305 return ((uchar)max_index);
10306 } else {
10307 return ((uchar)(max_index + 1));
10308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010309}
10310
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010311static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010312{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010313 ushort q_addr;
10314 uchar next_qp;
10315 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010316
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010317 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10318 q_status = (uchar)AscReadLramByte(iop_base,
10319 (ushort)(q_addr +
10320 ASC_SCSIQ_B_STATUS));
10321 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10322 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
10323 return (next_qp);
10324 }
10325 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010326}
10327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010328static uchar
10329AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010330{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010331 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010332
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010333 for (i = 0; i < n_free_q; i++) {
10334 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
10335 == ASC_QLINK_END) {
10336 return (ASC_QLINK_END);
10337 }
10338 }
10339 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010340}
10341
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010342static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010343{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010344 int count = 0;
10345 int sta = 0;
10346 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010347
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010348 if (AscIsChipHalted(iop_base))
10349 return (1);
10350 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
10351 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
10352 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
10353 do {
10354 if (AscIsChipHalted(iop_base)) {
10355 sta = 1;
10356 break;
10357 }
10358 DvcSleepMilliSecond(100);
10359 } while (count++ < 20);
10360 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
10361 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010362}
10363
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010364static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010365{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010366 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010367
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010368 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
10369 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
10370 ASC_STOP_REQ_RISC_STOP);
10371 do {
10372 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
10373 ASC_STOP_ACK_RISC_STOP) {
10374 return (1);
10375 }
10376 DvcSleepMilliSecond(100);
10377 } while (count++ < 20);
10378 }
10379 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010380}
10381
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010382static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010383{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010384 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010385}
10386
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010387static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010388{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010389 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010390}
10391
10392#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010393static ASC_DCNT __init AscGetEisaProductID(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010394{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010395 PortAddr eisa_iop;
10396 ushort product_id_high, product_id_low;
10397 ASC_DCNT product_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010398
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010399 eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
10400 product_id_low = inpw(eisa_iop);
10401 product_id_high = inpw(eisa_iop + 2);
10402 product_id = ((ASC_DCNT) product_id_high << 16) |
10403 (ASC_DCNT) product_id_low;
10404 return (product_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010405}
10406
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010407static PortAddr __init AscSearchIOPortAddrEISA(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010408{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010409 ASC_DCNT eisa_product_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010410
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010411 if (iop_base == 0) {
10412 iop_base = ASC_EISA_MIN_IOP_ADDR;
10413 } else {
10414 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
10415 return (0);
10416 if ((iop_base & 0x0050) == 0x0050) {
10417 iop_base += ASC_EISA_BIG_IOP_GAP;
10418 } else {
10419 iop_base += ASC_EISA_SMALL_IOP_GAP;
10420 }
10421 }
10422 while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
10423 eisa_product_id = AscGetEisaProductID(iop_base);
10424 if ((eisa_product_id == ASC_EISA_ID_740) ||
10425 (eisa_product_id == ASC_EISA_ID_750)) {
10426 if (AscFindSignature(iop_base)) {
10427 inpw(iop_base + 4);
10428 return (iop_base);
10429 }
10430 }
10431 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
10432 return (0);
10433 if ((iop_base & 0x0050) == 0x0050) {
10434 iop_base += ASC_EISA_BIG_IOP_GAP;
10435 } else {
10436 iop_base += ASC_EISA_SMALL_IOP_GAP;
10437 }
10438 }
10439 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010440}
10441#endif /* CONFIG_ISA */
10442
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010443static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010444{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010445 AscSetChipControl(iop_base, 0);
10446 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
10447 return (0);
10448 }
10449 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010450}
10451
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010452static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010453{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010454 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010455
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010456 cc_val =
10457 AscGetChipControl(iop_base) &
10458 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
10459 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
10460 AscSetChipIH(iop_base, INS_HALT);
10461 AscSetChipIH(iop_base, INS_RFLAG_WTM);
10462 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
10463 return (0);
10464 }
10465 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010466}
10467
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010468static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010469{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010470 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
10471 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
10472 return (1);
10473 }
10474 }
10475 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010476}
10477
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010478static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010479{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010480 AscSetBank(iop_base, 1);
10481 AscWriteChipIH(iop_base, ins_code);
10482 AscSetBank(iop_base, 0);
10483 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010484}
10485
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010486static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010487{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010488 uchar host_flag;
10489 uchar risc_flag;
10490 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010491
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010492 loop = 0;
10493 do {
10494 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
10495 if (loop++ > 0x7FFF) {
10496 break;
10497 }
10498 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
10499 host_flag =
10500 AscReadLramByte(iop_base,
10501 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
10502 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
10503 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
10504 AscSetChipStatus(iop_base, CIW_INT_ACK);
10505 loop = 0;
10506 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
10507 AscSetChipStatus(iop_base, CIW_INT_ACK);
10508 if (loop++ > 3) {
10509 break;
10510 }
10511 }
10512 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
10513 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010514}
10515
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010516static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010517{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010518 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010519
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010520 cfg = AscGetChipCfgLsw(iop_base);
10521 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
10522 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010523}
10524
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010525static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010526{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010527 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010528
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010529 cfg = AscGetChipCfgLsw(iop_base);
10530 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
10531 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010532}
10533
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010534static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010535{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010536 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010537
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010538 val = AscGetChipControl(iop_base) &
10539 (~
10540 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
10541 CC_CHIP_RESET));
10542 if (bank == 1) {
10543 val |= CC_BANK_ONE;
10544 } else if (bank == 2) {
10545 val |= CC_DIAG | CC_BANK_ONE;
10546 } else {
10547 val &= ~CC_BANK_ONE;
10548 }
10549 AscSetChipControl(iop_base, val);
10550 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010551}
10552
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010553static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010554{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010555 PortAddr iop_base;
10556 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010557
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010558 iop_base = asc_dvc->iop_base;
10559 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
10560 && (i-- > 0)) {
10561 DvcSleepMilliSecond(100);
10562 }
10563 AscStopChip(iop_base);
10564 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
10565 DvcDelayNanoSecond(asc_dvc, 60000);
10566 AscSetChipIH(iop_base, INS_RFLAG_WTM);
10567 AscSetChipIH(iop_base, INS_HALT);
10568 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
10569 AscSetChipControl(iop_base, CC_HALT);
10570 DvcSleepMilliSecond(200);
10571 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
10572 AscSetChipStatus(iop_base, 0);
10573 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010574}
10575
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010576static ASC_DCNT __init AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010577{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010578 if (bus_type & ASC_IS_ISA)
10579 return (ASC_MAX_ISA_DMA_COUNT);
10580 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
10581 return (ASC_MAX_VL_DMA_COUNT);
10582 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010583}
10584
10585#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010586static ushort __init AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010587{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010588 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010589
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010590 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
10591 if (channel == 0x03)
10592 return (0);
10593 else if (channel == 0x00)
10594 return (7);
10595 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010596}
10597
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010598static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010599{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010600 ushort cfg_lsw;
10601 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010602
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010603 if ((dma_channel >= 5) && (dma_channel <= 7)) {
10604 if (dma_channel == 7)
10605 value = 0x00;
10606 else
10607 value = dma_channel - 4;
10608 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
10609 cfg_lsw |= value;
10610 AscSetChipCfgLsw(iop_base, cfg_lsw);
10611 return (AscGetIsaDmaChannel(iop_base));
10612 }
10613 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010614}
10615
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010616static uchar __init AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010617{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010618 speed_value &= 0x07;
10619 AscSetBank(iop_base, 1);
10620 AscWriteChipDmaSpeed(iop_base, speed_value);
10621 AscSetBank(iop_base, 0);
10622 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010623}
10624
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010625static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010626{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010627 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010628
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010629 AscSetBank(iop_base, 1);
10630 speed_value = AscReadChipDmaSpeed(iop_base);
10631 speed_value &= 0x07;
10632 AscSetBank(iop_base, 0);
10633 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010634}
10635#endif /* CONFIG_ISA */
10636
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010637static ushort __init
10638AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010639{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010640 uchar lsb, msb;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010641
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010642 lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
10643 msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
10644 return ((ushort)((msb << 8) | lsb));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010645}
10646
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010647static ushort __init AscInitGetConfig(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010648{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010649 ushort warn_code;
10650 PortAddr iop_base;
10651 ushort PCIDeviceID;
10652 ushort PCIVendorID;
10653 uchar PCIRevisionID;
10654 uchar prevCmdRegBits;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010655
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010656 warn_code = 0;
10657 iop_base = asc_dvc->iop_base;
10658 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
10659 if (asc_dvc->err_code != 0) {
10660 return (UW_ERR);
10661 }
10662 if (asc_dvc->bus_type == ASC_IS_PCI) {
10663 PCIVendorID = AscReadPCIConfigWord(asc_dvc,
10664 AscPCIConfigVendorIDRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010665
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010666 PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
10667 AscPCIConfigDeviceIDRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010668
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010669 PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
10670 AscPCIConfigRevisionIDRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010671
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010672 if (PCIVendorID != PCI_VENDOR_ID_ASP) {
10673 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
10674 }
10675 prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
10676 AscPCIConfigCommandRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010677
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010678 if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
10679 AscPCICmdRegBits_IOMemBusMaster) {
10680 DvcWritePCIConfigByte(asc_dvc,
10681 AscPCIConfigCommandRegister,
10682 (prevCmdRegBits |
10683 AscPCICmdRegBits_IOMemBusMaster));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010684
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010685 if ((DvcReadPCIConfigByte(asc_dvc,
10686 AscPCIConfigCommandRegister)
10687 & AscPCICmdRegBits_IOMemBusMaster)
10688 != AscPCICmdRegBits_IOMemBusMaster) {
10689 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
10690 }
10691 }
10692 if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) ||
10693 (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) {
10694 DvcWritePCIConfigByte(asc_dvc,
10695 AscPCIConfigLatencyTimer, 0x00);
10696 if (DvcReadPCIConfigByte
10697 (asc_dvc, AscPCIConfigLatencyTimer)
10698 != 0x00) {
10699 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
10700 }
10701 } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) {
10702 if (DvcReadPCIConfigByte(asc_dvc,
10703 AscPCIConfigLatencyTimer) <
10704 0x20) {
10705 DvcWritePCIConfigByte(asc_dvc,
10706 AscPCIConfigLatencyTimer,
10707 0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010708
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010709 if (DvcReadPCIConfigByte(asc_dvc,
10710 AscPCIConfigLatencyTimer)
10711 < 0x20) {
10712 warn_code |=
10713 ASC_WARN_SET_PCI_CONFIG_SPACE;
10714 }
10715 }
10716 }
10717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010718
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010719 if (AscFindSignature(iop_base)) {
10720 warn_code |= AscInitAscDvcVar(asc_dvc);
10721 warn_code |= AscInitFromEEP(asc_dvc);
10722 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
10723 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
10724 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
10725 }
10726 } else {
10727 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10728 }
10729 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010730}
10731
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010732static ushort __init AscInitSetConfig(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010733{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010734 ushort warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010735
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010736 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
10737 if (asc_dvc->err_code != 0)
10738 return (UW_ERR);
10739 if (AscFindSignature(asc_dvc->iop_base)) {
10740 warn_code |= AscInitFromAscDvcVar(asc_dvc);
10741 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
10742 } else {
10743 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10744 }
10745 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010746}
10747
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010748static ushort __init AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010749{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010750 PortAddr iop_base;
10751 ushort cfg_msw;
10752 ushort warn_code;
10753 ushort pci_device_id = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010754
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010755 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010756#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010757 if (asc_dvc->cfg->dev)
10758 pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010759#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010760 warn_code = 0;
10761 cfg_msw = AscGetChipCfgMsw(iop_base);
10762 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
10763 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
10764 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
10765 AscSetChipCfgMsw(iop_base, cfg_msw);
10766 }
10767 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
10768 asc_dvc->cfg->cmd_qng_enabled) {
10769 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
10770 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
10771 }
10772 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
10773 warn_code |= ASC_WARN_AUTO_CONFIG;
10774 }
10775 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
10776 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
10777 != asc_dvc->irq_no) {
10778 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
10779 }
10780 }
10781 if (asc_dvc->bus_type & ASC_IS_PCI) {
10782 cfg_msw &= 0xFFC0;
10783 AscSetChipCfgMsw(iop_base, cfg_msw);
10784 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
10785 } else {
10786 if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) ||
10787 (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) {
10788 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
10789 asc_dvc->bug_fix_cntl |=
10790 ASC_BUG_FIX_ASYN_USE_SYN;
10791 }
10792 }
10793 } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
10794 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
10795 == ASC_CHIP_VER_ASYN_BUG) {
10796 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
10797 }
10798 }
10799 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
10800 asc_dvc->cfg->chip_scsi_id) {
10801 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
10802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010803#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010804 if (asc_dvc->bus_type & ASC_IS_ISA) {
10805 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
10806 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
10807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010808#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010809 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010810}
10811
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010812static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010813{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010814 ushort warn_code;
10815 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010816
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010817 iop_base = asc_dvc->iop_base;
10818 warn_code = 0;
10819 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
10820 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
10821 AscResetChipAndScsiBus(asc_dvc);
10822 DvcSleepMilliSecond((ASC_DCNT)
10823 ((ushort)asc_dvc->scsi_reset_wait * 1000));
10824 }
10825 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
10826 if (asc_dvc->err_code != 0)
10827 return (UW_ERR);
10828 if (!AscFindSignature(asc_dvc->iop_base)) {
10829 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10830 return (warn_code);
10831 }
10832 AscDisableInterrupt(iop_base);
10833 warn_code |= AscInitLram(asc_dvc);
10834 if (asc_dvc->err_code != 0)
10835 return (UW_ERR);
10836 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
10837 (ulong)_asc_mcode_chksum);
10838 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
10839 _asc_mcode_size) != _asc_mcode_chksum) {
10840 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
10841 return (warn_code);
10842 }
10843 warn_code |= AscInitMicroCodeVar(asc_dvc);
10844 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
10845 AscEnableInterrupt(iop_base);
10846 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010847}
10848
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010849static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010850{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010851 int i;
10852 PortAddr iop_base;
10853 ushort warn_code;
10854 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010855
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010856 iop_base = asc_dvc->iop_base;
10857 warn_code = 0;
10858 asc_dvc->err_code = 0;
10859 if ((asc_dvc->bus_type &
10860 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
10861 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
10862 }
10863 AscSetChipControl(iop_base, CC_HALT);
10864 AscSetChipStatus(iop_base, 0);
10865 asc_dvc->bug_fix_cntl = 0;
10866 asc_dvc->pci_fix_asyn_xfer = 0;
10867 asc_dvc->pci_fix_asyn_xfer_always = 0;
10868 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
10869 asc_dvc->sdtr_done = 0;
10870 asc_dvc->cur_total_qng = 0;
10871 asc_dvc->is_in_int = 0;
10872 asc_dvc->in_critical_cnt = 0;
10873 asc_dvc->last_q_shortage = 0;
10874 asc_dvc->use_tagged_qng = 0;
10875 asc_dvc->no_scam = 0;
10876 asc_dvc->unit_not_ready = 0;
10877 asc_dvc->queue_full_or_busy = 0;
10878 asc_dvc->redo_scam = 0;
10879 asc_dvc->res2 = 0;
10880 asc_dvc->host_init_sdtr_index = 0;
10881 asc_dvc->cfg->can_tagged_qng = 0;
10882 asc_dvc->cfg->cmd_qng_enabled = 0;
10883 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
10884 asc_dvc->init_sdtr = 0;
10885 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
10886 asc_dvc->scsi_reset_wait = 3;
10887 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
10888 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
10889 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
10890 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
10891 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
10892 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
10893 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
10894 ASC_LIB_VERSION_MINOR;
10895 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
10896 asc_dvc->cfg->chip_version = chip_version;
10897 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
10898 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
10899 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
10900 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
10901 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
10902 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
10903 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
10904 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
10905 asc_dvc->max_sdtr_index = 7;
10906 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
10907 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
10908 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
10909 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
10910 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
10911 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
10912 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
10913 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
10914 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
10915 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
10916 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
10917 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
10918 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
10919 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
10920 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
10921 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
10922 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
10923 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
10924 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
10925 asc_dvc->max_sdtr_index = 15;
10926 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
10927 AscSetExtraControl(iop_base,
10928 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
10929 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
10930 AscSetExtraControl(iop_base,
10931 (SEC_ACTIVE_NEGATE |
10932 SEC_ENABLE_FILTER));
10933 }
10934 }
10935 if (asc_dvc->bus_type == ASC_IS_PCI) {
10936 AscSetExtraControl(iop_base,
10937 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
10938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010940 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
10941 if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
10942 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
10943 asc_dvc->bus_type = ASC_IS_ISAPNP;
10944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010945#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010946 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
10947 asc_dvc->cfg->isa_dma_channel =
10948 (uchar)AscGetIsaDmaChannel(iop_base);
10949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010950#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010951 for (i = 0; i <= ASC_MAX_TID; i++) {
10952 asc_dvc->cur_dvc_qng[i] = 0;
10953 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
10954 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
10955 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
10956 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
10957 }
10958 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010959}
10960
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010961static ushort __init AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010962{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010963 ASCEEP_CONFIG eep_config_buf;
10964 ASCEEP_CONFIG *eep_config;
10965 PortAddr iop_base;
10966 ushort chksum;
10967 ushort warn_code;
10968 ushort cfg_msw, cfg_lsw;
10969 int i;
10970 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010971
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010972 iop_base = asc_dvc->iop_base;
10973 warn_code = 0;
10974 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
10975 AscStopQueueExe(iop_base);
10976 if ((AscStopChip(iop_base) == FALSE) ||
10977 (AscGetChipScsiCtrl(iop_base) != 0)) {
10978 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
10979 AscResetChipAndScsiBus(asc_dvc);
10980 DvcSleepMilliSecond((ASC_DCNT)
10981 ((ushort)asc_dvc->scsi_reset_wait * 1000));
10982 }
10983 if (AscIsChipHalted(iop_base) == FALSE) {
10984 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
10985 return (warn_code);
10986 }
10987 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
10988 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
10989 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
10990 return (warn_code);
10991 }
10992 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
10993 cfg_msw = AscGetChipCfgMsw(iop_base);
10994 cfg_lsw = AscGetChipCfgLsw(iop_base);
10995 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
10996 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
10997 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
10998 AscSetChipCfgMsw(iop_base, cfg_msw);
10999 }
11000 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
11001 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
11002 if (chksum == 0) {
11003 chksum = 0xaa55;
11004 }
11005 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
11006 warn_code |= ASC_WARN_AUTO_CONFIG;
11007 if (asc_dvc->cfg->chip_version == 3) {
11008 if (eep_config->cfg_lsw != cfg_lsw) {
11009 warn_code |= ASC_WARN_EEPROM_RECOVER;
11010 eep_config->cfg_lsw =
11011 AscGetChipCfgLsw(iop_base);
11012 }
11013 if (eep_config->cfg_msw != cfg_msw) {
11014 warn_code |= ASC_WARN_EEPROM_RECOVER;
11015 eep_config->cfg_msw =
11016 AscGetChipCfgMsw(iop_base);
11017 }
11018 }
11019 }
11020 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11021 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
11022 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
11023 eep_config->chksum);
11024 if (chksum != eep_config->chksum) {
11025 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
11026 ASC_CHIP_VER_PCI_ULTRA_3050) {
11027 ASC_DBG(1,
11028 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
11029 eep_config->init_sdtr = 0xFF;
11030 eep_config->disc_enable = 0xFF;
11031 eep_config->start_motor = 0xFF;
11032 eep_config->use_cmd_qng = 0;
11033 eep_config->max_total_qng = 0xF0;
11034 eep_config->max_tag_qng = 0x20;
11035 eep_config->cntl = 0xBFFF;
11036 ASC_EEP_SET_CHIP_ID(eep_config, 7);
11037 eep_config->no_scam = 0;
11038 eep_config->adapter_info[0] = 0;
11039 eep_config->adapter_info[1] = 0;
11040 eep_config->adapter_info[2] = 0;
11041 eep_config->adapter_info[3] = 0;
11042 eep_config->adapter_info[4] = 0;
11043 /* Indicate EEPROM-less board. */
11044 eep_config->adapter_info[5] = 0xBB;
11045 } else {
11046 ASC_PRINT
11047 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
11048 write_eep = 1;
11049 warn_code |= ASC_WARN_EEPROM_CHKSUM;
11050 }
11051 }
11052 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
11053 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
11054 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
11055 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
11056 asc_dvc->start_motor = eep_config->start_motor;
11057 asc_dvc->dvc_cntl = eep_config->cntl;
11058 asc_dvc->no_scam = eep_config->no_scam;
11059 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
11060 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
11061 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
11062 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
11063 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
11064 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
11065 if (!AscTestExternalLram(asc_dvc)) {
11066 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
11067 ASC_IS_PCI_ULTRA)) {
11068 eep_config->max_total_qng =
11069 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
11070 eep_config->max_tag_qng =
11071 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
11072 } else {
11073 eep_config->cfg_msw |= 0x0800;
11074 cfg_msw |= 0x0800;
11075 AscSetChipCfgMsw(iop_base, cfg_msw);
11076 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
11077 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
11078 }
11079 } else {
11080 }
11081 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
11082 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
11083 }
11084 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
11085 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
11086 }
11087 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
11088 eep_config->max_tag_qng = eep_config->max_total_qng;
11089 }
11090 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
11091 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
11092 }
11093 asc_dvc->max_total_qng = eep_config->max_total_qng;
11094 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
11095 eep_config->use_cmd_qng) {
11096 eep_config->disc_enable = eep_config->use_cmd_qng;
11097 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
11098 }
11099 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
11100 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
11101 }
11102 ASC_EEP_SET_CHIP_ID(eep_config,
11103 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
11104 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
11105 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
11106 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
11107 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
11108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011109
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011110 for (i = 0; i <= ASC_MAX_TID; i++) {
11111 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
11112 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
11113 asc_dvc->cfg->sdtr_period_offset[i] =
11114 (uchar)(ASC_DEF_SDTR_OFFSET |
11115 (asc_dvc->host_init_sdtr_index << 4));
11116 }
11117 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
11118 if (write_eep) {
11119 if ((i =
11120 AscSetEEPConfig(iop_base, eep_config,
11121 asc_dvc->bus_type)) != 0) {
11122 ASC_PRINT1
11123 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
11124 i);
11125 } else {
11126 ASC_PRINT
11127 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
11128 }
11129 }
11130 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011131}
11132
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011133static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011134{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011135 int i;
11136 ushort warn_code;
11137 PortAddr iop_base;
11138 ASC_PADDR phy_addr;
11139 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011140
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011141 iop_base = asc_dvc->iop_base;
11142 warn_code = 0;
11143 for (i = 0; i <= ASC_MAX_TID; i++) {
11144 AscPutMCodeInitSDTRAtID(iop_base, i,
11145 asc_dvc->cfg->sdtr_period_offset[i]
11146 );
11147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011148
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011149 AscInitQLinkVar(asc_dvc);
11150 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
11151 asc_dvc->cfg->disc_enable);
11152 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
11153 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011154
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011155 /* Align overrun buffer on an 8 byte boundary. */
11156 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
11157 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
11158 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
11159 (uchar *)&phy_addr, 1);
11160 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
11161 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
11162 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011163
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011164 asc_dvc->cfg->mcode_date =
11165 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
11166 asc_dvc->cfg->mcode_version =
11167 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011168
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011169 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11170 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11171 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
11172 return (warn_code);
11173 }
11174 if (AscStartChip(iop_base) != 1) {
11175 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
11176 return (warn_code);
11177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011178
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011179 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011180}
11181
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011182static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011183{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011184 PortAddr iop_base;
11185 ushort q_addr;
11186 ushort saved_word;
11187 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011188
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011189 iop_base = asc_dvc->iop_base;
11190 sta = 0;
11191 q_addr = ASC_QNO_TO_QADDR(241);
11192 saved_word = AscReadLramWord(iop_base, q_addr);
11193 AscSetChipLramAddr(iop_base, q_addr);
11194 AscSetChipLramData(iop_base, 0x55AA);
11195 DvcSleepMilliSecond(10);
11196 AscSetChipLramAddr(iop_base, q_addr);
11197 if (AscGetChipLramData(iop_base) == 0x55AA) {
11198 sta = 1;
11199 AscWriteLramWord(iop_base, q_addr, saved_word);
11200 }
11201 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011202}
11203
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011204static int __init AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011205{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011206 uchar read_back;
11207 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011208
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011209 retry = 0;
11210 while (TRUE) {
11211 AscSetChipEEPCmd(iop_base, cmd_reg);
11212 DvcSleepMilliSecond(1);
11213 read_back = AscGetChipEEPCmd(iop_base);
11214 if (read_back == cmd_reg) {
11215 return (1);
11216 }
11217 if (retry++ > ASC_EEP_MAX_RETRY) {
11218 return (0);
11219 }
11220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011221}
11222
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011223static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011224{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011225 ushort read_back;
11226 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011227
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011228 retry = 0;
11229 while (TRUE) {
11230 AscSetChipEEPData(iop_base, data_reg);
11231 DvcSleepMilliSecond(1);
11232 read_back = AscGetChipEEPData(iop_base);
11233 if (read_back == data_reg) {
11234 return (1);
11235 }
11236 if (retry++ > ASC_EEP_MAX_RETRY) {
11237 return (0);
11238 }
11239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011240}
11241
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011242static void __init AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011243{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011244 DvcSleepMilliSecond(1);
11245 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011246}
11247
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011248static void __init AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011249{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011250 DvcSleepMilliSecond(20);
11251 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011252}
11253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011254static ushort __init AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011255{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011256 ushort read_wval;
11257 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011258
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011259 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11260 AscWaitEEPRead();
11261 cmd_reg = addr | ASC_EEP_CMD_READ;
11262 AscWriteEEPCmdReg(iop_base, cmd_reg);
11263 AscWaitEEPRead();
11264 read_wval = AscGetChipEEPData(iop_base);
11265 AscWaitEEPRead();
11266 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011267}
11268
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011269static ushort __init
11270AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011271{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011272 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011273
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011274 read_wval = AscReadEEPWord(iop_base, addr);
11275 if (read_wval != word_val) {
11276 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
11277 AscWaitEEPRead();
11278 AscWriteEEPDataReg(iop_base, word_val);
11279 AscWaitEEPRead();
11280 AscWriteEEPCmdReg(iop_base,
11281 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
11282 AscWaitEEPWrite();
11283 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11284 AscWaitEEPRead();
11285 return (AscReadEEPWord(iop_base, addr));
11286 }
11287 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011288}
11289
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011290static ushort __init
11291AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011292{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011293 ushort wval;
11294 ushort sum;
11295 ushort *wbuf;
11296 int cfg_beg;
11297 int cfg_end;
11298 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11299 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011300
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011301 wbuf = (ushort *)cfg_buf;
11302 sum = 0;
11303 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
11304 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11305 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11306 sum += *wbuf;
11307 }
11308 if (bus_type & ASC_IS_VL) {
11309 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11310 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11311 } else {
11312 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11313 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11314 }
11315 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11316 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11317 if (s_addr <= uchar_end_in_config) {
11318 /*
11319 * Swap all char fields - must unswap bytes already swapped
11320 * by AscReadEEPWord().
11321 */
11322 *wbuf = le16_to_cpu(wval);
11323 } else {
11324 /* Don't swap word field at the end - cntl field. */
11325 *wbuf = wval;
11326 }
11327 sum += wval; /* Checksum treats all EEPROM data as words. */
11328 }
11329 /*
11330 * Read the checksum word which will be compared against 'sum'
11331 * by the caller. Word field already swapped.
11332 */
11333 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11334 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011335}
11336
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011337static int __init
11338AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011339{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011340 int n_error;
11341 ushort *wbuf;
11342 ushort word;
11343 ushort sum;
11344 int s_addr;
11345 int cfg_beg;
11346 int cfg_end;
11347 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011348
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011349 wbuf = (ushort *)cfg_buf;
11350 n_error = 0;
11351 sum = 0;
11352 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11353 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11354 sum += *wbuf;
11355 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11356 n_error++;
11357 }
11358 }
11359 if (bus_type & ASC_IS_VL) {
11360 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11361 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11362 } else {
11363 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11364 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11365 }
11366 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11367 if (s_addr <= uchar_end_in_config) {
11368 /*
11369 * This is a char field. Swap char fields before they are
11370 * swapped again by AscWriteEEPWord().
11371 */
11372 word = cpu_to_le16(*wbuf);
11373 if (word !=
11374 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11375 n_error++;
11376 }
11377 } else {
11378 /* Don't swap word field at the end - cntl field. */
11379 if (*wbuf !=
11380 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11381 n_error++;
11382 }
11383 }
11384 sum += *wbuf; /* Checksum calculated from word values. */
11385 }
11386 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11387 *wbuf = sum;
11388 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11389 n_error++;
11390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011391
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011392 /* Read EEPROM back again. */
11393 wbuf = (ushort *)cfg_buf;
11394 /*
11395 * Read two config words; Byte-swapping done by AscReadEEPWord().
11396 */
11397 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11398 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11399 n_error++;
11400 }
11401 }
11402 if (bus_type & ASC_IS_VL) {
11403 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11404 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11405 } else {
11406 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11407 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11408 }
11409 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11410 if (s_addr <= uchar_end_in_config) {
11411 /*
11412 * Swap all char fields. Must unswap bytes already swapped
11413 * by AscReadEEPWord().
11414 */
11415 word =
11416 le16_to_cpu(AscReadEEPWord
11417 (iop_base, (uchar)s_addr));
11418 } else {
11419 /* Don't swap word field at the end - cntl field. */
11420 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11421 }
11422 if (*wbuf != word) {
11423 n_error++;
11424 }
11425 }
11426 /* Read checksum; Byte swapping not needed. */
11427 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11428 n_error++;
11429 }
11430 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011431}
11432
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011433static int __init
11434AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011435{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011436 int retry;
11437 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011438
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011439 retry = 0;
11440 while (TRUE) {
11441 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
11442 bus_type)) == 0) {
11443 break;
11444 }
11445 if (++retry > ASC_EEP_MAX_RETRY) {
11446 break;
11447 }
11448 }
11449 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011450}
11451
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011452static void
11453AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011454{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011455 uchar dvc_type;
11456 ASC_SCSI_BIT_ID_TYPE tid_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011457
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011458 dvc_type = ASC_INQ_DVC_TYPE(inq);
11459 tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011460
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011461 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
11462 if (!(asc_dvc->init_sdtr & tid_bits)) {
11463 if ((dvc_type == TYPE_ROM) &&
11464 (AscCompareString((uchar *)inq->vendor_id,
11465 (uchar *)"HP ", 3) == 0)) {
11466 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
11467 }
11468 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
11469 if ((dvc_type == TYPE_PROCESSOR) ||
11470 (dvc_type == TYPE_SCANNER) ||
11471 (dvc_type == TYPE_ROM) || (dvc_type == TYPE_TAPE)) {
11472 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
11473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011474
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011475 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
11476 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
11477 tid_no,
11478 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11479 }
11480 }
11481 }
11482 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011483}
11484
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011485static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011486{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011487 if ((inq->add_len >= 32) &&
11488 (AscCompareString((uchar *)inq->vendor_id,
11489 (uchar *)"QUANTUM XP34301", 15) == 0) &&
11490 (AscCompareString((uchar *)inq->product_rev_level,
11491 (uchar *)"1071", 4) == 0)) {
11492 return 0;
11493 }
11494 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011495}
11496
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011497static void
11498AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011499{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011500 ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
11501 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011502
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011503 orig_init_sdtr = asc_dvc->init_sdtr;
11504 orig_use_tagged_qng = asc_dvc->use_tagged_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011505
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011506 asc_dvc->init_sdtr &= ~tid_bit;
11507 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
11508 asc_dvc->use_tagged_qng &= ~tid_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011510 if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) {
11511 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) {
11512 asc_dvc->init_sdtr |= tid_bit;
11513 }
11514 if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) &&
11515 ASC_INQ_CMD_QUEUE(inq)) {
11516 if (AscTagQueuingSafe(inq)) {
11517 asc_dvc->use_tagged_qng |= tid_bit;
11518 asc_dvc->cfg->can_tagged_qng |= tid_bit;
11519 }
11520 }
11521 }
11522 if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
11523 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
11524 asc_dvc->cfg->disc_enable);
11525 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
11526 asc_dvc->use_tagged_qng);
11527 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
11528 asc_dvc->cfg->can_tagged_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011529
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011530 asc_dvc->max_dvc_qng[tid_no] =
11531 asc_dvc->cfg->max_tag_qng[tid_no];
11532 AscWriteLramByte(asc_dvc->iop_base,
11533 (ushort)(ASCV_MAX_DVC_QNG_BEG + tid_no),
11534 asc_dvc->max_dvc_qng[tid_no]);
11535 }
11536 if (orig_init_sdtr != asc_dvc->init_sdtr) {
11537 AscAsyncFix(asc_dvc, tid_no, inq);
11538 }
11539 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011540}
11541
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011542static int AscCompareString(uchar *str1, uchar *str2, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011543{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011544 int i;
11545 int diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011546
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011547 for (i = 0; i < len; i++) {
11548 diff = (int)(str1[i] - str2[i]);
11549 if (diff != 0)
11550 return (diff);
11551 }
11552 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011553}
11554
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011555static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011556{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011557 uchar byte_data;
11558 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011559
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011560 if (isodd_word(addr)) {
11561 AscSetChipLramAddr(iop_base, addr - 1);
11562 word_data = AscGetChipLramData(iop_base);
11563 byte_data = (uchar)((word_data >> 8) & 0xFF);
11564 } else {
11565 AscSetChipLramAddr(iop_base, addr);
11566 word_data = AscGetChipLramData(iop_base);
11567 byte_data = (uchar)(word_data & 0xFF);
11568 }
11569 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011570}
Linus Torvalds1da177e2005-04-16 15:20:36 -070011571
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011572static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
11573{
11574 ushort word_data;
11575
11576 AscSetChipLramAddr(iop_base, addr);
11577 word_data = AscGetChipLramData(iop_base);
11578 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011579}
11580
11581#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011582static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011583{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011584 ushort val_low, val_high;
11585 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011586
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011587 AscSetChipLramAddr(iop_base, addr);
11588 val_low = AscGetChipLramData(iop_base);
11589 val_high = AscGetChipLramData(iop_base);
11590 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
11591 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011592}
11593#endif /* CC_VERY_LONG_SG_LIST */
11594
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011595static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011596{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011597 AscSetChipLramAddr(iop_base, addr);
11598 AscSetChipLramData(iop_base, word_val);
11599 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011600}
11601
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011602static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011603{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011604 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011605
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011606 if (isodd_word(addr)) {
11607 addr--;
11608 word_data = AscReadLramWord(iop_base, addr);
11609 word_data &= 0x00FF;
11610 word_data |= (((ushort)byte_val << 8) & 0xFF00);
11611 } else {
11612 word_data = AscReadLramWord(iop_base, addr);
11613 word_data &= 0xFF00;
11614 word_data |= ((ushort)byte_val & 0x00FF);
11615 }
11616 AscWriteLramWord(iop_base, addr, word_data);
11617 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011618}
11619
11620/*
11621 * Copy 2 bytes to LRAM.
11622 *
11623 * The source data is assumed to be in little-endian order in memory
11624 * and is maintained in little-endian order when written to LRAM.
11625 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011626static void
11627AscMemWordCopyPtrToLram(PortAddr iop_base,
11628 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011629{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011630 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011631
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011632 AscSetChipLramAddr(iop_base, s_addr);
11633 for (i = 0; i < 2 * words; i += 2) {
11634 /*
11635 * On a little-endian system the second argument below
11636 * produces a little-endian ushort which is written to
11637 * LRAM in little-endian order. On a big-endian system
11638 * the second argument produces a big-endian ushort which
11639 * is "transparently" byte-swapped by outpw() and written
11640 * in little-endian order to LRAM.
11641 */
11642 outpw(iop_base + IOP_RAM_DATA,
11643 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
11644 }
11645 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011646}
11647
11648/*
11649 * Copy 4 bytes to LRAM.
11650 *
11651 * The source data is assumed to be in little-endian order in memory
11652 * and is maintained in little-endian order when writen to LRAM.
11653 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011654static void
11655AscMemDWordCopyPtrToLram(PortAddr iop_base,
11656 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011657{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011658 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011659
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011660 AscSetChipLramAddr(iop_base, s_addr);
11661 for (i = 0; i < 4 * dwords; i += 4) {
11662 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
11663 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
11664 }
11665 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011666}
11667
11668/*
11669 * Copy 2 bytes from LRAM.
11670 *
11671 * The source data is assumed to be in little-endian order in LRAM
11672 * and is maintained in little-endian order when written to memory.
11673 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011674static void
11675AscMemWordCopyPtrFromLram(PortAddr iop_base,
11676 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011677{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011678 int i;
11679 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011680
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011681 AscSetChipLramAddr(iop_base, s_addr);
11682 for (i = 0; i < 2 * words; i += 2) {
11683 word = inpw(iop_base + IOP_RAM_DATA);
11684 d_buffer[i] = word & 0xff;
11685 d_buffer[i + 1] = (word >> 8) & 0xff;
11686 }
11687 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011688}
11689
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011690static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011691{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011692 ASC_DCNT sum;
11693 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011694
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011695 sum = 0L;
11696 for (i = 0; i < words; i++, s_addr += 2) {
11697 sum += AscReadLramWord(iop_base, s_addr);
11698 }
11699 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011700}
11701
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011702static void
11703AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011704{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011705 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011706
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011707 AscSetChipLramAddr(iop_base, s_addr);
11708 for (i = 0; i < words; i++) {
11709 AscSetChipLramData(iop_base, set_wval);
11710 }
11711 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011712}
11713
Linus Torvalds1da177e2005-04-16 15:20:36 -070011714/*
11715 * --- Adv Library Functions
11716 */
11717
11718/* a_mcode.h */
11719
11720/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011721static unsigned char _adv_asc3550_buf[] = {
11722 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
11723 0x01, 0x00, 0x48, 0xe4,
11724 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff,
11725 0x28, 0x0e, 0x9e, 0xe7,
11726 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7,
11727 0x55, 0xf0, 0x01, 0xf6,
11728 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
11729 0x00, 0xec, 0x85, 0xf0,
11730 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0,
11731 0x86, 0xf0, 0xb4, 0x00,
11732 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00,
11733 0xaa, 0x18, 0x02, 0x80,
11734 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
11735 0x00, 0x57, 0x01, 0xea,
11736 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80,
11737 0x03, 0xe6, 0xb6, 0x00,
11738 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12,
11739 0x02, 0x4a, 0xb9, 0x54,
11740 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
11741 0x3e, 0x00, 0x80, 0x00,
11742 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
11743 0x74, 0x01, 0x76, 0x01,
11744 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13,
11745 0x4c, 0x1c, 0xbb, 0x55,
11746 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
11747 0x03, 0xf7, 0x06, 0xf7,
11748 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08,
11749 0x30, 0x13, 0x64, 0x15,
11750 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c,
11751 0x04, 0xea, 0x5d, 0xf0,
11752 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
11753 0xcc, 0x00, 0x20, 0x01,
11754 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13,
11755 0x40, 0x13, 0x30, 0x1c,
11756 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
11757 0x59, 0xf0, 0xa7, 0xf0,
11758 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
11759 0xa4, 0x00, 0xb5, 0x00,
11760 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a,
11761 0x14, 0x0e, 0x02, 0x10,
11762 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13,
11763 0x10, 0x15, 0x14, 0x15,
11764 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
11765 0x91, 0x44, 0x0a, 0x45,
11766 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58,
11767 0x83, 0x59, 0x05, 0xe6,
11768 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8,
11769 0x02, 0xfa, 0x03, 0xfa,
11770 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
11771 0x9e, 0x00, 0xa8, 0x00,
11772 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01,
11773 0x7a, 0x01, 0xc0, 0x01,
11774 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08,
11775 0x69, 0x08, 0xba, 0x08,
11776 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
11777 0xf1, 0x10, 0x06, 0x12,
11778 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14,
11779 0x8a, 0x15, 0xc6, 0x17,
11780 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
11781 0x0e, 0x47, 0x48, 0x47,
11782 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
11783 0x14, 0x56, 0x77, 0x57,
11784 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c,
11785 0xf0, 0x29, 0x02, 0xfe,
11786 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf,
11787 0xfe, 0x80, 0x01, 0xff,
11788 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
11789 0x00, 0xfe, 0x57, 0x24,
11790 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09,
11791 0x00, 0x00, 0xff, 0x08,
11792 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
11793 0xff, 0xff, 0xff, 0x0f,
11794 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
11795 0xfe, 0x04, 0xf7, 0xcf,
11796 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67,
11797 0x0b, 0x3c, 0x2a, 0xfe,
11798 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0,
11799 0xfe, 0xf0, 0x01, 0xfe,
11800 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
11801 0x02, 0xfe, 0xd4, 0x0c,
11802 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
11803 0x1c, 0x05, 0xfe, 0xa6,
11804 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48,
11805 0xf0, 0xfe, 0x86, 0x02,
11806 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
11807 0xfe, 0x46, 0xf0, 0xfe,
11808 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
11809 0x44, 0x02, 0xfe, 0x44,
11810 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b,
11811 0xa0, 0x17, 0x06, 0x18,
11812 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
11813 0x1e, 0x1c, 0xfe, 0xe9,
11814 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7,
11815 0x0a, 0x6b, 0x01, 0x9e,
11816 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b,
11817 0x01, 0x82, 0xfe, 0xbd,
11818 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
11819 0x58, 0x1c, 0x17, 0x06,
11820 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21,
11821 0xfe, 0x94, 0x02, 0xfe,
11822 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97,
11823 0x01, 0xfe, 0x54, 0x0f,
11824 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
11825 0x69, 0x10, 0x17, 0x06,
11826 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05,
11827 0xf6, 0xc7, 0x01, 0xfe,
11828 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6,
11829 0x02, 0x29, 0x0a, 0x40,
11830 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
11831 0x58, 0x0a, 0x99, 0x01,
11832 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29,
11833 0x2a, 0x46, 0xfe, 0x02,
11834 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc,
11835 0x01, 0xfe, 0x07, 0x4b,
11836 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
11837 0xfe, 0x56, 0x03, 0xfe,
11838 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10,
11839 0xfe, 0x9f, 0xf0, 0xfe,
11840 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48,
11841 0x1c, 0xeb, 0x09, 0x04,
11842 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
11843 0x01, 0x0e, 0xac, 0x75,
11844 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2,
11845 0xfe, 0x82, 0xf0, 0xfe,
11846 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25,
11847 0x32, 0x1f, 0xfe, 0xb4,
11848 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
11849 0x0a, 0xf0, 0xfe, 0x7a,
11850 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c,
11851 0x01, 0x33, 0x8f, 0xfe,
11852 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8,
11853 0xf7, 0xfe, 0x48, 0x1c,
11854 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
11855 0x0a, 0xca, 0x01, 0x0e,
11856 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14,
11857 0x2c, 0x01, 0x33, 0x8f,
11858 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65,
11859 0xfe, 0x3c, 0x04, 0x1f,
11860 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
11861 0x12, 0x2b, 0xff, 0x02,
11862 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f,
11863 0x22, 0x30, 0x2e, 0xd5,
11864 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c,
11865 0xfe, 0x4c, 0x54, 0x64,
11866 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
11867 0xfe, 0x2a, 0x13, 0x2f,
11868 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
11869 0xd3, 0xfa, 0xef, 0x86,
11870 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04,
11871 0x1d, 0xfe, 0x1c, 0x12,
11872 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
11873 0x70, 0x0c, 0x02, 0x22,
11874 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92,
11875 0x01, 0x33, 0x02, 0x29,
11876 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87,
11877 0x80, 0xfe, 0x31, 0xe4,
11878 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
11879 0xfe, 0x70, 0x12, 0x49,
11880 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe,
11881 0x80, 0x05, 0xfe, 0x31,
11882 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00,
11883 0x28, 0xfe, 0x42, 0x12,
11884 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
11885 0x11, 0xfe, 0xe3, 0x00,
11886 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
11887 0x64, 0x05, 0x83, 0x24,
11888 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe,
11889 0x09, 0x48, 0x01, 0x08,
11890 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
11891 0x86, 0x24, 0x06, 0x12,
11892 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47,
11893 0x01, 0xa7, 0x14, 0x92,
11894 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c,
11895 0x02, 0x22, 0x05, 0xfe,
11896 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
11897 0x47, 0x01, 0xa7, 0x26,
11898 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f,
11899 0x01, 0xfe, 0xaa, 0x14,
11900 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00,
11901 0x05, 0x50, 0xb4, 0x0c,
11902 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
11903 0x13, 0x01, 0xfe, 0x14,
11904 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c,
11905 0xff, 0x02, 0x00, 0x57,
11906 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe,
11907 0x72, 0x06, 0x49, 0x04,
11908 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
11909 0x06, 0x11, 0x9a, 0x01,
11910 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06,
11911 0x01, 0xa7, 0xec, 0x72,
11912 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32,
11913 0xfe, 0x0a, 0xf0, 0xfe,
11914 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
11915 0x8d, 0x81, 0x02, 0x22,
11916 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00,
11917 0x01, 0x08, 0x15, 0x00,
11918 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15,
11919 0x00, 0x02, 0xfe, 0x32,
11920 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
11921 0xfe, 0x1b, 0x00, 0x01,
11922 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
11923 0x08, 0x15, 0x06, 0x01,
11924 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe,
11925 0x9a, 0x81, 0x4b, 0x1d,
11926 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
11927 0x45, 0xfe, 0x32, 0x12,
11928 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0,
11929 0xfe, 0x32, 0x07, 0x8d,
11930 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a,
11931 0x06, 0x15, 0x19, 0x02,
11932 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
11933 0x90, 0x77, 0xfe, 0xca,
11934 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07,
11935 0x10, 0xfe, 0x0e, 0x12,
11936 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe,
11937 0x83, 0xe7, 0xc4, 0xa1,
11938 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
11939 0x40, 0x12, 0x58, 0x01,
11940 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6,
11941 0x51, 0x83, 0xfb, 0xfe,
11942 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90,
11943 0xfe, 0x40, 0x50, 0xfe,
11944 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
11945 0xfe, 0x2a, 0x12, 0xfe,
11946 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f,
11947 0x85, 0x01, 0xa8, 0xfe,
11948 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56,
11949 0x18, 0x57, 0xfb, 0xfe,
11950 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
11951 0x0c, 0x39, 0x18, 0x3a,
11952 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e,
11953 0x11, 0x65, 0xfe, 0x48,
11954 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73,
11955 0xdd, 0xb8, 0xfe, 0x80,
11956 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
11957 0xfe, 0x7a, 0x08, 0x8d,
11958 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9,
11959 0x10, 0x61, 0x04, 0x06,
11960 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68,
11961 0x12, 0xfe, 0x2e, 0x1c,
11962 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
11963 0x52, 0x12, 0xfe, 0x2c,
11964 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe,
11965 0x08, 0xfe, 0x8a, 0x10,
11966 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe,
11967 0x24, 0x0a, 0xab, 0xfe,
11968 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
11969 0x1c, 0x12, 0xb5, 0xfe,
11970 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb,
11971 0x1c, 0x06, 0x16, 0x9d,
11972 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b,
11973 0x14, 0x92, 0x01, 0x33,
11974 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
11975 0xfe, 0x74, 0x18, 0x1c,
11976 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b,
11977 0x01, 0xe6, 0x1e, 0x27,
11978 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a,
11979 0x09, 0x04, 0x6a, 0xfe,
11980 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
11981 0xfe, 0x83, 0x80, 0xfe,
11982 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63,
11983 0x27, 0xfe, 0x40, 0x59,
11984 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18,
11985 0x7c, 0xbe, 0x54, 0xbf,
11986 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
11987 0x79, 0x56, 0x68, 0x57,
11988 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5,
11989 0xa2, 0x23, 0x0c, 0x7b,
11990 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19,
11991 0x16, 0xd7, 0x79, 0x39,
11992 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
11993 0xfe, 0x10, 0x58, 0xfe,
11994 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04,
11995 0x19, 0x16, 0xd7, 0x09,
11996 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f,
11997 0xfe, 0x10, 0x90, 0xfe,
11998 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
11999 0x11, 0x9b, 0x09, 0x04,
12000 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08,
12001 0xfe, 0x0c, 0x58, 0xfe,
12002 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04,
12003 0x0b, 0xfe, 0x1a, 0x12,
12004 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
12005 0x14, 0x7a, 0x01, 0x33,
12006 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39,
12007 0xfe, 0xed, 0x19, 0xbf,
12008 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff,
12009 0x34, 0xfe, 0x74, 0x10,
12010 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
12011 0x84, 0x05, 0xcb, 0x1c,
12012 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1,
12013 0xf0, 0xfe, 0xc4, 0x0a,
12014 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe,
12015 0xce, 0xf0, 0xfe, 0xca,
12016 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
12017 0x22, 0x00, 0x02, 0x5a,
12018 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a,
12019 0xfe, 0xd0, 0xf0, 0xfe,
12020 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f,
12021 0x4c, 0xfe, 0x10, 0x10,
12022 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
12023 0x2a, 0x13, 0xfe, 0x4e,
12024 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1,
12025 0x16, 0x32, 0x2a, 0x73,
12026 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25,
12027 0x32, 0x8c, 0xfe, 0x48,
12028 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
12029 0xdb, 0x10, 0x11, 0xfe,
12030 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0,
12031 0x22, 0x30, 0x2e, 0xd8,
12032 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1,
12033 0x45, 0x0f, 0xfe, 0x42,
12034 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
12035 0x09, 0x04, 0x0b, 0xfe,
12036 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28,
12037 0x00, 0x21, 0xfe, 0xa6,
12038 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00,
12039 0xfe, 0xe2, 0x10, 0x01,
12040 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
12041 0x01, 0x6f, 0x02, 0x29,
12042 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10,
12043 0x01, 0x86, 0x3e, 0x0b,
12044 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3,
12045 0x3e, 0x0b, 0x0f, 0xfe,
12046 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
12047 0xe8, 0x59, 0x11, 0x2d,
12048 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09,
12049 0x04, 0x0b, 0x84, 0x3e,
12050 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12,
12051 0x09, 0x04, 0x1b, 0xfe,
12052 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
12053 0x1c, 0x1c, 0xfe, 0x9d,
12054 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f,
12055 0xfe, 0x15, 0x00, 0xfe,
12056 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10,
12057 0x0f, 0xfe, 0x47, 0x00,
12058 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
12059 0xab, 0x70, 0x05, 0x6b,
12060 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe,
12061 0x1c, 0x42, 0x59, 0x01,
12062 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31,
12063 0x00, 0x37, 0x97, 0x01,
12064 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
12065 0x1d, 0xfe, 0xce, 0x45,
12066 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75,
12067 0x57, 0x05, 0x51, 0xfe,
12068 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48,
12069 0x46, 0x09, 0x04, 0x1d,
12070 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
12071 0x99, 0x01, 0x0e, 0xfe,
12072 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51,
12073 0xfe, 0xee, 0x14, 0xee,
12074 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad,
12075 0x13, 0x02, 0x29, 0x1e,
12076 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
12077 0xce, 0x1e, 0x2d, 0x47,
12078 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06,
12079 0x12, 0x4d, 0x01, 0xfe,
12080 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe,
12081 0xf0, 0x0d, 0xfe, 0x02,
12082 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
12083 0xf6, 0xfe, 0x34, 0x01,
12084 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13,
12085 0xaf, 0xfe, 0x02, 0xea,
12086 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c,
12087 0x05, 0xfe, 0x38, 0x01,
12088 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
12089 0x0c, 0xfe, 0x62, 0x01,
12090 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06,
12091 0x03, 0x23, 0x03, 0x1e,
12092 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe,
12093 0x71, 0x13, 0xfe, 0x24,
12094 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
12095 0xdc, 0xfe, 0x73, 0x57,
12096 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe,
12097 0x80, 0x5d, 0x03, 0xfe,
12098 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6,
12099 0x75, 0x03, 0x09, 0x04,
12100 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
12101 0xfe, 0x1e, 0x80, 0xe1,
12102 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e,
12103 0x90, 0xa3, 0xfe, 0x3c,
12104 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82,
12105 0x16, 0x2f, 0x07, 0x2d,
12106 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
12107 0xe8, 0x11, 0xfe, 0xe9,
12108 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe,
12109 0x1e, 0x1c, 0xfe, 0x14,
12110 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01,
12111 0x09, 0x04, 0x4f, 0xfe,
12112 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
12113 0x40, 0x12, 0x20, 0x63,
12114 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08,
12115 0x1c, 0x05, 0xfe, 0xac,
12116 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05,
12117 0xfe, 0xb0, 0x00, 0xfe,
12118 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
12119 0x24, 0x69, 0x12, 0xc9,
12120 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe,
12121 0x90, 0x4d, 0xfe, 0x91,
12122 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c,
12123 0xfe, 0x90, 0x4d, 0xfe,
12124 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
12125 0x46, 0x1e, 0x20, 0xed,
12126 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea,
12127 0x70, 0xfe, 0x14, 0x1c,
12128 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee,
12129 0xfe, 0x07, 0xe6, 0x1d,
12130 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
12131 0xfa, 0xef, 0xfe, 0x42,
12132 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0,
12133 0xfe, 0x36, 0x12, 0xf0,
12134 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
12135 0x3d, 0x75, 0x07, 0x10,
12136 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
12137 0x10, 0x07, 0x7e, 0x45,
12138 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74,
12139 0xfe, 0x01, 0xec, 0x97,
12140 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76,
12141 0x27, 0x01, 0xda, 0xfe,
12142 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
12143 0xfe, 0x48, 0x12, 0x07,
12144 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16,
12145 0xfe, 0x3e, 0x11, 0x07,
12146 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8,
12147 0x11, 0x07, 0x19, 0xfe,
12148 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
12149 0x01, 0x08, 0x8c, 0x43,
12150 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11,
12151 0x7e, 0x02, 0x29, 0x2b,
12152 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe,
12153 0xfc, 0x10, 0x09, 0x04,
12154 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
12155 0xc6, 0x10, 0x1e, 0x58,
12156 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c,
12157 0x54, 0x18, 0x55, 0x23,
12158 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01,
12159 0xa5, 0xc0, 0x38, 0xc1,
12160 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
12161 0x05, 0xfa, 0x4e, 0xfe,
12162 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56,
12163 0x0c, 0x56, 0x18, 0x57,
12164 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe,
12165 0x00, 0x56, 0xfe, 0xa1,
12166 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
12167 0x58, 0xfe, 0x1f, 0x40,
12168 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56,
12169 0x31, 0x57, 0xfe, 0x44,
12170 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe,
12171 0x8a, 0x50, 0x05, 0x39,
12172 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
12173 0x12, 0xcd, 0x02, 0x5b,
12174 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44,
12175 0x2f, 0x07, 0x9b, 0x21,
12176 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79,
12177 0x39, 0x68, 0x3a, 0xfe,
12178 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
12179 0x51, 0xfe, 0x8e, 0x51,
12180 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b,
12181 0x01, 0x08, 0x25, 0x32,
12182 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b,
12183 0x3b, 0x02, 0x44, 0x01,
12184 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
12185 0x01, 0x08, 0x1f, 0xa2,
12186 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c,
12187 0x00, 0x28, 0x84, 0x49,
12188 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06,
12189 0x78, 0x3d, 0xfe, 0xda,
12190 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
12191 0x05, 0xc6, 0x28, 0x84,
12192 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8,
12193 0x14, 0xfe, 0x03, 0x17,
12194 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01,
12195 0xfe, 0xaa, 0x14, 0x02,
12196 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
12197 0x21, 0x44, 0x01, 0xfe,
12198 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87,
12199 0xfe, 0x4a, 0xf4, 0x0b,
12200 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a,
12201 0x85, 0x02, 0x5b, 0x05,
12202 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
12203 0xd8, 0x14, 0x02, 0x5c,
12204 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1,
12205 0x01, 0x08, 0x23, 0x72,
12206 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca,
12207 0x12, 0x5e, 0x2b, 0x01,
12208 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
12209 0x1c, 0xfe, 0xff, 0x7f,
12210 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00,
12211 0x57, 0x48, 0x8b, 0x1c,
12212 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02,
12213 0x00, 0x57, 0x48, 0x8b,
12214 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
12215 0x03, 0x0a, 0x50, 0x01,
12216 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00,
12217 0x54, 0xfe, 0x00, 0xf4,
12218 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe,
12219 0x03, 0x7c, 0x63, 0x27,
12220 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
12221 0xfe, 0x82, 0x4a, 0xfe,
12222 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe,
12223 0x42, 0x48, 0x5f, 0x60,
12224 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08,
12225 0x1f, 0xfe, 0xa2, 0x14,
12226 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
12227 0xcc, 0x12, 0x49, 0x04,
12228 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe,
12229 0xe8, 0x13, 0x3b, 0x13,
12230 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55,
12231 0xa1, 0xff, 0x02, 0x83,
12232 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
12233 0x13, 0x06, 0xfe, 0x56,
12234 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe,
12235 0x64, 0x00, 0x17, 0x93,
12236 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe,
12237 0xc8, 0x00, 0x8e, 0xe4,
12238 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
12239 0x01, 0xba, 0xfe, 0x4e,
12240 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0,
12241 0xfe, 0x60, 0x14, 0xfe,
12242 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01,
12243 0xfe, 0x22, 0x13, 0x1c,
12244 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
12245 0xfe, 0x9c, 0x14, 0xb7,
12246 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba,
12247 0xfe, 0x9c, 0x14, 0xb7,
12248 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06,
12249 0xfe, 0xb4, 0x56, 0xfe,
12250 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
12251 0xe5, 0x15, 0x0b, 0x01,
12252 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89,
12253 0x49, 0x01, 0x08, 0x03,
12254 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6,
12255 0x15, 0x06, 0x01, 0x08,
12256 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
12257 0x4a, 0x01, 0x08, 0x03,
12258 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc,
12259 0xfe, 0x49, 0xf4, 0x00,
12260 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01,
12261 0x08, 0x2f, 0x07, 0xfe,
12262 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
12263 0x01, 0x43, 0x1e, 0xcd,
12264 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e,
12265 0xed, 0x88, 0x07, 0x10,
12266 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a,
12267 0x80, 0x01, 0x0e, 0x88,
12268 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
12269 0x88, 0x03, 0x0a, 0x42,
12270 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e,
12271 0xfe, 0x80, 0x80, 0xf2,
12272 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51,
12273 0x01, 0x82, 0x03, 0x17,
12274 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
12275 0xfe, 0x24, 0x1c, 0xfe,
12276 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0,
12277 0x91, 0x1d, 0x66, 0xfe,
12278 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe,
12279 0xda, 0x10, 0x17, 0x10,
12280 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
12281 0x05, 0xfe, 0x66, 0x01,
12282 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06,
12283 0xfe, 0x3c, 0x50, 0x66,
12284 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe,
12285 0x40, 0x16, 0xfe, 0xb6,
12286 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
12287 0x10, 0x71, 0xfe, 0x83,
12288 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90,
12289 0xfe, 0x62, 0x16, 0xfe,
12290 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19,
12291 0xfe, 0x98, 0xe7, 0x00,
12292 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
12293 0xfe, 0x30, 0xbc, 0xfe,
12294 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
12295 0xc5, 0x90, 0xfe, 0x9a,
12296 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe,
12297 0x42, 0x10, 0xfe, 0x02,
12298 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
12299 0xfe, 0x1d, 0xf7, 0x4f,
12300 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f,
12301 0x47, 0xfe, 0x83, 0x58,
12302 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11,
12303 0xfe, 0xdd, 0x00, 0x63,
12304 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
12305 0x06, 0x37, 0x95, 0xa9,
12306 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e,
12307 0x18, 0x1c, 0x1a, 0x5d,
12308 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe,
12309 0xe1, 0x10, 0x78, 0x2c,
12310 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
12311 0x13, 0x3c, 0x8a, 0x0a,
12312 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
12313 0xe3, 0xfe, 0x00, 0xcc,
12314 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01,
12315 0x0e, 0xf2, 0x01, 0x6f,
12316 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
12317 0xf6, 0xfe, 0xd6, 0xf0,
12318 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe,
12319 0x15, 0x00, 0x59, 0x76,
12320 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35,
12321 0x11, 0x2d, 0x01, 0x6f,
12322 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
12323 0xc8, 0xfe, 0x48, 0x55,
12324 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a,
12325 0x99, 0x01, 0x0e, 0xf0,
12326 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73,
12327 0x75, 0x03, 0x0a, 0x42,
12328 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
12329 0x0e, 0x73, 0x75, 0x03,
12330 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00,
12331 0xfe, 0x3a, 0x45, 0x5b,
12332 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00,
12333 0xfe, 0x02, 0xe6, 0x1b,
12334 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
12335 0xfe, 0x94, 0x00, 0xfe,
12336 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02,
12337 0xe6, 0x2c, 0xfe, 0x4e,
12338 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69,
12339 0x03, 0x07, 0x7a, 0xfe,
12340 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
12341 0x07, 0x1b, 0xfe, 0x5a,
12342 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d,
12343 0x24, 0x2c, 0xdc, 0x07,
12344 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d,
12345 0x9f, 0xad, 0x03, 0x14,
12346 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
12347 0x03, 0x25, 0xfe, 0xca,
12348 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a,
12349 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012350};
12351
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012352static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
12353static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012354
12355/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012356static unsigned char _adv_asc38C0800_buf[] = {
12357 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
12358 0x01, 0x00, 0x48, 0xe4,
12359 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff,
12360 0x1c, 0x0f, 0x00, 0xf6,
12361 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6,
12362 0x09, 0xe7, 0x55, 0xf0,
12363 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
12364 0x18, 0xf4, 0x08, 0x00,
12365 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6,
12366 0x86, 0xf0, 0xb1, 0xf0,
12367 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c,
12368 0x3c, 0x00, 0xbb, 0x00,
12369 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
12370 0xba, 0x13, 0x18, 0x40,
12371 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01,
12372 0x6e, 0x01, 0x74, 0x01,
12373 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00,
12374 0xc0, 0x00, 0x01, 0x01,
12375 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
12376 0x08, 0x12, 0x02, 0x4a,
12377 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4,
12378 0x5d, 0xf0, 0x02, 0xfa,
12379 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01,
12380 0x68, 0x01, 0x6a, 0x01,
12381 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
12382 0x06, 0x13, 0x4c, 0x1c,
12383 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00,
12384 0x0f, 0x00, 0x47, 0x00,
12385 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c,
12386 0x4e, 0x1c, 0x10, 0x44,
12387 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
12388 0x05, 0x00, 0x34, 0x00,
12389 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b,
12390 0x42, 0x0c, 0x12, 0x0f,
12391 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48,
12392 0x00, 0x4e, 0x42, 0x54,
12393 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
12394 0x59, 0xf0, 0xb8, 0xf0,
12395 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00,
12396 0x19, 0x00, 0x33, 0x00,
12397 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00,
12398 0xe7, 0x00, 0xe2, 0x03,
12399 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
12400 0x12, 0x13, 0x24, 0x14,
12401 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c,
12402 0x36, 0x1c, 0x08, 0x44,
12403 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54,
12404 0x3a, 0x55, 0x83, 0x55,
12405 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
12406 0x0c, 0xf0, 0x04, 0xf8,
12407 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00,
12408 0xa8, 0x00, 0xaa, 0x00,
12409 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01,
12410 0xc4, 0x01, 0xc6, 0x01,
12411 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
12412 0x68, 0x08, 0x69, 0x08,
12413 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10,
12414 0xed, 0x10, 0xf1, 0x10,
12415 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13,
12416 0x1e, 0x13, 0x46, 0x14,
12417 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
12418 0xca, 0x18, 0xe6, 0x19,
12419 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c,
12420 0xf0, 0x2b, 0x02, 0xfe,
12421 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6,
12422 0xfe, 0x84, 0x01, 0xff,
12423 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
12424 0x00, 0xfe, 0x57, 0x24,
12425 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09,
12426 0x00, 0x00, 0xff, 0x08,
12427 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
12428 0xff, 0xff, 0xff, 0x11,
12429 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
12430 0xfe, 0x04, 0xf7, 0xd6,
12431 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99,
12432 0x0a, 0x42, 0x2c, 0xfe,
12433 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0,
12434 0xfe, 0xf4, 0x01, 0xfe,
12435 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
12436 0x02, 0xfe, 0xc8, 0x0d,
12437 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
12438 0x1c, 0x03, 0xfe, 0xa6,
12439 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48,
12440 0xf0, 0xfe, 0x8a, 0x02,
12441 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
12442 0xfe, 0x46, 0xf0, 0xfe,
12443 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
12444 0x48, 0x02, 0xfe, 0x44,
12445 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a,
12446 0xaa, 0x18, 0x06, 0x14,
12447 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
12448 0x1e, 0x1c, 0xfe, 0xe9,
12449 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce,
12450 0x09, 0x70, 0x01, 0xa8,
12451 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70,
12452 0x01, 0x87, 0xfe, 0xbd,
12453 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
12454 0x58, 0x1c, 0x18, 0x06,
12455 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23,
12456 0xfe, 0x98, 0x02, 0xfe,
12457 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2,
12458 0x01, 0xfe, 0x48, 0x10,
12459 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
12460 0x69, 0x10, 0x18, 0x06,
12461 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05,
12462 0xf6, 0xce, 0x01, 0xfe,
12463 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe,
12464 0x82, 0x16, 0x02, 0x2b,
12465 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
12466 0xfe, 0x41, 0x58, 0x09,
12467 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe,
12468 0x82, 0x16, 0x02, 0x2b,
12469 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43,
12470 0xfe, 0x77, 0x57, 0xfe,
12471 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
12472 0xfe, 0x40, 0x1c, 0x1c,
12473 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48,
12474 0x03, 0xfe, 0x11, 0xf0,
12475 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10,
12476 0xfe, 0x11, 0x00, 0x02,
12477 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
12478 0x21, 0x22, 0xa3, 0xb7,
12479 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16,
12480 0x12, 0xd1, 0x1c, 0xd9,
12481 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12,
12482 0xfe, 0xe4, 0x00, 0x27,
12483 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
12484 0x06, 0xf0, 0xfe, 0xc8,
12485 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03,
12486 0x70, 0x28, 0x17, 0xfe,
12487 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8,
12488 0xf9, 0x2c, 0x99, 0x19,
12489 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
12490 0x74, 0x01, 0xaf, 0x8c,
12491 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e,
12492 0x8d, 0x51, 0x64, 0x79,
12493 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b,
12494 0xfe, 0x6a, 0x02, 0x02,
12495 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
12496 0xfe, 0x3c, 0x04, 0x3b,
12497 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02,
12498 0x00, 0x10, 0x01, 0x0b,
12499 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde,
12500 0xfe, 0x4c, 0x44, 0xfe,
12501 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
12502 0xda, 0x4f, 0x79, 0x2a,
12503 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b,
12504 0xfe, 0x2a, 0x13, 0x32,
12505 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c,
12506 0x54, 0x6b, 0xda, 0xfe,
12507 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
12508 0x08, 0x13, 0x32, 0x07,
12509 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d,
12510 0x08, 0x05, 0x06, 0x4d,
12511 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24,
12512 0x2d, 0x12, 0xfe, 0xe6,
12513 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
12514 0x02, 0x2b, 0xfe, 0x42,
12515 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
12516 0xfe, 0x87, 0x80, 0xfe,
12517 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80,
12518 0x07, 0x19, 0xfe, 0x7c,
12519 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
12520 0x17, 0xfe, 0x90, 0x05,
12521 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe,
12522 0xa0, 0x00, 0x28, 0xfe,
12523 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c,
12524 0x34, 0xfe, 0x89, 0x48,
12525 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
12526 0x12, 0xfe, 0xe3, 0x00,
12527 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
12528 0x70, 0x05, 0x88, 0x25,
12529 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe,
12530 0x09, 0x48, 0xff, 0x02,
12531 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
12532 0x08, 0x53, 0x05, 0xcb,
12533 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08,
12534 0x05, 0x1b, 0xfe, 0x22,
12535 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe,
12536 0x0d, 0x00, 0x01, 0x36,
12537 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
12538 0x03, 0x5c, 0x28, 0xfe,
12539 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53,
12540 0x05, 0x1f, 0xfe, 0x02,
12541 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5,
12542 0x01, 0x4b, 0x12, 0xfe,
12543 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
12544 0x12, 0x03, 0x45, 0x28,
12545 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe,
12546 0x43, 0x48, 0xc4, 0xcc,
12547 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4,
12548 0x6e, 0x41, 0x01, 0xb2,
12549 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
12550 0xfe, 0xcc, 0x15, 0x1d,
12551 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03,
12552 0x45, 0xc1, 0x0c, 0x45,
12553 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe,
12554 0xe2, 0x00, 0x27, 0xdb,
12555 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
12556 0xfe, 0x06, 0xf0, 0xfe,
12557 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12,
12558 0x16, 0x19, 0x01, 0x0b,
12559 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
12560 0xfe, 0x99, 0xa4, 0x01,
12561 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
12562 0x12, 0x08, 0x05, 0x1a,
12563 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
12564 0x0b, 0x16, 0x00, 0x01,
12565 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02,
12566 0xe2, 0x6c, 0x58, 0xbe,
12567 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
12568 0xfe, 0x09, 0x6f, 0xba,
12569 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27,
12570 0xfe, 0x54, 0x07, 0x1c,
12571 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c,
12572 0x07, 0x02, 0x24, 0x01,
12573 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
12574 0x2c, 0x90, 0xfe, 0xae,
12575 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a,
12576 0x37, 0x22, 0x20, 0x07,
12577 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a,
12578 0xfe, 0x06, 0x10, 0xfe,
12579 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
12580 0x37, 0x01, 0xb3, 0xb8,
12581 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a,
12582 0x50, 0xfe, 0x44, 0x51,
12583 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e,
12584 0x14, 0x5f, 0xfe, 0x0c,
12585 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
12586 0x14, 0x3e, 0xfe, 0x4a,
12587 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
12588 0x90, 0x0c, 0x60, 0x14,
12589 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62,
12590 0xfe, 0x44, 0x90, 0xfe,
12591 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
12592 0x0c, 0x5e, 0x14, 0x5f,
12593 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e,
12594 0x14, 0x3c, 0x21, 0x0c,
12595 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11,
12596 0x27, 0xdd, 0xfe, 0x9e,
12597 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
12598 0x9a, 0x08, 0xc6, 0xfe,
12599 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08,
12600 0x95, 0x86, 0x02, 0x24,
12601 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05,
12602 0x06, 0xfe, 0x10, 0x12,
12603 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
12604 0x1c, 0x02, 0xfe, 0x18,
12605 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe,
12606 0x2c, 0x1c, 0xfe, 0xaa,
12607 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe,
12608 0xde, 0x09, 0xfe, 0xb7,
12609 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
12610 0xfe, 0xf1, 0x18, 0xfe,
12611 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe,
12612 0x14, 0x59, 0xfe, 0x95,
12613 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0,
12614 0xfe, 0xf0, 0x08, 0xb5,
12615 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
12616 0x0b, 0xb6, 0xfe, 0xbf,
12617 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c,
12618 0x12, 0xc2, 0xfe, 0xd2,
12619 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e,
12620 0x06, 0x17, 0x85, 0xc5,
12621 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
12622 0x9d, 0x01, 0x36, 0x10,
12623 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe,
12624 0x98, 0x80, 0xfe, 0x19,
12625 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18,
12626 0xfe, 0x44, 0x54, 0xbe,
12627 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
12628 0x02, 0x4a, 0x08, 0x05,
12629 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e,
12630 0x9c, 0x3c, 0xfe, 0x6c,
12631 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f,
12632 0x3b, 0x40, 0x03, 0x49,
12633 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
12634 0x8f, 0xfe, 0xe3, 0x54,
12635 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe,
12636 0xda, 0x09, 0xfe, 0x8b,
12637 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa,
12638 0x0a, 0x3a, 0x49, 0x3b,
12639 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
12640 0xad, 0xfe, 0x01, 0x59,
12641 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a,
12642 0x49, 0x8f, 0xfe, 0xe3,
12643 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02,
12644 0x4a, 0x3a, 0x49, 0x3b,
12645 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
12646 0x02, 0x4a, 0x08, 0x05,
12647 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62,
12648 0xb7, 0xfe, 0x03, 0xa1,
12649 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
12650 0xfe, 0x86, 0x91, 0x6a,
12651 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
12652 0x61, 0x0c, 0x7f, 0x14,
12653 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62,
12654 0x9b, 0x2e, 0x9c, 0x3c,
12655 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05,
12656 0xfa, 0x3c, 0x01, 0xef,
12657 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
12658 0xe4, 0x08, 0x05, 0x1f,
12659 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37,
12660 0x03, 0x5e, 0x29, 0x5f,
12661 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe,
12662 0xf4, 0x09, 0x08, 0x05,
12663 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
12664 0x81, 0x50, 0xfe, 0x10,
12665 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe,
12666 0x08, 0x09, 0x12, 0xa6,
12667 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe,
12668 0x08, 0x09, 0xfe, 0x0c,
12669 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
12670 0x08, 0x05, 0x0a, 0xfe,
12671 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1,
12672 0xf0, 0xe2, 0x15, 0x7e,
12673 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19,
12674 0x57, 0x3d, 0xfe, 0xed,
12675 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
12676 0x00, 0xff, 0x35, 0xfe,
12677 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18,
12678 0x1e, 0x19, 0x8a, 0x03,
12679 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65,
12680 0xfe, 0xd1, 0xf0, 0xfe,
12681 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
12682 0x10, 0xfe, 0xce, 0xf0,
12683 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b,
12684 0x10, 0xfe, 0x22, 0x00,
12685 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00,
12686 0x02, 0x65, 0xfe, 0xd0,
12687 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
12688 0x0b, 0x10, 0x58, 0xfe,
12689 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe,
12690 0x12, 0x00, 0x2c, 0x0f,
12691 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14,
12692 0x0c, 0xbc, 0x17, 0x34,
12693 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
12694 0x0c, 0x1c, 0x34, 0x94,
12695 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01,
12696 0x4b, 0xfe, 0xdb, 0x10,
12697 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe,
12698 0x89, 0xf0, 0x24, 0x33,
12699 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
12700 0x33, 0x31, 0xdf, 0xbc,
12701 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49,
12702 0x17, 0xfe, 0x2c, 0x0d,
12703 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54,
12704 0x12, 0x55, 0xfe, 0x28,
12705 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
12706 0x44, 0xfe, 0x28, 0x00,
12707 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26,
12708 0x0f, 0x64, 0x12, 0x2f,
12709 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44,
12710 0x0a, 0xfe, 0xb4, 0x10,
12711 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
12712 0xfe, 0x34, 0x46, 0xac,
12713 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a,
12714 0x37, 0x01, 0xf5, 0x01,
12715 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02,
12716 0xfe, 0x2e, 0x03, 0x08,
12717 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
12718 0x1a, 0xfe, 0x58, 0x12,
12719 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
12720 0xfe, 0x50, 0x0d, 0xfe,
12721 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37,
12722 0xfe, 0xa9, 0x10, 0x10,
12723 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
12724 0xfe, 0x13, 0x00, 0xfe,
12725 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe,
12726 0x24, 0x00, 0x8c, 0xb5,
12727 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a,
12728 0xfe, 0x9d, 0x41, 0xfe,
12729 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
12730 0xb4, 0x15, 0xfe, 0x31,
12731 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06,
12732 0xec, 0xd0, 0xfc, 0x44,
12733 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47,
12734 0x4b, 0x91, 0xfe, 0x75,
12735 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
12736 0x0e, 0xfe, 0x44, 0x48,
12737 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41,
12738 0xfe, 0x41, 0x58, 0x09,
12739 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe,
12740 0x2e, 0x03, 0x09, 0x5d,
12741 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
12742 0xce, 0x47, 0xfe, 0xad,
12743 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13,
12744 0x59, 0x13, 0x9f, 0x13,
12745 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe,
12746 0xe0, 0x0e, 0x0f, 0x06,
12747 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
12748 0x3a, 0x01, 0x56, 0xfe,
12749 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec,
12750 0x20, 0x4f, 0xfe, 0x05,
12751 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe,
12752 0x48, 0xf4, 0x0d, 0xfe,
12753 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
12754 0x15, 0x1a, 0x39, 0xa0,
12755 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff,
12756 0x0c, 0xfe, 0x60, 0x01,
12757 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25,
12758 0x06, 0x13, 0x2f, 0x12,
12759 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
12760 0x22, 0x9f, 0xb7, 0x13,
12761 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39,
12762 0xa0, 0xb4, 0xfe, 0xd9,
12763 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04,
12764 0xc3, 0xfe, 0x03, 0xdc,
12765 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
12766 0xfe, 0x00, 0xcc, 0x04,
12767 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13,
12768 0xfe, 0x1c, 0x80, 0x07,
12769 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae,
12770 0xfe, 0x0c, 0x90, 0xfe,
12771 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
12772 0x0a, 0xfe, 0x3c, 0x50,
12773 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4,
12774 0x16, 0x08, 0x05, 0x1b,
12775 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58,
12776 0xfe, 0x2c, 0x13, 0x01,
12777 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
12778 0x0c, 0xfe, 0x64, 0x01,
12779 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03,
12780 0x80, 0x8d, 0xfe, 0x01,
12781 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64,
12782 0x22, 0x20, 0xfb, 0x79,
12783 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
12784 0x03, 0xfe, 0xae, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012785
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012786 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe,
12787 0xb2, 0x00, 0xfe, 0x09,
12788 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c,
12789 0x45, 0x0f, 0x46, 0x52,
12790 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
12791 0x0f, 0x44, 0x11, 0x0f,
12792 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4,
12793 0x25, 0x11, 0x13, 0x20,
12794 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14,
12795 0x56, 0xfe, 0xd6, 0xf0,
12796 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
12797 0x18, 0x1c, 0x04, 0x42,
12798 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe,
12799 0xf5, 0x13, 0x04, 0x01,
12800 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
12801 0x13, 0x32, 0x07, 0x2f,
12802 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
12803 0x41, 0x48, 0xfe, 0x45,
12804 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78,
12805 0x07, 0x11, 0xac, 0x09,
12806 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07,
12807 0x82, 0x4e, 0xfe, 0x14,
12808 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
12809 0xfe, 0x01, 0xec, 0xa2,
12810 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79,
12811 0x2a, 0x01, 0xe3, 0xfe,
12812 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a,
12813 0xfe, 0x48, 0x12, 0x07,
12814 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
12815 0xfe, 0x32, 0x12, 0x07,
12816 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07,
12817 0x1f, 0xfe, 0x12, 0x12,
12818 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b,
12819 0x94, 0x4b, 0x04, 0x2d,
12820 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
12821 0x32, 0x07, 0xa6, 0xfe,
12822 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05,
12823 0x5a, 0xfe, 0x72, 0x12,
12824 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62,
12825 0xfe, 0x26, 0x13, 0x03,
12826 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
12827 0x0c, 0x7f, 0x0c, 0x80,
12828 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c,
12829 0x3c, 0xfe, 0x04, 0x55,
12830 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe,
12831 0x91, 0x10, 0x03, 0x3f,
12832 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
12833 0x88, 0x9b, 0x2e, 0x9c,
12834 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
12835 0x56, 0x0c, 0x5e, 0x14,
12836 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40,
12837 0x03, 0x60, 0x29, 0x61,
12838 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
12839 0x50, 0xfe, 0xc6, 0x50,
12840 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d,
12841 0x29, 0x3e, 0xfe, 0x40,
12842 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72,
12843 0x2d, 0x01, 0x0b, 0x1d,
12844 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
12845 0x72, 0x01, 0xaf, 0x1e,
12846 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe,
12847 0x0a, 0x55, 0x35, 0xfe,
12848 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51,
12849 0x02, 0x72, 0xfe, 0x19,
12850 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
12851 0x1d, 0xe8, 0x33, 0x31,
12852 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01,
12853 0x0b, 0x1c, 0x34, 0x1d,
12854 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8,
12855 0x33, 0x31, 0xfe, 0xe8,
12856 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
12857 0x05, 0x1f, 0x35, 0xa9,
12858 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda,
12859 0x14, 0x01, 0xaf, 0x8c,
12860 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a,
12861 0x03, 0x45, 0x28, 0x35,
12862 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
12863 0x03, 0x5c, 0xc1, 0x0c,
12864 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02,
12865 0x89, 0x01, 0x0b, 0x1c,
12866 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1,
12867 0xfe, 0x42, 0x58, 0xf1,
12868 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
12869 0xf4, 0x06, 0xea, 0x32,
12870 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d,
12871 0x01, 0x0b, 0x26, 0x89,
12872 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13,
12873 0x26, 0xfe, 0xd4, 0x13,
12874 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
12875 0x13, 0x1c, 0xfe, 0xd0,
12876 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10,
12877 0x0f, 0x71, 0xff, 0x02,
12878 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe,
12879 0x00, 0x5c, 0x04, 0x0f,
12880 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
12881 0xfe, 0x00, 0x5c, 0x04,
12882 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff,
12883 0x02, 0x00, 0x57, 0x52,
12884 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01,
12885 0x87, 0x04, 0xfe, 0x03,
12886 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
12887 0xfe, 0x00, 0x7d, 0xfe,
12888 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e,
12889 0x14, 0x5f, 0x57, 0x3f,
12890 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83,
12891 0x5a, 0x8d, 0x04, 0x01,
12892 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
12893 0xfe, 0x96, 0x15, 0x33,
12894 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8,
12895 0x0a, 0xfe, 0xc1, 0x59,
12896 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13,
12897 0x21, 0x69, 0x1a, 0xee,
12898 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
12899 0x30, 0xfe, 0x78, 0x10,
12900 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae,
12901 0x98, 0xfe, 0x30, 0x00,
12902 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed,
12903 0x98, 0xfe, 0x64, 0x00,
12904 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
12905 0x10, 0x69, 0x06, 0xfe,
12906 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00,
12907 0x18, 0x59, 0x0f, 0x06,
12908 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe,
12909 0x43, 0xf4, 0x9f, 0xfe,
12910 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
12911 0x9e, 0xfe, 0xf3, 0x10,
12912 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00,
12913 0x17, 0xfe, 0x4d, 0xe4,
12914 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00,
12915 0x17, 0xfe, 0x4d, 0xe4,
12916 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
12917 0xf4, 0x00, 0xe9, 0x91,
12918 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a,
12919 0x04, 0x16, 0x06, 0x01,
12920 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01,
12921 0x0b, 0x26, 0xf3, 0x76,
12922 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
12923 0x16, 0x19, 0x01, 0x0b,
12924 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01,
12925 0x0b, 0x26, 0xb1, 0x76,
12926 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06,
12927 0xfe, 0x48, 0x13, 0xb8,
12928 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
12929 0xec, 0xfe, 0x27, 0x01,
12930 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32,
12931 0x07, 0xfe, 0xe3, 0x00,
12932 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b,
12933 0x22, 0xd4, 0x07, 0x06,
12934 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
12935 0x07, 0x11, 0xae, 0x09,
12936 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01,
12937 0x0e, 0x8e, 0xfe, 0x80,
12938 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04,
12939 0x09, 0x48, 0x01, 0x0e,
12940 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
12941 0x80, 0xfe, 0x80, 0x4c,
12942 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c,
12943 0x09, 0x5d, 0x01, 0x87,
12944 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe,
12945 0x19, 0xde, 0xfe, 0x24,
12946 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
12947 0x17, 0xad, 0x9a, 0x1b,
12948 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde,
12949 0x16, 0xfe, 0xda, 0x10,
12950 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe,
12951 0x18, 0x58, 0x03, 0xfe,
12952 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
12953 0xf4, 0x06, 0xfe, 0x3c,
12954 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f,
12955 0x97, 0xfe, 0x38, 0x17,
12956 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c,
12957 0x10, 0x18, 0x11, 0x75,
12958 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
12959 0x2e, 0x97, 0xfe, 0x5a,
12960 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19,
12961 0xfe, 0x98, 0xe7, 0x00,
12962 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75,
12963 0xfe, 0x30, 0xbc, 0xfe,
12964 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
12965 0xcb, 0x97, 0xfe, 0x92,
12966 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe,
12967 0x42, 0x10, 0xfe, 0x02,
12968 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe,
12969 0x03, 0xa1, 0xfe, 0x1d,
12970 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
12971 0x9a, 0x5b, 0x41, 0xfe,
12972 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7,
12973 0x11, 0x12, 0xfe, 0xdd,
12974 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8,
12975 0x17, 0x15, 0x06, 0x39,
12976 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
12977 0xfe, 0x7e, 0x18, 0x1e,
12978 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef,
12979 0x12, 0xfe, 0xe1, 0x10,
12980 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42,
12981 0x13, 0x42, 0x92, 0x09,
12982 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
12983 0xf0, 0xfe, 0x00, 0xcc,
12984 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01,
12985 0x0e, 0xfe, 0x80, 0x4c,
12986 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe,
12987 0x24, 0x12, 0xfe, 0x14,
12988 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
12989 0xe7, 0x0a, 0x10, 0xfe,
12990 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92,
12991 0x08, 0x54, 0x1b, 0x37,
12992 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba,
12993 0x90, 0x3a, 0xce, 0x3b,
12994 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
12995 0x13, 0xa3, 0x04, 0x09,
12996 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49,
12997 0x44, 0x17, 0xfe, 0xe8,
12998 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09,
12999 0x5d, 0x01, 0xa8, 0x09,
13000 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
13001 0x1c, 0x19, 0x03, 0xfe,
13002 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9,
13003 0x6b, 0xfe, 0x2e, 0x19,
13004 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4,
13005 0xfe, 0x0b, 0x00, 0x6b,
13006 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
13007 0x08, 0x10, 0x03, 0xfe,
13008 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff,
13009 0x04, 0x68, 0x54, 0xe7,
13010 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe,
13011 0x1a, 0xf4, 0xfe, 0x00,
13012 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
13013 0x04, 0x07, 0x7e, 0xfe,
13014 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
13015 0x07, 0x1a, 0xfe, 0x5a,
13016 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66,
13017 0x25, 0x6d, 0xe5, 0x07,
13018 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
13019 0xa9, 0xb8, 0x04, 0x15,
13020 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe,
13021 0x40, 0x5c, 0x04, 0x1c,
13022 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b,
13023 0xf7, 0xfe, 0x82, 0xf0,
13024 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070013025};
13026
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013027static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
13028static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013029
13030/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013031static unsigned char _adv_asc38C1600_buf[] = {
13032 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
13033 0x18, 0xe4, 0x01, 0x00,
13034 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00,
13035 0x07, 0x17, 0xc0, 0x5f,
13036 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7,
13037 0x85, 0xf0, 0x86, 0xf0,
13038 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
13039 0x98, 0x57, 0x01, 0xe6,
13040 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d,
13041 0x38, 0x54, 0x32, 0xf0,
13042 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4,
13043 0x00, 0xe6, 0xb1, 0xf0,
13044 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
13045 0x06, 0x13, 0x0c, 0x1c,
13046 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12,
13047 0xb9, 0x54, 0x00, 0x80,
13048 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56,
13049 0x03, 0xe6, 0x01, 0xea,
13050 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
13051 0x04, 0x13, 0xbb, 0x55,
13052 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00,
13053 0xbb, 0x00, 0xc0, 0x00,
13054 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12,
13055 0x4c, 0x1c, 0x4e, 0x1c,
13056 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
13057 0x24, 0x01, 0x3c, 0x01,
13058 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01,
13059 0x78, 0x01, 0x7c, 0x01,
13060 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c,
13061 0x6e, 0x1e, 0x02, 0x48,
13062 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
13063 0x03, 0xfc, 0x06, 0x00,
13064 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a,
13065 0x30, 0x1c, 0x38, 0x1c,
13066 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea,
13067 0x5d, 0xf0, 0xa7, 0xf0,
13068 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
13069 0x33, 0x00, 0x34, 0x00,
13070 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01,
13071 0x79, 0x01, 0x3c, 0x09,
13072 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13,
13073 0x40, 0x16, 0x50, 0x16,
13074 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
13075 0x05, 0xf0, 0x09, 0xf0,
13076 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00,
13077 0x9c, 0x00, 0xa4, 0x00,
13078 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08,
13079 0xe9, 0x09, 0x5c, 0x0c,
13080 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
13081 0x42, 0x1d, 0x08, 0x44,
13082 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54,
13083 0x83, 0x55, 0x83, 0x59,
13084 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0,
13085 0x4b, 0xf4, 0x04, 0xf8,
13086 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
13087 0xa8, 0x00, 0xaa, 0x00,
13088 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01,
13089 0x7a, 0x01, 0x82, 0x01,
13090 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07,
13091 0x68, 0x08, 0x10, 0x0d,
13092 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
13093 0xf3, 0x10, 0x06, 0x12,
13094 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c,
13095 0xf0, 0x35, 0x05, 0xfe,
13096 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8,
13097 0xfe, 0x88, 0x01, 0xff,
13098 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
13099 0x00, 0xfe, 0x57, 0x24,
13100 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09,
13101 0x00, 0x00, 0xff, 0x08,
13102 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
13103 0xff, 0xff, 0xff, 0x13,
13104 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
13105 0xfe, 0x04, 0xf7, 0xe8,
13106 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d,
13107 0x0d, 0x51, 0x37, 0xfe,
13108 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0,
13109 0xfe, 0xf8, 0x01, 0xfe,
13110 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
13111 0x05, 0xfe, 0x08, 0x0f,
13112 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe,
13113 0x28, 0x1c, 0x03, 0xfe,
13114 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe,
13115 0x48, 0xf0, 0xfe, 0x90,
13116 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
13117 0x02, 0xfe, 0x46, 0xf0,
13118 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0,
13119 0xfe, 0x4e, 0x02, 0xfe,
13120 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c,
13121 0x0d, 0xa2, 0x1c, 0x07,
13122 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
13123 0x1c, 0xf5, 0xfe, 0x1e,
13124 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc,
13125 0xde, 0x0a, 0x81, 0x01,
13126 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a,
13127 0x81, 0x01, 0x5c, 0xfe,
13128 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
13129 0xfe, 0x58, 0x1c, 0x1c,
13130 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02,
13131 0x2b, 0xfe, 0x9e, 0x02,
13132 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30,
13133 0x00, 0x47, 0xb8, 0x01,
13134 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
13135 0x1a, 0x31, 0xfe, 0x69,
13136 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe,
13137 0x1e, 0x1e, 0x20, 0x2c,
13138 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a,
13139 0x44, 0x15, 0x56, 0x51,
13140 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
13141 0x01, 0x18, 0x09, 0x00,
13142 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01,
13143 0x18, 0xfe, 0xc8, 0x54,
13144 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60,
13145 0xfe, 0x02, 0xe8, 0x30,
13146 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
13147 0xfe, 0xe4, 0x01, 0xfe,
13148 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe,
13149 0x26, 0xf0, 0xfe, 0x66,
13150 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe,
13151 0xef, 0x10, 0xfe, 0x9f,
13152 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
13153 0x70, 0x37, 0xfe, 0x48,
13154 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26,
13155 0x21, 0xb9, 0xc7, 0x20,
13156 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15,
13157 0xe1, 0x2a, 0xeb, 0xfe,
13158 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
13159 0x15, 0xfe, 0xe4, 0x00,
13160 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41,
13161 0xfe, 0x06, 0xf0, 0xfe,
13162 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29,
13163 0x03, 0x81, 0x1e, 0x1b,
13164 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
13165 0xea, 0xfe, 0x46, 0x1c,
13166 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
13167 0xfe, 0x48, 0x1c, 0x75,
13168 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a,
13169 0xe1, 0x01, 0x18, 0x77,
13170 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
13171 0x8f, 0xfe, 0x70, 0x02,
13172 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04,
13173 0x16, 0xfe, 0x4a, 0x04,
13174 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff,
13175 0x02, 0x00, 0x10, 0x01,
13176 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
13177 0xee, 0xfe, 0x4c, 0x44,
13178 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54,
13179 0x7b, 0xec, 0x60, 0x8d,
13180 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01,
13181 0x0c, 0x06, 0x28, 0xfe,
13182 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
13183 0x13, 0x34, 0xfe, 0x4c,
13184 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54,
13185 0x13, 0x01, 0x0c, 0x06,
13186 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06,
13187 0x28, 0xf9, 0x1f, 0x7f,
13188 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
13189 0xfe, 0xa4, 0x0e, 0x05,
13190 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe,
13191 0x9c, 0x93, 0x3a, 0x0b,
13192 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b,
13193 0x7d, 0x1d, 0xfe, 0x46,
13194 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
13195 0xfe, 0x87, 0x83, 0xfe,
13196 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98,
13197 0x13, 0x0f, 0xfe, 0x20,
13198 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84,
13199 0x12, 0x01, 0x38, 0x06,
13200 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
13201 0x05, 0xd0, 0x54, 0x01,
13202 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe,
13203 0x50, 0x12, 0x5e, 0xff,
13204 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02,
13205 0x00, 0x10, 0x2f, 0xfe,
13206 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
13207 0x38, 0xfe, 0x4a, 0xf0,
13208 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe,
13209 0x21, 0x00, 0xf1, 0x2e,
13210 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00,
13211 0x10, 0x2f, 0xfe, 0xd0,
13212 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
13213 0x1c, 0x00, 0x4d, 0x01,
13214 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06,
13215 0x28, 0xfe, 0x24, 0x12,
13216 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe,
13217 0x0d, 0x00, 0x01, 0x42,
13218 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
13219 0x03, 0xb6, 0x1e, 0xfe,
13220 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17,
13221 0xfe, 0x72, 0x06, 0x0a,
13222 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56,
13223 0x19, 0x16, 0xfe, 0x68,
13224 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
13225 0x03, 0x9a, 0x1e, 0xfe,
13226 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12,
13227 0x48, 0xfe, 0x92, 0x06,
13228 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13,
13229 0x58, 0xff, 0x02, 0x00,
13230 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
13231 0xfe, 0xea, 0x06, 0x01,
13232 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16,
13233 0xfe, 0xe0, 0x06, 0x15,
13234 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07,
13235 0x01, 0x84, 0xfe, 0xae,
13236 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
13237 0x1e, 0xfe, 0x1a, 0x12,
13238 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
13239 0x43, 0x48, 0x62, 0x80,
13240 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24,
13241 0x36, 0xfe, 0x02, 0xf6,
13242 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
13243 0xd0, 0x0d, 0x17, 0xfe,
13244 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20,
13245 0x9e, 0x15, 0x82, 0x01,
13246 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58,
13247 0x57, 0x10, 0xe6, 0x05,
13248 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
13249 0xfe, 0x9c, 0x32, 0x5f,
13250 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c,
13251 0xfe, 0x0a, 0xf0, 0xfe,
13252 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08,
13253 0xaf, 0xa0, 0x05, 0x29,
13254 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
13255 0x00, 0x01, 0x08, 0x14,
13256 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08,
13257 0x14, 0x00, 0x05, 0xfe,
13258 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06,
13259 0x12, 0xfe, 0x30, 0x13,
13260 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
13261 0x01, 0x08, 0x14, 0x00,
13262 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a,
13263 0x78, 0x4f, 0x0f, 0xfe,
13264 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d,
13265 0x28, 0x48, 0xfe, 0x6c,
13266 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
13267 0x12, 0x53, 0x63, 0x4e,
13268 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe,
13269 0x6c, 0x08, 0xaf, 0xa0,
13270 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24,
13271 0x05, 0xed, 0xfe, 0x9c,
13272 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
13273 0x1e, 0xfe, 0x99, 0x58,
13274 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a,
13275 0x22, 0x6b, 0x01, 0x0c,
13276 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e,
13277 0x1e, 0x47, 0x2c, 0x7a,
13278 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
13279 0x01, 0x0c, 0x61, 0x65,
13280 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a,
13281 0x16, 0xfe, 0x08, 0x50,
13282 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10,
13283 0x01, 0xfe, 0xce, 0x1e,
13284 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
13285 0x01, 0xfe, 0xfe, 0x1e,
13286 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a,
13287 0x10, 0x01, 0x0c, 0x06,
13288 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e,
13289 0x10, 0x6a, 0x22, 0x6b,
13290 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
13291 0xfe, 0x9f, 0x83, 0x33,
13292 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93,
13293 0x3a, 0x0b, 0xfe, 0xc6,
13294 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d,
13295 0x01, 0xfe, 0xce, 0x1e,
13296 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
13297 0x04, 0xfe, 0xc0, 0x93,
13298 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e,
13299 0x10, 0x4b, 0x22, 0x4c,
13300 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe,
13301 0x4e, 0x11, 0x2f, 0xfe,
13302 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
13303 0x3c, 0x37, 0x88, 0xf5,
13304 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a,
13305 0xd3, 0xfe, 0x42, 0x0a,
13306 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0,
13307 0x05, 0x29, 0x01, 0x41,
13308 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
13309 0xfe, 0x14, 0x12, 0x01,
13310 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe,
13311 0x2e, 0x1c, 0x05, 0xfe,
13312 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41,
13313 0xfe, 0x2c, 0x1c, 0xfe,
13314 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
13315 0x92, 0x10, 0xc4, 0xf6,
13316 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe,
13317 0xe7, 0x10, 0xfe, 0x2b,
13318 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12,
13319 0xac, 0xfe, 0xd2, 0xf0,
13320 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
13321 0x1b, 0xbf, 0xd4, 0x5b,
13322 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75,
13323 0x5e, 0x32, 0x1f, 0x7f,
13324 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98,
13325 0x05, 0x70, 0xfe, 0x74,
13326 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
13327 0x0f, 0x4d, 0x01, 0xfe,
13328 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06,
13329 0x0d, 0x2b, 0xfe, 0xe2,
13330 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24,
13331 0xfe, 0x88, 0x13, 0x21,
13332 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
13333 0x83, 0x83, 0xfe, 0xc9,
13334 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04,
13335 0x91, 0x04, 0xfe, 0x84,
13336 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93,
13337 0xfe, 0xcb, 0x57, 0x0b,
13338 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
13339 0x6a, 0x3b, 0x6b, 0x10,
13340 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30,
13341 0x20, 0x6e, 0xdb, 0x64,
13342 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55,
13343 0xfe, 0x04, 0xfa, 0x64,
13344 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
13345 0x10, 0x98, 0x91, 0x6c,
13346 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91,
13347 0x4b, 0x7e, 0x4c, 0x01,
13348 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10,
13349 0x58, 0xfe, 0x91, 0x58,
13350 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
13351 0x1b, 0x40, 0x01, 0x0c,
13352 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f,
13353 0xfe, 0x10, 0x90, 0x04,
13354 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93,
13355 0x79, 0x0b, 0x0e, 0xfe,
13356 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
13357 0x01, 0x0c, 0x06, 0x0d,
13358 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe,
13359 0x0c, 0x58, 0xfe, 0x8d,
13360 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99,
13361 0x83, 0x33, 0x0b, 0x0e,
13362 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
13363 0x19, 0xfe, 0x19, 0x41,
13364 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42,
13365 0x19, 0xfe, 0x44, 0x00,
13366 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda,
13367 0x4c, 0xfe, 0x0c, 0x51,
13368 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
13369 0x76, 0x10, 0xac, 0xfe,
13370 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03,
13371 0xe3, 0x23, 0x07, 0xfe,
13372 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe,
13373 0xcc, 0x0c, 0x1f, 0x92,
13374 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
13375 0x0c, 0xfe, 0x3e, 0x10,
13376 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70,
13377 0xfe, 0xcb, 0xf0, 0xfe,
13378 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe,
13379 0xf4, 0x0c, 0x19, 0x94,
13380 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
13381 0xfe, 0xcc, 0xf0, 0xef,
13382 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe,
13383 0x4e, 0x11, 0x2f, 0xfe,
13384 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b,
13385 0x3c, 0x37, 0x88, 0xf5,
13386 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
13387 0x2f, 0xfe, 0x3e, 0x0d,
13388 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f,
13389 0xd2, 0x9f, 0xd3, 0x9f,
13390 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4,
13391 0xc5, 0x75, 0xd7, 0x99,
13392 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
13393 0x9c, 0x2f, 0xfe, 0x8c,
13394 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe,
13395 0x42, 0x00, 0x05, 0x70,
13396 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06,
13397 0x0d, 0xfe, 0x44, 0x13,
13398 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
13399 0xfe, 0xda, 0x0e, 0x0a,
13400 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa,
13401 0x10, 0x01, 0xfe, 0xf4,
13402 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40,
13403 0x15, 0x56, 0x01, 0x85,
13404 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
13405 0xcc, 0x10, 0x01, 0xa7,
13406 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04,
13407 0xfe, 0x99, 0x83, 0xfe,
13408 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe,
13409 0x43, 0x00, 0xfe, 0xa2,
13410 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
13411 0x00, 0x1d, 0x40, 0x15,
13412 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05,
13413 0xfe, 0x3a, 0x03, 0x01,
13414 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01,
13415 0x76, 0x06, 0x12, 0xfe,
13416 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
13417 0xfe, 0x9d, 0xf0, 0xfe,
13418 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01,
13419 0x0c, 0x61, 0x12, 0x44,
13420 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f,
13421 0xfe, 0x2e, 0x10, 0x19,
13422 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
13423 0xfe, 0x41, 0x00, 0xa2,
13424 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b,
13425 0xea, 0x4f, 0xfe, 0x04,
13426 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05,
13427 0x35, 0xfe, 0x12, 0x1c,
13428 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
13429 0xfe, 0xd4, 0x11, 0x05,
13430 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe,
13431 0xce, 0x45, 0x31, 0x51,
13432 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03,
13433 0x67, 0xfe, 0x98, 0x56,
13434 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
13435 0x0c, 0x06, 0x28, 0xfe,
13436 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba,
13437 0xfe, 0xfa, 0x14, 0xfe,
13438 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67,
13439 0xfe, 0xe0, 0x14, 0xfe,
13440 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
13441 0xfe, 0xad, 0x13, 0x05,
13442 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20,
13443 0xe7, 0xfe, 0x08, 0x1c,
13444 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe,
13445 0x48, 0x55, 0xa5, 0x3b,
13446 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
13447 0xf0, 0x1a, 0x03, 0xfe,
13448 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02,
13449 0xec, 0xe7, 0x53, 0x00,
13450 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
13451 0x01, 0xfe, 0x62, 0x1b,
13452 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
13453 0xea, 0xe7, 0x53, 0x92,
13454 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03,
13455 0xfe, 0x38, 0x01, 0x23,
13456 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62,
13457 0x01, 0x01, 0xfe, 0x1e,
13458 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
13459 0x26, 0x02, 0x21, 0x96,
13460 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5,
13461 0xc3, 0xfe, 0xe1, 0x10,
13462 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf,
13463 0xfe, 0x03, 0xdc, 0xfe,
13464 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
13465 0x00, 0xcc, 0x02, 0xfe,
13466 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13,
13467 0x0f, 0xfe, 0x1c, 0x80,
13468 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13,
13469 0x0f, 0xfe, 0x1e, 0x80,
13470 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
13471 0x1d, 0x80, 0x04, 0xfe,
13472 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee,
13473 0x1e, 0xac, 0xfe, 0x14,
13474 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e,
13475 0x1f, 0xfe, 0x30, 0xf4,
13476 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
13477 0x56, 0xfb, 0x01, 0xfe,
13478 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01,
13479 0xfe, 0x00, 0x1d, 0x15,
13480 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe,
13481 0x22, 0x1b, 0xfe, 0x1e,
13482 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
13483 0x96, 0x90, 0x04, 0xfe,
13484 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66,
13485 0x01, 0x01, 0x0c, 0x06,
13486 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b,
13487 0x0e, 0x77, 0xfe, 0x01,
13488 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
13489 0x21, 0x2c, 0xfe, 0x00,
13490 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe,
13491 0x06, 0x58, 0x03, 0xfe,
13492 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58,
13493 0x03, 0xfe, 0xb2, 0x00,
13494 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
13495 0x66, 0x10, 0x55, 0x10,
13496 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91,
13497 0x54, 0x2b, 0xfe, 0x88,
13498 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe,
13499 0x91, 0x54, 0x2b, 0xfe,
13500 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
13501 0x00, 0x40, 0x8d, 0x2c,
13502 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe,
13503 0x12, 0x1c, 0x75, 0xfe,
13504 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c,
13505 0x14, 0xfe, 0x0e, 0x47,
13506 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
13507 0xa7, 0x90, 0x34, 0x60,
13508 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80,
13509 0x09, 0x56, 0xfe, 0x34,
13510 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48,
13511 0xfe, 0x45, 0x48, 0x01,
13512 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
13513 0x09, 0x1a, 0xa5, 0x0a,
13514 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4,
13515 0xfe, 0x14, 0x56, 0xfe,
13516 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01,
13517 0xec, 0xb8, 0xfe, 0x9e,
13518 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
13519 0xf4, 0xfe, 0xdd, 0x10,
13520 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48,
13521 0x12, 0x09, 0x0d, 0xfe,
13522 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4,
13523 0x13, 0x09, 0xfe, 0x23,
13524 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
13525 0x24, 0xfe, 0x12, 0x12,
13526 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08,
13527 0xae, 0x41, 0x02, 0x32,
13528 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05,
13529 0x35, 0x32, 0x01, 0x43,
13530 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
13531 0x13, 0x01, 0x0c, 0x06,
13532 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe,
13533 0xe5, 0x55, 0xb0, 0xfe,
13534 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e,
13535 0xfe, 0xb6, 0x0e, 0x10,
13536 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
13537 0x88, 0x20, 0x6e, 0x01,
13538 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5,
13539 0x55, 0xfe, 0x04, 0xfa,
13540 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d,
13541 0xfe, 0x40, 0x56, 0xfe,
13542 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
13543 0x44, 0x55, 0xfe, 0xe5,
13544 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10,
13545 0x68, 0x22, 0x69, 0x01,
13546 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b,
13547 0x6b, 0xfe, 0x2c, 0x50,
13548 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
13549 0x50, 0x03, 0x68, 0x3b,
13550 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe,
13551 0x40, 0x50, 0xfe, 0xc2,
13552 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08,
13553 0x16, 0x3d, 0x27, 0x25,
13554 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
13555 0xa6, 0x23, 0x3f, 0x1b,
13556 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c,
13557 0xfe, 0x0a, 0x55, 0x31,
13558 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e,
13559 0x51, 0x05, 0x72, 0x01,
13560 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
13561 0x2a, 0x3c, 0x16, 0xc0,
13562 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b,
13563 0xfe, 0x66, 0x15, 0x05,
13564 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d,
13565 0x2b, 0x3d, 0x01, 0x08,
13566 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
13567 0xb6, 0x1e, 0x83, 0x01,
13568 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46,
13569 0x07, 0x90, 0x3f, 0x01,
13570 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13,
13571 0x01, 0x43, 0x09, 0x82,
13572 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
13573 0x05, 0x72, 0xfe, 0xc0,
13574 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e,
13575 0x32, 0x01, 0x08, 0x17,
13576 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16,
13577 0x3d, 0x27, 0x25, 0xbd,
13578 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
13579 0xe8, 0x14, 0x01, 0xa6,
13580 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe,
13581 0x0e, 0x12, 0x01, 0x43,
13582 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32,
13583 0x01, 0x08, 0x17, 0x73,
13584 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
13585 0x27, 0x25, 0xbd, 0x09,
13586 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe,
13587 0xb6, 0x14, 0x86, 0xa8,
13588 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09,
13589 0x82, 0x4e, 0x05, 0x72,
13590 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
13591 0xfe, 0xc0, 0x19, 0x05,
13592 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f,
13593 0xcc, 0x01, 0x08, 0x26,
13594 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe,
13595 0xcc, 0x15, 0x5e, 0x32,
13596 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
13597 0xad, 0x23, 0xfe, 0xff,
13598 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02,
13599 0x00, 0x57, 0x52, 0xad,
13600 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff,
13601 0x02, 0x00, 0x57, 0x52,
13602 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
13603 0x02, 0x13, 0x58, 0xff,
13604 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01,
13605 0x5c, 0x0a, 0x55, 0x01,
13606 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a,
13607 0xff, 0x03, 0x00, 0x54,
13608 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
13609 0x7c, 0x3a, 0x0b, 0x0e,
13610 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19,
13611 0xfe, 0x1a, 0xf7, 0x00,
13612 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c,
13613 0xda, 0x6d, 0x02, 0xfe,
13614 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
13615 0x02, 0x01, 0xc6, 0xfe,
13616 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27,
13617 0x25, 0xbe, 0x01, 0x08,
13618 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59,
13619 0x03, 0x9a, 0x1e, 0xfe,
13620 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
13621 0x48, 0xfe, 0x08, 0x17,
13622 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26,
13623 0x17, 0x4d, 0x13, 0x07,
13624 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1,
13625 0xff, 0x02, 0x83, 0x55,
13626 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
13627 0x17, 0x1c, 0x63, 0x13,
13628 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64,
13629 0x00, 0xb0, 0xfe, 0x80,
13630 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10,
13631 0x53, 0x07, 0xfe, 0x60,
13632 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
13633 0x00, 0x1c, 0x95, 0x13,
13634 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3,
13635 0xfe, 0x43, 0xf4, 0x96,
13636 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43,
13637 0xf4, 0x94, 0xf6, 0x8b,
13638 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
13639 0xda, 0x17, 0x62, 0x49,
13640 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80,
13641 0x71, 0x50, 0x26, 0xfe,
13642 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3,
13643 0x58, 0x02, 0x50, 0x13,
13644 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
13645 0x25, 0xbe, 0xfe, 0x03,
13646 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9,
13647 0x0a, 0x01, 0x08, 0x16,
13648 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01,
13649 0x01, 0x08, 0x16, 0xa9,
13650 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
13651 0x08, 0x16, 0xa9, 0x27,
13652 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83,
13653 0x01, 0x38, 0x06, 0x24,
13654 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1,
13655 0x78, 0x03, 0x9a, 0x1e,
13656 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
13657 0xfe, 0x40, 0x5a, 0x23,
13658 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c,
13659 0x80, 0x48, 0xfe, 0xaa,
13660 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01,
13661 0xfe, 0xac, 0x1d, 0xfe,
13662 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
13663 0x43, 0x48, 0x2d, 0x93,
13664 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4,
13665 0x36, 0xfe, 0x34, 0xf4,
13666 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe,
13667 0x28, 0x10, 0xfe, 0xc0,
13668 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
13669 0x18, 0x45, 0xfe, 0x1c,
13670 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c,
13671 0x19, 0xfe, 0x04, 0xf4,
13672 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d,
13673 0x21, 0xfe, 0x7f, 0x01,
13674 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
13675 0x7e, 0x01, 0xfe, 0xc8,
13676 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa,
13677 0x21, 0xfe, 0x81, 0x01,
13678 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50,
13679 0x13, 0x0d, 0x02, 0x14,
13680 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
13681 0xfe, 0x82, 0x19, 0x14,
13682 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01,
13683 0x08, 0x02, 0x14, 0x07,
13684 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07,
13685 0x01, 0x08, 0x17, 0xc1,
13686 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
13687 0x08, 0x02, 0x50, 0x02,
13688 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74,
13689 0x14, 0x12, 0x01, 0x08,
13690 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01,
13691 0x08, 0x17, 0x74, 0xfe,
13692 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
13693 0x74, 0x5f, 0xcc, 0x01,
13694 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4,
13695 0xfe, 0x49, 0xf4, 0x00,
13696 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff,
13697 0x02, 0x00, 0x10, 0x2f,
13698 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
13699 0x16, 0xfe, 0x64, 0x1a,
13700 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c,
13701 0x61, 0x07, 0x44, 0x02,
13702 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12,
13703 0x13, 0x0a, 0x9d, 0x01,
13704 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
13705 0xfe, 0x80, 0xe7, 0x1a,
13706 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02,
13707 0x0a, 0x5a, 0x01, 0x18,
13708 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe,
13709 0x7e, 0x1e, 0xfe, 0x80,
13710 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
13711 0xfe, 0x80, 0x4c, 0x0a,
13712 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf,
13713 0xfe, 0x19, 0xde, 0xfe,
13714 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe,
13715 0x2a, 0x1c, 0xfa, 0xb3,
13716 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
13717 0xf4, 0x1a, 0xfe, 0xfa,
13718 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24,
13719 0xfe, 0x18, 0x58, 0x03,
13720 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f,
13721 0xfe, 0x30, 0xf4, 0x07,
13722 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
13723 0xf7, 0x24, 0xb1, 0xfe,
13724 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b,
13725 0xfe, 0xba, 0x10, 0x1c,
13726 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
13727 0x1d, 0xf7, 0x54, 0xb1,
13728 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
13729 0xaf, 0x19, 0xfe, 0x98,
13730 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c,
13731 0x1a, 0x87, 0x8b, 0x0f,
13732 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58,
13733 0xfe, 0x32, 0x90, 0x04,
13734 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
13735 0x7c, 0x12, 0xfe, 0x0f,
13736 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14,
13737 0x31, 0x02, 0xc9, 0x2b,
13738 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe,
13739 0x6a, 0xfe, 0x19, 0xfe,
13740 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
13741 0x1b, 0xfe, 0x36, 0x14,
13742 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19,
13743 0xfe, 0x80, 0xe7, 0x1a,
13744 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a,
13745 0x30, 0xfe, 0x12, 0x45,
13746 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
13747 0x39, 0xf0, 0x75, 0x26,
13748 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03,
13749 0xe3, 0x23, 0x07, 0xfe,
13750 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09,
13751 0x56, 0xfe, 0x3c, 0x13,
13752 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
13753 0x01, 0x18, 0xcb, 0xfe,
13754 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16,
13755 0xfe, 0x00, 0xcc, 0xcb,
13756 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18,
13757 0xfe, 0x80, 0x4c, 0x01,
13758 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
13759 0x12, 0xfe, 0x14, 0x56,
13760 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7,
13761 0x0d, 0x19, 0xfe, 0x15,
13762 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06,
13763 0x83, 0xfe, 0x18, 0x80,
13764 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
13765 0x90, 0xfe, 0xba, 0x90,
13766 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02,
13767 0x21, 0xb9, 0x88, 0x20,
13768 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01,
13769 0x18, 0xfe, 0x49, 0x44,
13770 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
13771 0x1a, 0xa4, 0x0a, 0x67,
13772 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4,
13773 0x1d, 0x7b, 0xfe, 0x52,
13774 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe,
13775 0x4e, 0xe4, 0xdd, 0x7b,
13776 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
13777 0xfe, 0x4e, 0xe4, 0xfe,
13778 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24,
13779 0xfe, 0x08, 0x10, 0x03,
13780 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04,
13781 0x68, 0x54, 0xfe, 0xf1,
13782 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
13783 0xfe, 0x1a, 0xf4, 0xfe,
13784 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02,
13785 0x09, 0x92, 0xfe, 0x5a,
13786 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe,
13787 0x5a, 0xf0, 0xfe, 0xc8,
13788 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
13789 0x1a, 0x10, 0x09, 0x0d,
13790 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02,
13791 0x1f, 0x93, 0x01, 0x42,
13792 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e,
13793 0xfe, 0x14, 0xf0, 0x08,
13794 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
13795 0xfe, 0x82, 0xf0, 0xfe,
13796 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e,
13797 0x02, 0x0f, 0xfe, 0x18,
13798 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02,
13799 0x80, 0x04, 0xfe, 0x82,
13800 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
13801 0x83, 0x33, 0x0b, 0x0e,
13802 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e,
13803 0x02, 0x0f, 0xfe, 0x04,
13804 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80,
13805 0x80, 0x04, 0xfe, 0x80,
13806 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
13807 0xfe, 0x99, 0x83, 0xfe,
13808 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86,
13809 0x83, 0xfe, 0xce, 0x47,
13810 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a,
13811 0x0b, 0x0e, 0x02, 0x0f,
13812 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
13813 0xfe, 0x08, 0x90, 0x04,
13814 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04,
13815 0xfe, 0x8a, 0x93, 0x79,
13816 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a,
13817 0x0b, 0x0e, 0x02, 0x0f,
13818 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
13819 0xfe, 0x3c, 0x90, 0x04,
13820 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80,
13821 0x04, 0xfe, 0x83, 0x83,
13822 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070013823};
13824
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013825static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
13826static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013827
13828/* a_init.c */
13829/*
13830 * EEPROM Configuration.
13831 *
13832 * All drivers should use this structure to set the default EEPROM
13833 * configuration. The BIOS now uses this structure when it is built.
13834 * Additional structure information can be found in a_condor.h where
13835 * the structure is defined.
13836 *
13837 * The *_Field_IsChar structs are needed to correct for endianness.
13838 * These values are read from the board 16 bits at a time directly
13839 * into the structs. Because some fields are char, the values will be
13840 * in the wrong order. The *_Field_IsChar tells when to flip the
13841 * bytes. Data read and written to PCI memory is automatically swapped
13842 * on big-endian platforms so char fields read as words are actually being
13843 * unswapped on big-endian platforms.
13844 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013845static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __initdata = {
13846 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
13847 0x0000, /* cfg_msw */
13848 0xFFFF, /* disc_enable */
13849 0xFFFF, /* wdtr_able */
13850 0xFFFF, /* sdtr_able */
13851 0xFFFF, /* start_motor */
13852 0xFFFF, /* tagqng_able */
13853 0xFFFF, /* bios_scan */
13854 0, /* scam_tolerant */
13855 7, /* adapter_scsi_id */
13856 0, /* bios_boot_delay */
13857 3, /* scsi_reset_delay */
13858 0, /* bios_id_lun */
13859 0, /* termination */
13860 0, /* reserved1 */
13861 0xFFE7, /* bios_ctrl */
13862 0xFFFF, /* ultra_able */
13863 0, /* reserved2 */
13864 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
13865 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13866 0, /* dvc_cntl */
13867 0, /* bug_fix */
13868 0, /* serial_number_word1 */
13869 0, /* serial_number_word2 */
13870 0, /* serial_number_word3 */
13871 0, /* check_sum */
13872 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13873 , /* oem_name[16] */
13874 0, /* dvc_err_code */
13875 0, /* adv_err_code */
13876 0, /* adv_err_addr */
13877 0, /* saved_dvc_err_code */
13878 0, /* saved_adv_err_code */
13879 0, /* saved_adv_err_addr */
13880 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013881};
13882
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013883static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = {
13884 0, /* cfg_lsw */
13885 0, /* cfg_msw */
13886 0, /* -disc_enable */
13887 0, /* wdtr_able */
13888 0, /* sdtr_able */
13889 0, /* start_motor */
13890 0, /* tagqng_able */
13891 0, /* bios_scan */
13892 0, /* scam_tolerant */
13893 1, /* adapter_scsi_id */
13894 1, /* bios_boot_delay */
13895 1, /* scsi_reset_delay */
13896 1, /* bios_id_lun */
13897 1, /* termination */
13898 1, /* reserved1 */
13899 0, /* bios_ctrl */
13900 0, /* ultra_able */
13901 0, /* reserved2 */
13902 1, /* max_host_qng */
13903 1, /* max_dvc_qng */
13904 0, /* dvc_cntl */
13905 0, /* bug_fix */
13906 0, /* serial_number_word1 */
13907 0, /* serial_number_word2 */
13908 0, /* serial_number_word3 */
13909 0, /* check_sum */
13910 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13911 , /* oem_name[16] */
13912 0, /* dvc_err_code */
13913 0, /* adv_err_code */
13914 0, /* adv_err_addr */
13915 0, /* saved_dvc_err_code */
13916 0, /* saved_adv_err_code */
13917 0, /* saved_adv_err_addr */
13918 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013919};
13920
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013921static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = {
13922 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
13923 0x0000, /* 01 cfg_msw */
13924 0xFFFF, /* 02 disc_enable */
13925 0xFFFF, /* 03 wdtr_able */
13926 0x4444, /* 04 sdtr_speed1 */
13927 0xFFFF, /* 05 start_motor */
13928 0xFFFF, /* 06 tagqng_able */
13929 0xFFFF, /* 07 bios_scan */
13930 0, /* 08 scam_tolerant */
13931 7, /* 09 adapter_scsi_id */
13932 0, /* bios_boot_delay */
13933 3, /* 10 scsi_reset_delay */
13934 0, /* bios_id_lun */
13935 0, /* 11 termination_se */
13936 0, /* termination_lvd */
13937 0xFFE7, /* 12 bios_ctrl */
13938 0x4444, /* 13 sdtr_speed2 */
13939 0x4444, /* 14 sdtr_speed3 */
13940 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
13941 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13942 0, /* 16 dvc_cntl */
13943 0x4444, /* 17 sdtr_speed4 */
13944 0, /* 18 serial_number_word1 */
13945 0, /* 19 serial_number_word2 */
13946 0, /* 20 serial_number_word3 */
13947 0, /* 21 check_sum */
13948 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13949 , /* 22-29 oem_name[16] */
13950 0, /* 30 dvc_err_code */
13951 0, /* 31 adv_err_code */
13952 0, /* 32 adv_err_addr */
13953 0, /* 33 saved_dvc_err_code */
13954 0, /* 34 saved_adv_err_code */
13955 0, /* 35 saved_adv_err_addr */
13956 0, /* 36 reserved */
13957 0, /* 37 reserved */
13958 0, /* 38 reserved */
13959 0, /* 39 reserved */
13960 0, /* 40 reserved */
13961 0, /* 41 reserved */
13962 0, /* 42 reserved */
13963 0, /* 43 reserved */
13964 0, /* 44 reserved */
13965 0, /* 45 reserved */
13966 0, /* 46 reserved */
13967 0, /* 47 reserved */
13968 0, /* 48 reserved */
13969 0, /* 49 reserved */
13970 0, /* 50 reserved */
13971 0, /* 51 reserved */
13972 0, /* 52 reserved */
13973 0, /* 53 reserved */
13974 0, /* 54 reserved */
13975 0, /* 55 reserved */
13976 0, /* 56 cisptr_lsw */
13977 0, /* 57 cisprt_msw */
13978 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
13979 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
13980 0, /* 60 reserved */
13981 0, /* 61 reserved */
13982 0, /* 62 reserved */
13983 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013984};
13985
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013986static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = {
13987 0, /* 00 cfg_lsw */
13988 0, /* 01 cfg_msw */
13989 0, /* 02 disc_enable */
13990 0, /* 03 wdtr_able */
13991 0, /* 04 sdtr_speed1 */
13992 0, /* 05 start_motor */
13993 0, /* 06 tagqng_able */
13994 0, /* 07 bios_scan */
13995 0, /* 08 scam_tolerant */
13996 1, /* 09 adapter_scsi_id */
13997 1, /* bios_boot_delay */
13998 1, /* 10 scsi_reset_delay */
13999 1, /* bios_id_lun */
14000 1, /* 11 termination_se */
14001 1, /* termination_lvd */
14002 0, /* 12 bios_ctrl */
14003 0, /* 13 sdtr_speed2 */
14004 0, /* 14 sdtr_speed3 */
14005 1, /* 15 max_host_qng */
14006 1, /* max_dvc_qng */
14007 0, /* 16 dvc_cntl */
14008 0, /* 17 sdtr_speed4 */
14009 0, /* 18 serial_number_word1 */
14010 0, /* 19 serial_number_word2 */
14011 0, /* 20 serial_number_word3 */
14012 0, /* 21 check_sum */
14013 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
14014 , /* 22-29 oem_name[16] */
14015 0, /* 30 dvc_err_code */
14016 0, /* 31 adv_err_code */
14017 0, /* 32 adv_err_addr */
14018 0, /* 33 saved_dvc_err_code */
14019 0, /* 34 saved_adv_err_code */
14020 0, /* 35 saved_adv_err_addr */
14021 0, /* 36 reserved */
14022 0, /* 37 reserved */
14023 0, /* 38 reserved */
14024 0, /* 39 reserved */
14025 0, /* 40 reserved */
14026 0, /* 41 reserved */
14027 0, /* 42 reserved */
14028 0, /* 43 reserved */
14029 0, /* 44 reserved */
14030 0, /* 45 reserved */
14031 0, /* 46 reserved */
14032 0, /* 47 reserved */
14033 0, /* 48 reserved */
14034 0, /* 49 reserved */
14035 0, /* 50 reserved */
14036 0, /* 51 reserved */
14037 0, /* 52 reserved */
14038 0, /* 53 reserved */
14039 0, /* 54 reserved */
14040 0, /* 55 reserved */
14041 0, /* 56 cisptr_lsw */
14042 0, /* 57 cisprt_msw */
14043 0, /* 58 subsysvid */
14044 0, /* 59 subsysid */
14045 0, /* 60 reserved */
14046 0, /* 61 reserved */
14047 0, /* 62 reserved */
14048 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014049};
14050
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014051static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = {
14052 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
14053 0x0000, /* 01 cfg_msw */
14054 0xFFFF, /* 02 disc_enable */
14055 0xFFFF, /* 03 wdtr_able */
14056 0x5555, /* 04 sdtr_speed1 */
14057 0xFFFF, /* 05 start_motor */
14058 0xFFFF, /* 06 tagqng_able */
14059 0xFFFF, /* 07 bios_scan */
14060 0, /* 08 scam_tolerant */
14061 7, /* 09 adapter_scsi_id */
14062 0, /* bios_boot_delay */
14063 3, /* 10 scsi_reset_delay */
14064 0, /* bios_id_lun */
14065 0, /* 11 termination_se */
14066 0, /* termination_lvd */
14067 0xFFE7, /* 12 bios_ctrl */
14068 0x5555, /* 13 sdtr_speed2 */
14069 0x5555, /* 14 sdtr_speed3 */
14070 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
14071 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
14072 0, /* 16 dvc_cntl */
14073 0x5555, /* 17 sdtr_speed4 */
14074 0, /* 18 serial_number_word1 */
14075 0, /* 19 serial_number_word2 */
14076 0, /* 20 serial_number_word3 */
14077 0, /* 21 check_sum */
14078 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
14079 , /* 22-29 oem_name[16] */
14080 0, /* 30 dvc_err_code */
14081 0, /* 31 adv_err_code */
14082 0, /* 32 adv_err_addr */
14083 0, /* 33 saved_dvc_err_code */
14084 0, /* 34 saved_adv_err_code */
14085 0, /* 35 saved_adv_err_addr */
14086 0, /* 36 reserved */
14087 0, /* 37 reserved */
14088 0, /* 38 reserved */
14089 0, /* 39 reserved */
14090 0, /* 40 reserved */
14091 0, /* 41 reserved */
14092 0, /* 42 reserved */
14093 0, /* 43 reserved */
14094 0, /* 44 reserved */
14095 0, /* 45 reserved */
14096 0, /* 46 reserved */
14097 0, /* 47 reserved */
14098 0, /* 48 reserved */
14099 0, /* 49 reserved */
14100 0, /* 50 reserved */
14101 0, /* 51 reserved */
14102 0, /* 52 reserved */
14103 0, /* 53 reserved */
14104 0, /* 54 reserved */
14105 0, /* 55 reserved */
14106 0, /* 56 cisptr_lsw */
14107 0, /* 57 cisprt_msw */
14108 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
14109 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
14110 0, /* 60 reserved */
14111 0, /* 61 reserved */
14112 0, /* 62 reserved */
14113 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014114};
14115
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014116static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = {
14117 0, /* 00 cfg_lsw */
14118 0, /* 01 cfg_msw */
14119 0, /* 02 disc_enable */
14120 0, /* 03 wdtr_able */
14121 0, /* 04 sdtr_speed1 */
14122 0, /* 05 start_motor */
14123 0, /* 06 tagqng_able */
14124 0, /* 07 bios_scan */
14125 0, /* 08 scam_tolerant */
14126 1, /* 09 adapter_scsi_id */
14127 1, /* bios_boot_delay */
14128 1, /* 10 scsi_reset_delay */
14129 1, /* bios_id_lun */
14130 1, /* 11 termination_se */
14131 1, /* termination_lvd */
14132 0, /* 12 bios_ctrl */
14133 0, /* 13 sdtr_speed2 */
14134 0, /* 14 sdtr_speed3 */
14135 1, /* 15 max_host_qng */
14136 1, /* max_dvc_qng */
14137 0, /* 16 dvc_cntl */
14138 0, /* 17 sdtr_speed4 */
14139 0, /* 18 serial_number_word1 */
14140 0, /* 19 serial_number_word2 */
14141 0, /* 20 serial_number_word3 */
14142 0, /* 21 check_sum */
14143 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
14144 , /* 22-29 oem_name[16] */
14145 0, /* 30 dvc_err_code */
14146 0, /* 31 adv_err_code */
14147 0, /* 32 adv_err_addr */
14148 0, /* 33 saved_dvc_err_code */
14149 0, /* 34 saved_adv_err_code */
14150 0, /* 35 saved_adv_err_addr */
14151 0, /* 36 reserved */
14152 0, /* 37 reserved */
14153 0, /* 38 reserved */
14154 0, /* 39 reserved */
14155 0, /* 40 reserved */
14156 0, /* 41 reserved */
14157 0, /* 42 reserved */
14158 0, /* 43 reserved */
14159 0, /* 44 reserved */
14160 0, /* 45 reserved */
14161 0, /* 46 reserved */
14162 0, /* 47 reserved */
14163 0, /* 48 reserved */
14164 0, /* 49 reserved */
14165 0, /* 50 reserved */
14166 0, /* 51 reserved */
14167 0, /* 52 reserved */
14168 0, /* 53 reserved */
14169 0, /* 54 reserved */
14170 0, /* 55 reserved */
14171 0, /* 56 cisptr_lsw */
14172 0, /* 57 cisprt_msw */
14173 0, /* 58 subsysvid */
14174 0, /* 59 subsysid */
14175 0, /* 60 reserved */
14176 0, /* 61 reserved */
14177 0, /* 62 reserved */
14178 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014179};
14180
14181/*
14182 * Initialize the ADV_DVC_VAR structure.
14183 *
14184 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14185 *
14186 * For a non-fatal error return a warning code. If there are no warnings
14187 * then 0 is returned.
14188 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189static int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014190{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014191 ushort warn_code;
14192 AdvPortAddr iop_base;
14193 uchar pci_cmd_reg;
14194 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014195
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014196 warn_code = 0;
14197 asc_dvc->err_code = 0;
14198 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014200 /*
14201 * PCI Command Register
14202 *
14203 * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes
14204 * I/O Space Control, Memory Space Control and Bus Master Control bits.
14205 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014206
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014207 if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
14208 AscPCIConfigCommandRegister))
14209 & AscPCICmdRegBits_BusMastering)
14210 != AscPCICmdRegBits_BusMastering) {
14211 pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014212
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014213 DvcAdvWritePCIConfigByte(asc_dvc,
14214 AscPCIConfigCommandRegister,
14215 pci_cmd_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014216
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014217 if (((DvcAdvReadPCIConfigByte
14218 (asc_dvc, AscPCIConfigCommandRegister))
14219 & AscPCICmdRegBits_BusMastering)
14220 != AscPCICmdRegBits_BusMastering) {
14221 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14222 }
14223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014224
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014225 /*
14226 * PCI Latency Timer
14227 *
14228 * If the "latency timer" register is 0x20 or above, then we don't need
14229 * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
14230 * comes up less than 0x20).
14231 */
14232 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
14233 DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer,
14234 0x20);
14235 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) <
14236 0x20) {
14237 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14238 }
14239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014241 /*
14242 * Save the state of the PCI Configuration Command Register
14243 * "Parity Error Response Control" Bit. If the bit is clear (0),
14244 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
14245 * DMA parity errors.
14246 */
14247 asc_dvc->cfg->control_flag = 0;
14248 if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
14249 & AscPCICmdRegBits_ParErrRespCtrl)) == 0) {
14250 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
14251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014252
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014253 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
14254 ADV_LIB_VERSION_MINOR;
14255 asc_dvc->cfg->chip_version =
14256 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014257
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014258 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
14259 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
14260 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014261
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014262 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
14263 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
14264 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014265
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014266 /*
14267 * Reset the chip to start and allow register writes.
14268 */
14269 if (AdvFindSignature(iop_base) == 0) {
14270 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
14271 return ADV_ERROR;
14272 } else {
14273 /*
14274 * The caller must set 'chip_type' to a valid setting.
14275 */
14276 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
14277 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
14278 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
14279 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
14280 return ADV_ERROR;
14281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014282
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014283 /*
14284 * Reset Chip.
14285 */
14286 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
14287 ADV_CTRL_REG_CMD_RESET);
14288 DvcSleepMilliSecond(100);
14289 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
14290 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014291
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014292 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14293 if ((status =
14294 AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) {
14295 return ADV_ERROR;
14296 }
14297 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14298 if ((status =
14299 AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) {
14300 return ADV_ERROR;
14301 }
14302 } else {
14303 if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) {
14304 return ADV_ERROR;
14305 }
14306 }
14307 warn_code |= status;
14308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014309
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014310 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014311}
14312
14313/*
14314 * Initialize the ASC-3550.
14315 *
14316 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14317 *
14318 * For a non-fatal error return a warning code. If there are no warnings
14319 * then 0 is returned.
14320 *
14321 * Needed after initialization for error recovery.
14322 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014323static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014324{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014325 AdvPortAddr iop_base;
14326 ushort warn_code;
14327 ADV_DCNT sum;
14328 int begin_addr;
14329 int end_addr;
14330 ushort code_sum;
14331 int word;
14332 int j;
14333 int adv_asc3550_expanded_size;
14334 ADV_CARR_T *carrp;
14335 ADV_DCNT contig_len;
14336 ADV_SDCNT buf_size;
14337 ADV_PADDR carr_paddr;
14338 int i;
14339 ushort scsi_cfg1;
14340 uchar tid;
14341 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
14342 ushort wdtr_able = 0, sdtr_able, tagqng_able;
14343 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070014344
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014345 /* If there is already an error, don't continue. */
14346 if (asc_dvc->err_code != 0) {
14347 return ADV_ERROR;
14348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014349
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014350 /*
14351 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
14352 */
14353 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
14354 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
14355 return ADV_ERROR;
14356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014357
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014358 warn_code = 0;
14359 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014360
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014361 /*
14362 * Save the RISC memory BIOS region before writing the microcode.
14363 * The BIOS may already be loaded and using its RISC LRAM region
14364 * so its region must be saved and restored.
14365 *
14366 * Note: This code makes the assumption, which is currently true,
14367 * that a chip reset does not clear RISC LRAM.
14368 */
14369 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14370 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14371 bios_mem[i]);
14372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014374 /*
14375 * Save current per TID negotiated values.
14376 */
14377 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
14378 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014379
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014380 bios_version =
14381 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
14382 major = (bios_version >> 12) & 0xF;
14383 minor = (bios_version >> 8) & 0xF;
14384 if (major < 3 || (major == 3 && minor == 1)) {
14385 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
14386 AdvReadWordLram(iop_base, 0x120, wdtr_able);
14387 } else {
14388 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14389 }
14390 }
14391 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14392 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14393 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14394 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14395 max_cmd[tid]);
14396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014397
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014398 /*
14399 * Load the Microcode
14400 *
14401 * Write the microcode image to RISC memory starting at address 0.
14402 */
14403 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14404 /* Assume the following compressed format of the microcode buffer:
14405 *
14406 * 254 word (508 byte) table indexed by byte code followed
14407 * by the following byte codes:
14408 *
14409 * 1-Byte Code:
14410 * 00: Emit word 0 in table.
14411 * 01: Emit word 1 in table.
14412 * .
14413 * FD: Emit word 253 in table.
14414 *
14415 * Multi-Byte Code:
14416 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
14417 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
14418 */
14419 word = 0;
14420 for (i = 253 * 2; i < _adv_asc3550_size; i++) {
14421 if (_adv_asc3550_buf[i] == 0xff) {
14422 for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) {
14423 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14424 _adv_asc3550_buf
14425 [i +
14426 3] << 8) |
14427 _adv_asc3550_buf
14428 [i + 2]));
14429 word++;
14430 }
14431 i += 3;
14432 } else if (_adv_asc3550_buf[i] == 0xfe) {
14433 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14434 _adv_asc3550_buf[i +
14435 2]
14436 << 8) |
14437 _adv_asc3550_buf[i +
14438 1]));
14439 i += 2;
14440 word++;
14441 } else {
14442 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14443 _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
14444 word++;
14445 }
14446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014447
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014448 /*
14449 * Set 'word' for later use to clear the rest of memory and save
14450 * the expanded mcode size.
14451 */
14452 word *= 2;
14453 adv_asc3550_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014454
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014455 /*
14456 * Clear the rest of ASC-3550 Internal RAM (8KB).
14457 */
14458 for (; word < ADV_3550_MEMSIZE; word += 2) {
14459 AdvWriteWordAutoIncLram(iop_base, 0);
14460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014461
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014462 /*
14463 * Verify the microcode checksum.
14464 */
14465 sum = 0;
14466 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014467
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014468 for (word = 0; word < adv_asc3550_expanded_size; word += 2) {
14469 sum += AdvReadWordAutoIncLram(iop_base);
14470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014471
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014472 if (sum != _adv_asc3550_chksum) {
14473 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14474 return ADV_ERROR;
14475 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014476
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014477 /*
14478 * Restore the RISC memory BIOS region.
14479 */
14480 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14481 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14482 bios_mem[i]);
14483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014484
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014485 /*
14486 * Calculate and write the microcode code checksum to the microcode
14487 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14488 */
14489 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14490 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14491 code_sum = 0;
14492 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
14493 for (word = begin_addr; word < end_addr; word += 2) {
14494 code_sum += AdvReadWordAutoIncLram(iop_base);
14495 }
14496 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014497
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014498 /*
14499 * Read and save microcode version and date.
14500 */
14501 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
14502 asc_dvc->cfg->mcode_date);
14503 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
14504 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014505
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014506 /*
14507 * Set the chip type to indicate the ASC3550.
14508 */
14509 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014510
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014511 /*
14512 * If the PCI Configuration Command Register "Parity Error Response
14513 * Control" Bit was clear (0), then set the microcode variable
14514 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14515 * to ignore DMA parity errors.
14516 */
14517 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
14518 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14519 word |= CONTROL_FLAG_IGNORE_PERR;
14520 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014522
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014523 /*
14524 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
14525 * threshold of 128 bytes. This register is only accessible to the host.
14526 */
14527 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14528 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014529
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014530 /*
14531 * Microcode operating variables for WDTR, SDTR, and command tag
14532 * queuing will be set in AdvInquiryHandling() based on what a
14533 * device reports it is capable of in Inquiry byte 7.
14534 *
14535 * If SCSI Bus Resets have been disabled, then directly set
14536 * SDTR and WDTR from the EEPROM configuration. This will allow
14537 * the BIOS and warm boot to work without a SCSI bus hang on
14538 * the Inquiry caused by host and target mismatched DTR values.
14539 * Without the SCSI Bus Reset, before an Inquiry a device can't
14540 * be assumed to be in Asynchronous, Narrow mode.
14541 */
14542 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
14543 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
14544 asc_dvc->wdtr_able);
14545 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
14546 asc_dvc->sdtr_able);
14547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014548
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014549 /*
14550 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
14551 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
14552 * bitmask. These values determine the maximum SDTR speed negotiated
14553 * with a device.
14554 *
14555 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
14556 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
14557 * without determining here whether the device supports SDTR.
14558 *
14559 * 4-bit speed SDTR speed name
14560 * =========== ===============
14561 * 0000b (0x0) SDTR disabled
14562 * 0001b (0x1) 5 Mhz
14563 * 0010b (0x2) 10 Mhz
14564 * 0011b (0x3) 20 Mhz (Ultra)
14565 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
14566 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
14567 * 0110b (0x6) Undefined
14568 * .
14569 * 1111b (0xF) Undefined
14570 */
14571 word = 0;
14572 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14573 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
14574 /* Set Ultra speed for TID 'tid'. */
14575 word |= (0x3 << (4 * (tid % 4)));
14576 } else {
14577 /* Set Fast speed for TID 'tid'. */
14578 word |= (0x2 << (4 * (tid % 4)));
14579 }
14580 if (tid == 3) { /* Check if done with sdtr_speed1. */
14581 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
14582 word = 0;
14583 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
14584 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
14585 word = 0;
14586 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
14587 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
14588 word = 0;
14589 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
14590 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
14591 /* End of loop. */
14592 }
14593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014594
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014595 /*
14596 * Set microcode operating variable for the disconnect per TID bitmask.
14597 */
14598 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
14599 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014601 /*
14602 * Set SCSI_CFG0 Microcode Default Value.
14603 *
14604 * The microcode will set the SCSI_CFG0 register using this value
14605 * after it is started below.
14606 */
14607 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14608 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
14609 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014610
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014611 /*
14612 * Determine SCSI_CFG1 Microcode Default Value.
14613 *
14614 * The microcode will set the SCSI_CFG1 register using this value
14615 * after it is started below.
14616 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014617
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014618 /* Read current SCSI_CFG1 Register value. */
14619 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014620
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014621 /*
14622 * If all three connectors are in use, return an error.
14623 */
14624 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
14625 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
14626 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
14627 return ADV_ERROR;
14628 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014629
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014630 /*
14631 * If the internal narrow cable is reversed all of the SCSI_CTRL
14632 * register signals will be set. Check for and return an error if
14633 * this condition is found.
14634 */
14635 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
14636 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14637 return ADV_ERROR;
14638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014639
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014640 /*
14641 * If this is a differential board and a single-ended device
14642 * is attached to one of the connectors, return an error.
14643 */
14644 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
14645 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
14646 return ADV_ERROR;
14647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014648
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014649 /*
14650 * If automatic termination control is enabled, then set the
14651 * termination value based on a table listed in a_condor.h.
14652 *
14653 * If manual termination was specified with an EEPROM setting
14654 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
14655 * is ready to be 'ored' into SCSI_CFG1.
14656 */
14657 if (asc_dvc->cfg->termination == 0) {
14658 /*
14659 * The software always controls termination by setting TERM_CTL_SEL.
14660 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
14661 */
14662 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014663
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014664 switch (scsi_cfg1 & CABLE_DETECT) {
14665 /* TERM_CTL_H: on, TERM_CTL_L: on */
14666 case 0x3:
14667 case 0x7:
14668 case 0xB:
14669 case 0xD:
14670 case 0xE:
14671 case 0xF:
14672 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
14673 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014674
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014675 /* TERM_CTL_H: on, TERM_CTL_L: off */
14676 case 0x1:
14677 case 0x5:
14678 case 0x9:
14679 case 0xA:
14680 case 0xC:
14681 asc_dvc->cfg->termination |= TERM_CTL_H;
14682 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014683
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014684 /* TERM_CTL_H: off, TERM_CTL_L: off */
14685 case 0x2:
14686 case 0x6:
14687 break;
14688 }
14689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014690
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014691 /*
14692 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
14693 */
14694 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014695
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014696 /*
14697 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
14698 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
14699 * referenced, because the hardware internally inverts
14700 * the Termination High and Low bits if TERM_POL is set.
14701 */
14702 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014703
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014704 /*
14705 * Set SCSI_CFG1 Microcode Default Value
14706 *
14707 * Set filter value and possibly modified termination control
14708 * bits in the Microcode SCSI_CFG1 Register Value.
14709 *
14710 * The microcode will set the SCSI_CFG1 register using this value
14711 * after it is started below.
14712 */
14713 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
14714 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014715
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014716 /*
14717 * Set MEM_CFG Microcode Default Value
14718 *
14719 * The microcode will set the MEM_CFG register using this value
14720 * after it is started below.
14721 *
14722 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
14723 * are defined.
14724 *
14725 * ASC-3550 has 8KB internal memory.
14726 */
14727 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
14728 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014729
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014730 /*
14731 * Set SEL_MASK Microcode Default Value
14732 *
14733 * The microcode will set the SEL_MASK register using this value
14734 * after it is started below.
14735 */
14736 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14737 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014738
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014739 /*
14740 * Build carrier freelist.
14741 *
14742 * Driver must have already allocated memory and set 'carrier_buf'.
14743 */
14744 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014745
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014746 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
14747 asc_dvc->carr_freelist = NULL;
14748 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
14749 buf_size = ADV_CARRIER_BUFSIZE;
14750 } else {
14751 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
14752 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014753
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014754 do {
14755 /*
14756 * Get physical address of the carrier 'carrp'.
14757 */
14758 contig_len = sizeof(ADV_CARR_T);
14759 carr_paddr =
14760 cpu_to_le32(DvcGetPhyAddr
14761 (asc_dvc, NULL, (uchar *)carrp,
14762 (ADV_SDCNT *)&contig_len,
14763 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014764
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014765 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014766
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014767 /*
14768 * If the current carrier is not physically contiguous, then
14769 * maybe there was a page crossing. Try the next carrier aligned
14770 * start address.
14771 */
14772 if (contig_len < sizeof(ADV_CARR_T)) {
14773 carrp++;
14774 continue;
14775 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014776
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014777 carrp->carr_pa = carr_paddr;
14778 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014779
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014780 /*
14781 * Insert the carrier at the beginning of the freelist.
14782 */
14783 carrp->next_vpa =
14784 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14785 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014786
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014787 carrp++;
14788 }
14789 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014790
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014791 /*
14792 * Set-up the Host->RISC Initiator Command Queue (ICQ).
14793 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014794
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014795 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
14796 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14797 return ADV_ERROR;
14798 }
14799 asc_dvc->carr_freelist = (ADV_CARR_T *)
14800 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014801
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014802 /*
14803 * The first command issued will be placed in the stopper carrier.
14804 */
14805 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014806
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014807 /*
14808 * Set RISC ICQ physical address start value.
14809 */
14810 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014811
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014812 /*
14813 * Set-up the RISC->Host Initiator Response Queue (IRQ).
14814 */
14815 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
14816 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14817 return ADV_ERROR;
14818 }
14819 asc_dvc->carr_freelist = (ADV_CARR_T *)
14820 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014821
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014822 /*
14823 * The first command completed by the RISC will be placed in
14824 * the stopper.
14825 *
14826 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
14827 * completed the RISC will set the ASC_RQ_STOPPER bit.
14828 */
14829 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014831 /*
14832 * Set RISC IRQ physical address start value.
14833 */
14834 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
14835 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014836
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014837 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14838 (ADV_INTR_ENABLE_HOST_INTR |
14839 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014841 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14842 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014843
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014844 /* finally, finally, gentlemen, start your engine */
14845 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014847 /*
14848 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14849 * Resets should be performed. The RISC has to be running
14850 * to issue a SCSI Bus Reset.
14851 */
14852 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
14853 /*
14854 * If the BIOS Signature is present in memory, restore the
14855 * BIOS Handshake Configuration Table and do not perform
14856 * a SCSI Bus Reset.
14857 */
14858 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
14859 0x55AA) {
14860 /*
14861 * Restore per TID negotiated values.
14862 */
14863 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14864 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14865 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
14866 tagqng_able);
14867 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14868 AdvWriteByteLram(iop_base,
14869 ASC_MC_NUMBER_OF_MAX_CMD + tid,
14870 max_cmd[tid]);
14871 }
14872 } else {
14873 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
14874 warn_code = ASC_WARN_BUSRESET_ERROR;
14875 }
14876 }
14877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014878
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014879 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014880}
14881
14882/*
14883 * Initialize the ASC-38C0800.
14884 *
14885 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14886 *
14887 * For a non-fatal error return a warning code. If there are no warnings
14888 * then 0 is returned.
14889 *
14890 * Needed after initialization for error recovery.
14891 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014892static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014893{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014894 AdvPortAddr iop_base;
14895 ushort warn_code;
14896 ADV_DCNT sum;
14897 int begin_addr;
14898 int end_addr;
14899 ushort code_sum;
14900 int word;
14901 int j;
14902 int adv_asc38C0800_expanded_size;
14903 ADV_CARR_T *carrp;
14904 ADV_DCNT contig_len;
14905 ADV_SDCNT buf_size;
14906 ADV_PADDR carr_paddr;
14907 int i;
14908 ushort scsi_cfg1;
14909 uchar byte;
14910 uchar tid;
14911 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
14912 ushort wdtr_able, sdtr_able, tagqng_able;
14913 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070014914
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014915 /* If there is already an error, don't continue. */
14916 if (asc_dvc->err_code != 0) {
14917 return ADV_ERROR;
14918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014919
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014920 /*
14921 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
14922 */
14923 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
14924 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
14925 return ADV_ERROR;
14926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014927
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014928 warn_code = 0;
14929 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014930
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014931 /*
14932 * Save the RISC memory BIOS region before writing the microcode.
14933 * The BIOS may already be loaded and using its RISC LRAM region
14934 * so its region must be saved and restored.
14935 *
14936 * Note: This code makes the assumption, which is currently true,
14937 * that a chip reset does not clear RISC LRAM.
14938 */
14939 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14940 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14941 bios_mem[i]);
14942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014943
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014944 /*
14945 * Save current per TID negotiated values.
14946 */
14947 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14948 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14949 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14950 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14951 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14952 max_cmd[tid]);
14953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014954
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014955 /*
14956 * RAM BIST (RAM Built-In Self Test)
14957 *
14958 * Address : I/O base + offset 0x38h register (byte).
14959 * Function: Bit 7-6(RW) : RAM mode
14960 * Normal Mode : 0x00
14961 * Pre-test Mode : 0x40
14962 * RAM Test Mode : 0x80
14963 * Bit 5 : unused
14964 * Bit 4(RO) : Done bit
14965 * Bit 3-0(RO) : Status
14966 * Host Error : 0x08
14967 * Int_RAM Error : 0x04
14968 * RISC Error : 0x02
14969 * SCSI Error : 0x01
14970 * No Error : 0x00
14971 *
14972 * Note: RAM BIST code should be put right here, before loading the
14973 * microcode and after saving the RISC memory BIOS region.
14974 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014975
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014976 /*
14977 * LRAM Pre-test
14978 *
14979 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
14980 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
14981 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
14982 * to NORMAL_MODE, return an error too.
14983 */
14984 for (i = 0; i < 2; i++) {
14985 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
14986 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14987 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14988 if ((byte & RAM_TEST_DONE) == 0
14989 || (byte & 0x0F) != PRE_TEST_VALUE) {
14990 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14991 return ADV_ERROR;
14992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014993
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014994 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
14995 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14996 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
14997 != NORMAL_VALUE) {
14998 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14999 return ADV_ERROR;
15000 }
15001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015002
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015003 /*
15004 * LRAM Test - It takes about 1.5 ms to run through the test.
15005 *
15006 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
15007 * If Done bit not set or Status not 0, save register byte, set the
15008 * err_code, and return an error.
15009 */
15010 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
15011 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015012
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015013 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
15014 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
15015 /* Get here if Done bit not set or Status not 0. */
15016 asc_dvc->bist_err_code = byte; /* for BIOS display message */
15017 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
15018 return ADV_ERROR;
15019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015020
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015021 /* We need to reset back to normal mode after LRAM test passes. */
15022 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015023
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015024 /*
15025 * Load the Microcode
15026 *
15027 * Write the microcode image to RISC memory starting at address 0.
15028 *
15029 */
15030 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015031
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015032 /* Assume the following compressed format of the microcode buffer:
15033 *
15034 * 254 word (508 byte) table indexed by byte code followed
15035 * by the following byte codes:
15036 *
15037 * 1-Byte Code:
15038 * 00: Emit word 0 in table.
15039 * 01: Emit word 1 in table.
15040 * .
15041 * FD: Emit word 253 in table.
15042 *
15043 * Multi-Byte Code:
15044 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
15045 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
15046 */
15047 word = 0;
15048 for (i = 253 * 2; i < _adv_asc38C0800_size; i++) {
15049 if (_adv_asc38C0800_buf[i] == 0xff) {
15050 for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) {
15051 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15052 _adv_asc38C0800_buf
15053 [i +
15054 3] << 8) |
15055 _adv_asc38C0800_buf
15056 [i + 2]));
15057 word++;
15058 }
15059 i += 3;
15060 } else if (_adv_asc38C0800_buf[i] == 0xfe) {
15061 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15062 _adv_asc38C0800_buf
15063 [i +
15064 2] << 8) |
15065 _adv_asc38C0800_buf[i
15066 +
15067 1]));
15068 i += 2;
15069 word++;
15070 } else {
15071 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15072 _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
15073 word++;
15074 }
15075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015076
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015077 /*
15078 * Set 'word' for later use to clear the rest of memory and save
15079 * the expanded mcode size.
15080 */
15081 word *= 2;
15082 adv_asc38C0800_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015083
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015084 /*
15085 * Clear the rest of ASC-38C0800 Internal RAM (16KB).
15086 */
15087 for (; word < ADV_38C0800_MEMSIZE; word += 2) {
15088 AdvWriteWordAutoIncLram(iop_base, 0);
15089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015090
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015091 /*
15092 * Verify the microcode checksum.
15093 */
15094 sum = 0;
15095 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015096
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015097 for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) {
15098 sum += AdvReadWordAutoIncLram(iop_base);
15099 }
15100 ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015102 ASC_DBG2(1,
15103 "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n",
15104 (ulong)sum, (ulong)_adv_asc38C0800_chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015105
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015106 if (sum != _adv_asc38C0800_chksum) {
15107 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
15108 return ADV_ERROR;
15109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015111 /*
15112 * Restore the RISC memory BIOS region.
15113 */
15114 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
15115 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
15116 bios_mem[i]);
15117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015118
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015119 /*
15120 * Calculate and write the microcode code checksum to the microcode
15121 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
15122 */
15123 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
15124 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
15125 code_sum = 0;
15126 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
15127 for (word = begin_addr; word < end_addr; word += 2) {
15128 code_sum += AdvReadWordAutoIncLram(iop_base);
15129 }
15130 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015131
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015132 /*
15133 * Read microcode version and date.
15134 */
15135 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
15136 asc_dvc->cfg->mcode_date);
15137 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
15138 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015140 /*
15141 * Set the chip type to indicate the ASC38C0800.
15142 */
15143 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015144
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015145 /*
15146 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
15147 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
15148 * cable detection and then we are able to read C_DET[3:0].
15149 *
15150 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
15151 * Microcode Default Value' section below.
15152 */
15153 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
15154 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
15155 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015156
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015157 /*
15158 * If the PCI Configuration Command Register "Parity Error Response
15159 * Control" Bit was clear (0), then set the microcode variable
15160 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
15161 * to ignore DMA parity errors.
15162 */
15163 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
15164 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15165 word |= CONTROL_FLAG_IGNORE_PERR;
15166 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015168
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015169 /*
15170 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
15171 * bits for the default FIFO threshold.
15172 *
15173 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
15174 *
15175 * For DMA Errata #4 set the BC_THRESH_ENB bit.
15176 */
15177 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
15178 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
15179 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015180
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015181 /*
15182 * Microcode operating variables for WDTR, SDTR, and command tag
15183 * queuing will be set in AdvInquiryHandling() based on what a
15184 * device reports it is capable of in Inquiry byte 7.
15185 *
15186 * If SCSI Bus Resets have been disabled, then directly set
15187 * SDTR and WDTR from the EEPROM configuration. This will allow
15188 * the BIOS and warm boot to work without a SCSI bus hang on
15189 * the Inquiry caused by host and target mismatched DTR values.
15190 * Without the SCSI Bus Reset, before an Inquiry a device can't
15191 * be assumed to be in Asynchronous, Narrow mode.
15192 */
15193 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
15194 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
15195 asc_dvc->wdtr_able);
15196 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
15197 asc_dvc->sdtr_able);
15198 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015200 /*
15201 * Set microcode operating variables for DISC and SDTR_SPEED1,
15202 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
15203 * configuration values.
15204 *
15205 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
15206 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
15207 * without determining here whether the device supports SDTR.
15208 */
15209 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
15210 asc_dvc->cfg->disc_enable);
15211 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
15212 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
15213 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
15214 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015215
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015216 /*
15217 * Set SCSI_CFG0 Microcode Default Value.
15218 *
15219 * The microcode will set the SCSI_CFG0 register using this value
15220 * after it is started below.
15221 */
15222 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
15223 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
15224 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015225
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015226 /*
15227 * Determine SCSI_CFG1 Microcode Default Value.
15228 *
15229 * The microcode will set the SCSI_CFG1 register using this value
15230 * after it is started below.
15231 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015232
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015233 /* Read current SCSI_CFG1 Register value. */
15234 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015235
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015236 /*
15237 * If the internal narrow cable is reversed all of the SCSI_CTRL
15238 * register signals will be set. Check for and return an error if
15239 * this condition is found.
15240 */
15241 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
15242 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
15243 return ADV_ERROR;
15244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015245
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015246 /*
15247 * All kind of combinations of devices attached to one of four connectors
15248 * are acceptable except HVD device attached. For example, LVD device can
15249 * be attached to SE connector while SE device attached to LVD connector.
15250 * If LVD device attached to SE connector, it only runs up to Ultra speed.
15251 *
15252 * If an HVD device is attached to one of LVD connectors, return an error.
15253 * However, there is no way to detect HVD device attached to SE connectors.
15254 */
15255 if (scsi_cfg1 & HVD) {
15256 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
15257 return ADV_ERROR;
15258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015259
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015260 /*
15261 * If either SE or LVD automatic termination control is enabled, then
15262 * set the termination value based on a table listed in a_condor.h.
15263 *
15264 * If manual termination was specified with an EEPROM setting then
15265 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to
15266 * be 'ored' into SCSI_CFG1.
15267 */
15268 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
15269 /* SE automatic termination control is enabled. */
15270 switch (scsi_cfg1 & C_DET_SE) {
15271 /* TERM_SE_HI: on, TERM_SE_LO: on */
15272 case 0x1:
15273 case 0x2:
15274 case 0x3:
15275 asc_dvc->cfg->termination |= TERM_SE;
15276 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015277
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015278 /* TERM_SE_HI: on, TERM_SE_LO: off */
15279 case 0x0:
15280 asc_dvc->cfg->termination |= TERM_SE_HI;
15281 break;
15282 }
15283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015284
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015285 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
15286 /* LVD automatic termination control is enabled. */
15287 switch (scsi_cfg1 & C_DET_LVD) {
15288 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
15289 case 0x4:
15290 case 0x8:
15291 case 0xC:
15292 asc_dvc->cfg->termination |= TERM_LVD;
15293 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015294
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015295 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
15296 case 0x0:
15297 break;
15298 }
15299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015300
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015301 /*
15302 * Clear any set TERM_SE and TERM_LVD bits.
15303 */
15304 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015305
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015306 /*
15307 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
15308 */
15309 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015310
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015311 /*
15312 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits
15313 * and set possibly modified termination control bits in the Microcode
15314 * SCSI_CFG1 Register Value.
15315 */
15316 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015317
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015318 /*
15319 * Set SCSI_CFG1 Microcode Default Value
15320 *
15321 * Set possibly modified termination control and reset DIS_TERM_DRV
15322 * bits in the Microcode SCSI_CFG1 Register Value.
15323 *
15324 * The microcode will set the SCSI_CFG1 register using this value
15325 * after it is started below.
15326 */
15327 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015328
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015329 /*
15330 * Set MEM_CFG Microcode Default Value
15331 *
15332 * The microcode will set the MEM_CFG register using this value
15333 * after it is started below.
15334 *
15335 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
15336 * are defined.
15337 *
15338 * ASC-38C0800 has 16KB internal memory.
15339 */
15340 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15341 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015342
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015343 /*
15344 * Set SEL_MASK Microcode Default Value
15345 *
15346 * The microcode will set the SEL_MASK register using this value
15347 * after it is started below.
15348 */
15349 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
15350 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015351
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015352 /*
15353 * Build the carrier freelist.
15354 *
15355 * Driver must have already allocated memory and set 'carrier_buf'.
15356 */
15357 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015358
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015359 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
15360 asc_dvc->carr_freelist = NULL;
15361 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
15362 buf_size = ADV_CARRIER_BUFSIZE;
15363 } else {
15364 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
15365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015366
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015367 do {
15368 /*
15369 * Get physical address for the carrier 'carrp'.
15370 */
15371 contig_len = sizeof(ADV_CARR_T);
15372 carr_paddr =
15373 cpu_to_le32(DvcGetPhyAddr
15374 (asc_dvc, NULL, (uchar *)carrp,
15375 (ADV_SDCNT *)&contig_len,
15376 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015377
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015378 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015379
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015380 /*
15381 * If the current carrier is not physically contiguous, then
15382 * maybe there was a page crossing. Try the next carrier aligned
15383 * start address.
15384 */
15385 if (contig_len < sizeof(ADV_CARR_T)) {
15386 carrp++;
15387 continue;
15388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015389
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015390 carrp->carr_pa = carr_paddr;
15391 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015392
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015393 /*
15394 * Insert the carrier at the beginning of the freelist.
15395 */
15396 carrp->next_vpa =
15397 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
15398 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015399
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015400 carrp++;
15401 }
15402 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015403
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015404 /*
15405 * Set-up the Host->RISC Initiator Command Queue (ICQ).
15406 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015407
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015408 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
15409 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15410 return ADV_ERROR;
15411 }
15412 asc_dvc->carr_freelist = (ADV_CARR_T *)
15413 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015414
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015415 /*
15416 * The first command issued will be placed in the stopper carrier.
15417 */
15418 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015419
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015420 /*
15421 * Set RISC ICQ physical address start value.
15422 * carr_pa is LE, must be native before write
15423 */
15424 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015425
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015426 /*
15427 * Set-up the RISC->Host Initiator Response Queue (IRQ).
15428 */
15429 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
15430 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15431 return ADV_ERROR;
15432 }
15433 asc_dvc->carr_freelist = (ADV_CARR_T *)
15434 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015435
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015436 /*
15437 * The first command completed by the RISC will be placed in
15438 * the stopper.
15439 *
15440 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
15441 * completed the RISC will set the ASC_RQ_STOPPER bit.
15442 */
15443 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015444
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015445 /*
15446 * Set RISC IRQ physical address start value.
15447 *
15448 * carr_pa is LE, must be native before write *
15449 */
15450 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
15451 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015452
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015453 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
15454 (ADV_INTR_ENABLE_HOST_INTR |
15455 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015456
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015457 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
15458 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015459
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015460 /* finally, finally, gentlemen, start your engine */
15461 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015462
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015463 /*
15464 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
15465 * Resets should be performed. The RISC has to be running
15466 * to issue a SCSI Bus Reset.
15467 */
15468 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
15469 /*
15470 * If the BIOS Signature is present in memory, restore the
15471 * BIOS Handshake Configuration Table and do not perform
15472 * a SCSI Bus Reset.
15473 */
15474 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
15475 0x55AA) {
15476 /*
15477 * Restore per TID negotiated values.
15478 */
15479 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15480 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15481 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
15482 tagqng_able);
15483 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
15484 AdvWriteByteLram(iop_base,
15485 ASC_MC_NUMBER_OF_MAX_CMD + tid,
15486 max_cmd[tid]);
15487 }
15488 } else {
15489 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
15490 warn_code = ASC_WARN_BUSRESET_ERROR;
15491 }
15492 }
15493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015494
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015495 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015496}
15497
15498/*
15499 * Initialize the ASC-38C1600.
15500 *
15501 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
15502 *
15503 * For a non-fatal error return a warning code. If there are no warnings
15504 * then 0 is returned.
15505 *
15506 * Needed after initialization for error recovery.
15507 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015508static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015509{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015510 AdvPortAddr iop_base;
15511 ushort warn_code;
15512 ADV_DCNT sum;
15513 int begin_addr;
15514 int end_addr;
15515 ushort code_sum;
15516 long word;
15517 int j;
15518 int adv_asc38C1600_expanded_size;
15519 ADV_CARR_T *carrp;
15520 ADV_DCNT contig_len;
15521 ADV_SDCNT buf_size;
15522 ADV_PADDR carr_paddr;
15523 int i;
15524 ushort scsi_cfg1;
15525 uchar byte;
15526 uchar tid;
15527 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
15528 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
15529 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070015530
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015531 /* If there is already an error, don't continue. */
15532 if (asc_dvc->err_code != 0) {
15533 return ADV_ERROR;
15534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015535
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015536 /*
15537 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
15538 */
15539 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
15540 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
15541 return ADV_ERROR;
15542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015543
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015544 warn_code = 0;
15545 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015546
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015547 /*
15548 * Save the RISC memory BIOS region before writing the microcode.
15549 * The BIOS may already be loaded and using its RISC LRAM region
15550 * so its region must be saved and restored.
15551 *
15552 * Note: This code makes the assumption, which is currently true,
15553 * that a chip reset does not clear RISC LRAM.
15554 */
15555 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
15556 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
15557 bios_mem[i]);
15558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015559
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015560 /*
15561 * Save current per TID negotiated values.
15562 */
15563 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15564 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15565 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
15566 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
15567 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
15568 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
15569 max_cmd[tid]);
15570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015571
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015572 /*
15573 * RAM BIST (Built-In Self Test)
15574 *
15575 * Address : I/O base + offset 0x38h register (byte).
15576 * Function: Bit 7-6(RW) : RAM mode
15577 * Normal Mode : 0x00
15578 * Pre-test Mode : 0x40
15579 * RAM Test Mode : 0x80
15580 * Bit 5 : unused
15581 * Bit 4(RO) : Done bit
15582 * Bit 3-0(RO) : Status
15583 * Host Error : 0x08
15584 * Int_RAM Error : 0x04
15585 * RISC Error : 0x02
15586 * SCSI Error : 0x01
15587 * No Error : 0x00
15588 *
15589 * Note: RAM BIST code should be put right here, before loading the
15590 * microcode and after saving the RISC memory BIOS region.
15591 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015592
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015593 /*
15594 * LRAM Pre-test
15595 *
15596 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
15597 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
15598 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
15599 * to NORMAL_MODE, return an error too.
15600 */
15601 for (i = 0; i < 2; i++) {
15602 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
15603 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
15604 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
15605 if ((byte & RAM_TEST_DONE) == 0
15606 || (byte & 0x0F) != PRE_TEST_VALUE) {
15607 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
15608 return ADV_ERROR;
15609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015610
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015611 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
15612 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
15613 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
15614 != NORMAL_VALUE) {
15615 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
15616 return ADV_ERROR;
15617 }
15618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015619
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015620 /*
15621 * LRAM Test - It takes about 1.5 ms to run through the test.
15622 *
15623 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
15624 * If Done bit not set or Status not 0, save register byte, set the
15625 * err_code, and return an error.
15626 */
15627 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
15628 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015629
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015630 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
15631 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
15632 /* Get here if Done bit not set or Status not 0. */
15633 asc_dvc->bist_err_code = byte; /* for BIOS display message */
15634 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
15635 return ADV_ERROR;
15636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015637
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015638 /* We need to reset back to normal mode after LRAM test passes. */
15639 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015641 /*
15642 * Load the Microcode
15643 *
15644 * Write the microcode image to RISC memory starting at address 0.
15645 *
15646 */
15647 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015648
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015649 /*
15650 * Assume the following compressed format of the microcode buffer:
15651 *
15652 * 254 word (508 byte) table indexed by byte code followed
15653 * by the following byte codes:
15654 *
15655 * 1-Byte Code:
15656 * 00: Emit word 0 in table.
15657 * 01: Emit word 1 in table.
15658 * .
15659 * FD: Emit word 253 in table.
15660 *
15661 * Multi-Byte Code:
15662 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
15663 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
15664 */
15665 word = 0;
15666 for (i = 253 * 2; i < _adv_asc38C1600_size; i++) {
15667 if (_adv_asc38C1600_buf[i] == 0xff) {
15668 for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) {
15669 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15670 _adv_asc38C1600_buf
15671 [i +
15672 3] << 8) |
15673 _adv_asc38C1600_buf
15674 [i + 2]));
15675 word++;
15676 }
15677 i += 3;
15678 } else if (_adv_asc38C1600_buf[i] == 0xfe) {
15679 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15680 _adv_asc38C1600_buf
15681 [i +
15682 2] << 8) |
15683 _adv_asc38C1600_buf[i
15684 +
15685 1]));
15686 i += 2;
15687 word++;
15688 } else {
15689 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15690 _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2]));
15691 word++;
15692 }
15693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015694
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015695 /*
15696 * Set 'word' for later use to clear the rest of memory and save
15697 * the expanded mcode size.
15698 */
15699 word *= 2;
15700 adv_asc38C1600_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015701
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015702 /*
15703 * Clear the rest of ASC-38C1600 Internal RAM (32KB).
15704 */
15705 for (; word < ADV_38C1600_MEMSIZE; word += 2) {
15706 AdvWriteWordAutoIncLram(iop_base, 0);
15707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015708
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015709 /*
15710 * Verify the microcode checksum.
15711 */
15712 sum = 0;
15713 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015714
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015715 for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) {
15716 sum += AdvReadWordAutoIncLram(iop_base);
15717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015718
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015719 if (sum != _adv_asc38C1600_chksum) {
15720 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
15721 return ADV_ERROR;
15722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015723
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015724 /*
15725 * Restore the RISC memory BIOS region.
15726 */
15727 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
15728 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
15729 bios_mem[i]);
15730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015731
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015732 /*
15733 * Calculate and write the microcode code checksum to the microcode
15734 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
15735 */
15736 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
15737 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
15738 code_sum = 0;
15739 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
15740 for (word = begin_addr; word < end_addr; word += 2) {
15741 code_sum += AdvReadWordAutoIncLram(iop_base);
15742 }
15743 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015744
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015745 /*
15746 * Read microcode version and date.
15747 */
15748 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
15749 asc_dvc->cfg->mcode_date);
15750 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
15751 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015752
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015753 /*
15754 * Set the chip type to indicate the ASC38C1600.
15755 */
15756 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015758 /*
15759 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
15760 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
15761 * cable detection and then we are able to read C_DET[3:0].
15762 *
15763 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
15764 * Microcode Default Value' section below.
15765 */
15766 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
15767 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
15768 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015769
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015770 /*
15771 * If the PCI Configuration Command Register "Parity Error Response
15772 * Control" Bit was clear (0), then set the microcode variable
15773 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
15774 * to ignore DMA parity errors.
15775 */
15776 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
15777 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15778 word |= CONTROL_FLAG_IGNORE_PERR;
15779 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015781
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015782 /*
15783 * If the BIOS control flag AIPP (Asynchronous Information
15784 * Phase Protection) disable bit is not set, then set the firmware
15785 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
15786 * AIPP checking and encoding.
15787 */
15788 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
15789 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15790 word |= CONTROL_FLAG_ENABLE_AIPP;
15791 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15792 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015793
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015794 /*
15795 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
15796 * and START_CTL_TH [3:2].
15797 */
15798 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
15799 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015800
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015801 /*
15802 * Microcode operating variables for WDTR, SDTR, and command tag
15803 * queuing will be set in AdvInquiryHandling() based on what a
15804 * device reports it is capable of in Inquiry byte 7.
15805 *
15806 * If SCSI Bus Resets have been disabled, then directly set
15807 * SDTR and WDTR from the EEPROM configuration. This will allow
15808 * the BIOS and warm boot to work without a SCSI bus hang on
15809 * the Inquiry caused by host and target mismatched DTR values.
15810 * Without the SCSI Bus Reset, before an Inquiry a device can't
15811 * be assumed to be in Asynchronous, Narrow mode.
15812 */
15813 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
15814 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
15815 asc_dvc->wdtr_able);
15816 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
15817 asc_dvc->sdtr_able);
15818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015819
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015820 /*
15821 * Set microcode operating variables for DISC and SDTR_SPEED1,
15822 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
15823 * configuration values.
15824 *
15825 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
15826 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
15827 * without determining here whether the device supports SDTR.
15828 */
15829 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
15830 asc_dvc->cfg->disc_enable);
15831 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
15832 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
15833 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
15834 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015835
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015836 /*
15837 * Set SCSI_CFG0 Microcode Default Value.
15838 *
15839 * The microcode will set the SCSI_CFG0 register using this value
15840 * after it is started below.
15841 */
15842 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
15843 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
15844 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015845
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015846 /*
15847 * Calculate SCSI_CFG1 Microcode Default Value.
15848 *
15849 * The microcode will set the SCSI_CFG1 register using this value
15850 * after it is started below.
15851 *
15852 * Each ASC-38C1600 function has only two cable detect bits.
15853 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
15854 */
15855 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015857 /*
15858 * If the cable is reversed all of the SCSI_CTRL register signals
15859 * will be set. Check for and return an error if this condition is
15860 * found.
15861 */
15862 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
15863 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
15864 return ADV_ERROR;
15865 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015866
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015867 /*
15868 * Each ASC-38C1600 function has two connectors. Only an HVD device
15869 * can not be connected to either connector. An LVD device or SE device
15870 * may be connected to either connecor. If an SE device is connected,
15871 * then at most Ultra speed (20 Mhz) can be used on both connectors.
15872 *
15873 * If an HVD device is attached, return an error.
15874 */
15875 if (scsi_cfg1 & HVD) {
15876 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
15877 return ADV_ERROR;
15878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015879
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015880 /*
15881 * Each function in the ASC-38C1600 uses only the SE cable detect and
15882 * termination because there are two connectors for each function. Each
15883 * function may use either LVD or SE mode. Corresponding the SE automatic
15884 * termination control EEPROM bits are used for each function. Each
15885 * function has its own EEPROM. If SE automatic control is enabled for
15886 * the function, then set the termination value based on a table listed
15887 * in a_condor.h.
15888 *
15889 * If manual termination is specified in the EEPROM for the function,
15890 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
15891 * ready to be 'ored' into SCSI_CFG1.
15892 */
15893 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
15894 /* SE automatic termination control is enabled. */
15895 switch (scsi_cfg1 & C_DET_SE) {
15896 /* TERM_SE_HI: on, TERM_SE_LO: on */
15897 case 0x1:
15898 case 0x2:
15899 case 0x3:
15900 asc_dvc->cfg->termination |= TERM_SE;
15901 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015902
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015903 case 0x0:
15904 if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) {
15905 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
15906 } else {
15907 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
15908 asc_dvc->cfg->termination |= TERM_SE_HI;
15909 }
15910 break;
15911 }
15912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015913
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015914 /*
15915 * Clear any set TERM_SE bits.
15916 */
15917 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015918
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015919 /*
15920 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
15921 */
15922 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015923
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015924 /*
15925 * Clear Big Endian and Terminator Polarity bits and set possibly
15926 * modified termination control bits in the Microcode SCSI_CFG1
15927 * Register Value.
15928 *
15929 * Big Endian bit is not used even on big endian machines.
15930 */
15931 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015932
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015933 /*
15934 * Set SCSI_CFG1 Microcode Default Value
15935 *
15936 * Set possibly modified termination control bits in the Microcode
15937 * SCSI_CFG1 Register Value.
15938 *
15939 * The microcode will set the SCSI_CFG1 register using this value
15940 * after it is started below.
15941 */
15942 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015943
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015944 /*
15945 * Set MEM_CFG Microcode Default Value
15946 *
15947 * The microcode will set the MEM_CFG register using this value
15948 * after it is started below.
15949 *
15950 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
15951 * are defined.
15952 *
15953 * ASC-38C1600 has 32KB internal memory.
15954 *
15955 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
15956 * out a special 16K Adv Library and Microcode version. After the issue
15957 * resolved, we should turn back to the 32K support. Both a_condor.h and
15958 * mcode.sas files also need to be updated.
15959 *
15960 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15961 * BIOS_EN | RAM_SZ_32KB);
15962 */
15963 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15964 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015965
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015966 /*
15967 * Set SEL_MASK Microcode Default Value
15968 *
15969 * The microcode will set the SEL_MASK register using this value
15970 * after it is started below.
15971 */
15972 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
15973 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015974
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015975 /*
15976 * Build the carrier freelist.
15977 *
15978 * Driver must have already allocated memory and set 'carrier_buf'.
15979 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015980
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015981 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015982
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015983 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
15984 asc_dvc->carr_freelist = NULL;
15985 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
15986 buf_size = ADV_CARRIER_BUFSIZE;
15987 } else {
15988 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
15989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015991 do {
15992 /*
15993 * Get physical address for the carrier 'carrp'.
15994 */
15995 contig_len = sizeof(ADV_CARR_T);
15996 carr_paddr =
15997 cpu_to_le32(DvcGetPhyAddr
15998 (asc_dvc, NULL, (uchar *)carrp,
15999 (ADV_SDCNT *)&contig_len,
16000 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016001
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016002 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016003
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016004 /*
16005 * If the current carrier is not physically contiguous, then
16006 * maybe there was a page crossing. Try the next carrier aligned
16007 * start address.
16008 */
16009 if (contig_len < sizeof(ADV_CARR_T)) {
16010 carrp++;
16011 continue;
16012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016013
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016014 carrp->carr_pa = carr_paddr;
16015 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016016
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016017 /*
16018 * Insert the carrier at the beginning of the freelist.
16019 */
16020 carrp->next_vpa =
16021 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
16022 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016023
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016024 carrp++;
16025 }
16026 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016027
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016028 /*
16029 * Set-up the Host->RISC Initiator Command Queue (ICQ).
16030 */
16031 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
16032 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
16033 return ADV_ERROR;
16034 }
16035 asc_dvc->carr_freelist = (ADV_CARR_T *)
16036 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016037
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016038 /*
16039 * The first command issued will be placed in the stopper carrier.
16040 */
16041 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016042
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016043 /*
16044 * Set RISC ICQ physical address start value. Initialize the
16045 * COMMA register to the same value otherwise the RISC will
16046 * prematurely detect a command is available.
16047 */
16048 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
16049 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
16050 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016051
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016052 /*
16053 * Set-up the RISC->Host Initiator Response Queue (IRQ).
16054 */
16055 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
16056 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
16057 return ADV_ERROR;
16058 }
16059 asc_dvc->carr_freelist = (ADV_CARR_T *)
16060 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016061
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016062 /*
16063 * The first command completed by the RISC will be placed in
16064 * the stopper.
16065 *
16066 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
16067 * completed the RISC will set the ASC_RQ_STOPPER bit.
16068 */
16069 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016071 /*
16072 * Set RISC IRQ physical address start value.
16073 */
16074 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
16075 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016076
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016077 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
16078 (ADV_INTR_ENABLE_HOST_INTR |
16079 ADV_INTR_ENABLE_GLOBAL_INTR));
16080 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
16081 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016082
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016083 /* finally, finally, gentlemen, start your engine */
16084 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016085
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016086 /*
16087 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
16088 * Resets should be performed. The RISC has to be running
16089 * to issue a SCSI Bus Reset.
16090 */
16091 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
16092 /*
16093 * If the BIOS Signature is present in memory, restore the
16094 * per TID microcode operating variables.
16095 */
16096 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
16097 0x55AA) {
16098 /*
16099 * Restore per TID negotiated values.
16100 */
16101 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16102 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16103 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
16104 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
16105 tagqng_able);
16106 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
16107 AdvWriteByteLram(iop_base,
16108 ASC_MC_NUMBER_OF_MAX_CMD + tid,
16109 max_cmd[tid]);
16110 }
16111 } else {
16112 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
16113 warn_code = ASC_WARN_BUSRESET_ERROR;
16114 }
16115 }
16116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016117
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016118 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016119}
16120
16121/*
16122 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
16123 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
16124 * all of this is done.
16125 *
16126 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
16127 *
16128 * For a non-fatal error return a warning code. If there are no warnings
16129 * then 0 is returned.
16130 *
16131 * Note: Chip is stopped on entry.
16132 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016133static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016134{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016135 AdvPortAddr iop_base;
16136 ushort warn_code;
16137 ADVEEP_3550_CONFIG eep_config;
16138 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016140 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016141
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016142 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016144 /*
16145 * Read the board's EEPROM configuration.
16146 *
16147 * Set default values if a bad checksum is found.
16148 */
16149 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
16150 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016151
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016152 /*
16153 * Set EEPROM default values.
16154 */
16155 for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) {
16156 *((uchar *)&eep_config + i) =
16157 *((uchar *)&Default_3550_EEPROM_Config + i);
16158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016159
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016160 /*
16161 * Assume the 6 byte board serial number that was read
16162 * from EEPROM is correct even if the EEPROM checksum
16163 * failed.
16164 */
16165 eep_config.serial_number_word3 =
16166 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016167
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016168 eep_config.serial_number_word2 =
16169 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016170
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016171 eep_config.serial_number_word1 =
16172 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016173
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016174 AdvSet3550EEPConfig(iop_base, &eep_config);
16175 }
16176 /*
16177 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
16178 * EEPROM configuration that was read.
16179 *
16180 * This is the mapping of EEPROM fields to Adv Library fields.
16181 */
16182 asc_dvc->wdtr_able = eep_config.wdtr_able;
16183 asc_dvc->sdtr_able = eep_config.sdtr_able;
16184 asc_dvc->ultra_able = eep_config.ultra_able;
16185 asc_dvc->tagqng_able = eep_config.tagqng_able;
16186 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
16187 asc_dvc->max_host_qng = eep_config.max_host_qng;
16188 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16189 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
16190 asc_dvc->start_motor = eep_config.start_motor;
16191 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
16192 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
16193 asc_dvc->no_scam = eep_config.scam_tolerant;
16194 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
16195 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
16196 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016197
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016198 /*
16199 * Set the host maximum queuing (max. 253, min. 16) and the per device
16200 * maximum queuing (max. 63, min. 4).
16201 */
16202 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
16203 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16204 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
16205 /* If the value is zero, assume it is uninitialized. */
16206 if (eep_config.max_host_qng == 0) {
16207 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16208 } else {
16209 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
16210 }
16211 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016212
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016213 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
16214 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16215 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
16216 /* If the value is zero, assume it is uninitialized. */
16217 if (eep_config.max_dvc_qng == 0) {
16218 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16219 } else {
16220 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
16221 }
16222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016223
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016224 /*
16225 * If 'max_dvc_qng' is greater than 'max_host_qng', then
16226 * set 'max_dvc_qng' to 'max_host_qng'.
16227 */
16228 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
16229 eep_config.max_dvc_qng = eep_config.max_host_qng;
16230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016231
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016232 /*
16233 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
16234 * values based on possibly adjusted EEPROM values.
16235 */
16236 asc_dvc->max_host_qng = eep_config.max_host_qng;
16237 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016238
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016239 /*
16240 * If the EEPROM 'termination' field is set to automatic (0), then set
16241 * the ADV_DVC_CFG 'termination' field to automatic also.
16242 *
16243 * If the termination is specified with a non-zero 'termination'
16244 * value check that a legal value is set and set the ADV_DVC_CFG
16245 * 'termination' field appropriately.
16246 */
16247 if (eep_config.termination == 0) {
16248 asc_dvc->cfg->termination = 0; /* auto termination */
16249 } else {
16250 /* Enable manual control with low off / high off. */
16251 if (eep_config.termination == 1) {
16252 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016254 /* Enable manual control with low off / high on. */
16255 } else if (eep_config.termination == 2) {
16256 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016257
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016258 /* Enable manual control with low on / high on. */
16259 } else if (eep_config.termination == 3) {
16260 asc_dvc->cfg->termination =
16261 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
16262 } else {
16263 /*
16264 * The EEPROM 'termination' field contains a bad value. Use
16265 * automatic termination instead.
16266 */
16267 asc_dvc->cfg->termination = 0;
16268 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16269 }
16270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016271
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016272 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016273}
16274
16275/*
16276 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
16277 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
16278 * all of this is done.
16279 *
16280 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
16281 *
16282 * For a non-fatal error return a warning code. If there are no warnings
16283 * then 0 is returned.
16284 *
16285 * Note: Chip is stopped on entry.
16286 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016287static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016288{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016289 AdvPortAddr iop_base;
16290 ushort warn_code;
16291 ADVEEP_38C0800_CONFIG eep_config;
16292 int i;
16293 uchar tid, termination;
16294 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016295
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016296 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016298 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016299
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016300 /*
16301 * Read the board's EEPROM configuration.
16302 *
16303 * Set default values if a bad checksum is found.
16304 */
16305 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
16306 eep_config.check_sum) {
16307 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016308
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016309 /*
16310 * Set EEPROM default values.
16311 */
16312 for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) {
16313 *((uchar *)&eep_config + i) =
16314 *((uchar *)&Default_38C0800_EEPROM_Config + i);
16315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016316
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016317 /*
16318 * Assume the 6 byte board serial number that was read
16319 * from EEPROM is correct even if the EEPROM checksum
16320 * failed.
16321 */
16322 eep_config.serial_number_word3 =
16323 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016324
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016325 eep_config.serial_number_word2 =
16326 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016328 eep_config.serial_number_word1 =
16329 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016330
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016331 AdvSet38C0800EEPConfig(iop_base, &eep_config);
16332 }
16333 /*
16334 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
16335 * EEPROM configuration that was read.
16336 *
16337 * This is the mapping of EEPROM fields to Adv Library fields.
16338 */
16339 asc_dvc->wdtr_able = eep_config.wdtr_able;
16340 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
16341 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
16342 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
16343 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
16344 asc_dvc->tagqng_able = eep_config.tagqng_able;
16345 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
16346 asc_dvc->max_host_qng = eep_config.max_host_qng;
16347 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16348 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
16349 asc_dvc->start_motor = eep_config.start_motor;
16350 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
16351 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
16352 asc_dvc->no_scam = eep_config.scam_tolerant;
16353 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
16354 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
16355 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016356
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016357 /*
16358 * For every Target ID if any of its 'sdtr_speed[1234]' bits
16359 * are set, then set an 'sdtr_able' bit for it.
16360 */
16361 asc_dvc->sdtr_able = 0;
16362 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
16363 if (tid == 0) {
16364 sdtr_speed = asc_dvc->sdtr_speed1;
16365 } else if (tid == 4) {
16366 sdtr_speed = asc_dvc->sdtr_speed2;
16367 } else if (tid == 8) {
16368 sdtr_speed = asc_dvc->sdtr_speed3;
16369 } else if (tid == 12) {
16370 sdtr_speed = asc_dvc->sdtr_speed4;
16371 }
16372 if (sdtr_speed & ADV_MAX_TID) {
16373 asc_dvc->sdtr_able |= (1 << tid);
16374 }
16375 sdtr_speed >>= 4;
16376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016377
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016378 /*
16379 * Set the host maximum queuing (max. 253, min. 16) and the per device
16380 * maximum queuing (max. 63, min. 4).
16381 */
16382 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
16383 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16384 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
16385 /* If the value is zero, assume it is uninitialized. */
16386 if (eep_config.max_host_qng == 0) {
16387 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16388 } else {
16389 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
16390 }
16391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016392
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016393 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
16394 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16395 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
16396 /* If the value is zero, assume it is uninitialized. */
16397 if (eep_config.max_dvc_qng == 0) {
16398 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16399 } else {
16400 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
16401 }
16402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016403
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016404 /*
16405 * If 'max_dvc_qng' is greater than 'max_host_qng', then
16406 * set 'max_dvc_qng' to 'max_host_qng'.
16407 */
16408 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
16409 eep_config.max_dvc_qng = eep_config.max_host_qng;
16410 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016411
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016412 /*
16413 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
16414 * values based on possibly adjusted EEPROM values.
16415 */
16416 asc_dvc->max_host_qng = eep_config.max_host_qng;
16417 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016418
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016419 /*
16420 * If the EEPROM 'termination' field is set to automatic (0), then set
16421 * the ADV_DVC_CFG 'termination' field to automatic also.
16422 *
16423 * If the termination is specified with a non-zero 'termination'
16424 * value check that a legal value is set and set the ADV_DVC_CFG
16425 * 'termination' field appropriately.
16426 */
16427 if (eep_config.termination_se == 0) {
16428 termination = 0; /* auto termination for SE */
16429 } else {
16430 /* Enable manual control with low off / high off. */
16431 if (eep_config.termination_se == 1) {
16432 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016433
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016434 /* Enable manual control with low off / high on. */
16435 } else if (eep_config.termination_se == 2) {
16436 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016437
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016438 /* Enable manual control with low on / high on. */
16439 } else if (eep_config.termination_se == 3) {
16440 termination = TERM_SE;
16441 } else {
16442 /*
16443 * The EEPROM 'termination_se' field contains a bad value.
16444 * Use automatic termination instead.
16445 */
16446 termination = 0;
16447 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16448 }
16449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016450
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016451 if (eep_config.termination_lvd == 0) {
16452 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
16453 } else {
16454 /* Enable manual control with low off / high off. */
16455 if (eep_config.termination_lvd == 1) {
16456 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016457
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016458 /* Enable manual control with low off / high on. */
16459 } else if (eep_config.termination_lvd == 2) {
16460 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016461
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016462 /* Enable manual control with low on / high on. */
16463 } else if (eep_config.termination_lvd == 3) {
16464 asc_dvc->cfg->termination = termination | TERM_LVD;
16465 } else {
16466 /*
16467 * The EEPROM 'termination_lvd' field contains a bad value.
16468 * Use automatic termination instead.
16469 */
16470 asc_dvc->cfg->termination = termination;
16471 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16472 }
16473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016474
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016475 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016476}
16477
16478/*
16479 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
16480 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
16481 * all of this is done.
16482 *
16483 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
16484 *
16485 * For a non-fatal error return a warning code. If there are no warnings
16486 * then 0 is returned.
16487 *
16488 * Note: Chip is stopped on entry.
16489 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016490static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016491{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016492 AdvPortAddr iop_base;
16493 ushort warn_code;
16494 ADVEEP_38C1600_CONFIG eep_config;
16495 int i;
16496 uchar tid, termination;
16497 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016498
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016499 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016500
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016501 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016502
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016503 /*
16504 * Read the board's EEPROM configuration.
16505 *
16506 * Set default values if a bad checksum is found.
16507 */
16508 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
16509 eep_config.check_sum) {
16510 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016511
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016512 /*
16513 * Set EEPROM default values.
16514 */
16515 for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) {
16516 if (i == 1
16517 && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) !=
16518 0) {
16519 /*
16520 * Set Function 1 EEPROM Word 0 MSB
16521 *
16522 * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11)
16523 * EEPROM bits.
16524 *
16525 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and
16526 * old Mac system booting problem. The Expansion ROM must
16527 * be disabled in Function 1 for these systems.
16528 *
16529 */
16530 *((uchar *)&eep_config + i) =
16531 ((*
16532 ((uchar *)&Default_38C1600_EEPROM_Config
16533 +
16534 i)) &
16535 (~
16536 (((ADV_EEPROM_BIOS_ENABLE |
16537 ADV_EEPROM_INTAB) >> 8) & 0xFF)));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016538
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016539 /*
16540 * Set the INTAB (bit 11) if the GPIO 0 input indicates
16541 * the Function 1 interrupt line is wired to INTA.
16542 *
16543 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
16544 * 1 - Function 1 interrupt line wired to INT A.
16545 * 0 - Function 1 interrupt line wired to INT B.
16546 *
16547 * Note: Adapter boards always have Function 0 wired to INTA.
16548 * Put all 5 GPIO bits in input mode and then read
16549 * their input values.
16550 */
16551 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL,
16552 0);
16553 if (AdvReadByteRegister
16554 (iop_base, IOPB_GPIO_DATA) & 0x01) {
16555 /* Function 1 interrupt wired to INTA; Set EEPROM bit. */
16556 *((uchar *)&eep_config + i) |=
16557 ((ADV_EEPROM_INTAB >> 8) & 0xFF);
16558 }
16559 } else {
16560 *((uchar *)&eep_config + i) =
16561 *((uchar *)&Default_38C1600_EEPROM_Config
16562 + i);
16563 }
16564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016565
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016566 /*
16567 * Assume the 6 byte board serial number that was read
16568 * from EEPROM is correct even if the EEPROM checksum
16569 * failed.
16570 */
16571 eep_config.serial_number_word3 =
16572 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016573
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016574 eep_config.serial_number_word2 =
16575 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016576
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016577 eep_config.serial_number_word1 =
16578 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016579
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016580 AdvSet38C1600EEPConfig(iop_base, &eep_config);
16581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016582
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016583 /*
16584 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
16585 * EEPROM configuration that was read.
16586 *
16587 * This is the mapping of EEPROM fields to Adv Library fields.
16588 */
16589 asc_dvc->wdtr_able = eep_config.wdtr_able;
16590 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
16591 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
16592 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
16593 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
16594 asc_dvc->ppr_able = 0;
16595 asc_dvc->tagqng_able = eep_config.tagqng_able;
16596 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
16597 asc_dvc->max_host_qng = eep_config.max_host_qng;
16598 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16599 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
16600 asc_dvc->start_motor = eep_config.start_motor;
16601 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
16602 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
16603 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016604
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016605 /*
16606 * For every Target ID if any of its 'sdtr_speed[1234]' bits
16607 * are set, then set an 'sdtr_able' bit for it.
16608 */
16609 asc_dvc->sdtr_able = 0;
16610 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
16611 if (tid == 0) {
16612 sdtr_speed = asc_dvc->sdtr_speed1;
16613 } else if (tid == 4) {
16614 sdtr_speed = asc_dvc->sdtr_speed2;
16615 } else if (tid == 8) {
16616 sdtr_speed = asc_dvc->sdtr_speed3;
16617 } else if (tid == 12) {
16618 sdtr_speed = asc_dvc->sdtr_speed4;
16619 }
16620 if (sdtr_speed & ASC_MAX_TID) {
16621 asc_dvc->sdtr_able |= (1 << tid);
16622 }
16623 sdtr_speed >>= 4;
16624 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016625
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016626 /*
16627 * Set the host maximum queuing (max. 253, min. 16) and the per device
16628 * maximum queuing (max. 63, min. 4).
16629 */
16630 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
16631 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16632 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
16633 /* If the value is zero, assume it is uninitialized. */
16634 if (eep_config.max_host_qng == 0) {
16635 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16636 } else {
16637 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
16638 }
16639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016641 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
16642 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16643 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
16644 /* If the value is zero, assume it is uninitialized. */
16645 if (eep_config.max_dvc_qng == 0) {
16646 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16647 } else {
16648 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
16649 }
16650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016651
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016652 /*
16653 * If 'max_dvc_qng' is greater than 'max_host_qng', then
16654 * set 'max_dvc_qng' to 'max_host_qng'.
16655 */
16656 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
16657 eep_config.max_dvc_qng = eep_config.max_host_qng;
16658 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016659
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016660 /*
16661 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
16662 * values based on possibly adjusted EEPROM values.
16663 */
16664 asc_dvc->max_host_qng = eep_config.max_host_qng;
16665 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016666
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016667 /*
16668 * If the EEPROM 'termination' field is set to automatic (0), then set
16669 * the ASC_DVC_CFG 'termination' field to automatic also.
16670 *
16671 * If the termination is specified with a non-zero 'termination'
16672 * value check that a legal value is set and set the ASC_DVC_CFG
16673 * 'termination' field appropriately.
16674 */
16675 if (eep_config.termination_se == 0) {
16676 termination = 0; /* auto termination for SE */
16677 } else {
16678 /* Enable manual control with low off / high off. */
16679 if (eep_config.termination_se == 1) {
16680 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016681
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016682 /* Enable manual control with low off / high on. */
16683 } else if (eep_config.termination_se == 2) {
16684 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016685
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016686 /* Enable manual control with low on / high on. */
16687 } else if (eep_config.termination_se == 3) {
16688 termination = TERM_SE;
16689 } else {
16690 /*
16691 * The EEPROM 'termination_se' field contains a bad value.
16692 * Use automatic termination instead.
16693 */
16694 termination = 0;
16695 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16696 }
16697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016698
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016699 if (eep_config.termination_lvd == 0) {
16700 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
16701 } else {
16702 /* Enable manual control with low off / high off. */
16703 if (eep_config.termination_lvd == 1) {
16704 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016705
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016706 /* Enable manual control with low off / high on. */
16707 } else if (eep_config.termination_lvd == 2) {
16708 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016709
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016710 /* Enable manual control with low on / high on. */
16711 } else if (eep_config.termination_lvd == 3) {
16712 asc_dvc->cfg->termination = termination | TERM_LVD;
16713 } else {
16714 /*
16715 * The EEPROM 'termination_lvd' field contains a bad value.
16716 * Use automatic termination instead.
16717 */
16718 asc_dvc->cfg->termination = termination;
16719 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16720 }
16721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016722
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016723 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016724}
16725
16726/*
16727 * Read EEPROM configuration into the specified buffer.
16728 *
16729 * Return a checksum based on the EEPROM configuration read.
16730 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016731static ushort __init
Linus Torvalds1da177e2005-04-16 15:20:36 -070016732AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
16733{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016734 ushort wval, chksum;
16735 ushort *wbuf;
16736 int eep_addr;
16737 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016738
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016739 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
16740 wbuf = (ushort *)cfg_buf;
16741 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016742
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016743 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16744 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16745 wval = AdvReadEEPWord(iop_base, eep_addr);
16746 chksum += wval; /* Checksum is calculated from word values. */
16747 if (*charfields++) {
16748 *wbuf = le16_to_cpu(wval);
16749 } else {
16750 *wbuf = wval;
16751 }
16752 }
16753 /* Read checksum word. */
16754 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16755 wbuf++;
16756 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016758 /* Read rest of EEPROM not covered by the checksum. */
16759 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16760 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16761 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16762 if (*charfields++) {
16763 *wbuf = le16_to_cpu(*wbuf);
16764 }
16765 }
16766 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016767}
16768
16769/*
16770 * Read EEPROM configuration into the specified buffer.
16771 *
16772 * Return a checksum based on the EEPROM configuration read.
16773 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016774static ushort __init
16775AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016776{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016777 ushort wval, chksum;
16778 ushort *wbuf;
16779 int eep_addr;
16780 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016781
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016782 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
16783 wbuf = (ushort *)cfg_buf;
16784 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016785
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016786 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16787 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16788 wval = AdvReadEEPWord(iop_base, eep_addr);
16789 chksum += wval; /* Checksum is calculated from word values. */
16790 if (*charfields++) {
16791 *wbuf = le16_to_cpu(wval);
16792 } else {
16793 *wbuf = wval;
16794 }
16795 }
16796 /* Read checksum word. */
16797 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16798 wbuf++;
16799 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016800
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016801 /* Read rest of EEPROM not covered by the checksum. */
16802 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16803 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16804 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16805 if (*charfields++) {
16806 *wbuf = le16_to_cpu(*wbuf);
16807 }
16808 }
16809 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016810}
16811
16812/*
16813 * Read EEPROM configuration into the specified buffer.
16814 *
16815 * Return a checksum based on the EEPROM configuration read.
16816 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016817static ushort __init
16818AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016819{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016820 ushort wval, chksum;
16821 ushort *wbuf;
16822 int eep_addr;
16823 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016824
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016825 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
16826 wbuf = (ushort *)cfg_buf;
16827 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016828
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016829 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16830 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16831 wval = AdvReadEEPWord(iop_base, eep_addr);
16832 chksum += wval; /* Checksum is calculated from word values. */
16833 if (*charfields++) {
16834 *wbuf = le16_to_cpu(wval);
16835 } else {
16836 *wbuf = wval;
16837 }
16838 }
16839 /* Read checksum word. */
16840 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16841 wbuf++;
16842 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016843
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016844 /* Read rest of EEPROM not covered by the checksum. */
16845 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16846 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16847 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16848 if (*charfields++) {
16849 *wbuf = le16_to_cpu(*wbuf);
16850 }
16851 }
16852 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016853}
16854
16855/*
16856 * Read the EEPROM from specified location
16857 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016858static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016859{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016860 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16861 ASC_EEP_CMD_READ | eep_word_addr);
16862 AdvWaitEEPCmd(iop_base);
16863 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016864}
16865
16866/*
16867 * Wait for EEPROM command to complete
16868 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016869static void __init AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016870{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016871 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016872
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016873 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
16874 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
16875 ASC_EEP_CMD_DONE) {
16876 break;
16877 }
16878 DvcSleepMilliSecond(1);
16879 }
16880 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
16881 0) {
16882 ASC_ASSERT(0);
16883 }
16884 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016885}
16886
16887/*
16888 * Write the EEPROM from 'cfg_buf'.
16889 */
Randy Dunlapc8360432006-06-25 05:48:40 -070016890void __init
Linus Torvalds1da177e2005-04-16 15:20:36 -070016891AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
16892{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016893 ushort *wbuf;
16894 ushort addr, chksum;
16895 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016897 wbuf = (ushort *)cfg_buf;
16898 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
16899 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016900
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016901 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16902 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016903
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016904 /*
16905 * Write EEPROM from word 0 to word 20.
16906 */
16907 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16908 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16909 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016910
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016911 if (*charfields++) {
16912 word = cpu_to_le16(*wbuf);
16913 } else {
16914 word = *wbuf;
16915 }
16916 chksum += *wbuf; /* Checksum is calculated from word values. */
16917 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16918 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16919 ASC_EEP_CMD_WRITE | addr);
16920 AdvWaitEEPCmd(iop_base);
16921 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16922 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016923
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016924 /*
16925 * Write EEPROM checksum at word 21.
16926 */
16927 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16928 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16929 AdvWaitEEPCmd(iop_base);
16930 wbuf++;
16931 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016932
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016933 /*
16934 * Write EEPROM OEM name at words 22 to 29.
16935 */
16936 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16937 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16938 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016940 if (*charfields++) {
16941 word = cpu_to_le16(*wbuf);
16942 } else {
16943 word = *wbuf;
16944 }
16945 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16946 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16947 ASC_EEP_CMD_WRITE | addr);
16948 AdvWaitEEPCmd(iop_base);
16949 }
16950 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16951 AdvWaitEEPCmd(iop_base);
16952 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016953}
16954
16955/*
16956 * Write the EEPROM from 'cfg_buf'.
16957 */
Randy Dunlapc8360432006-06-25 05:48:40 -070016958void __init
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016959AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016960{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016961 ushort *wbuf;
16962 ushort *charfields;
16963 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016964
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016965 wbuf = (ushort *)cfg_buf;
16966 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
16967 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016968
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016969 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16970 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016971
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016972 /*
16973 * Write EEPROM from word 0 to word 20.
16974 */
16975 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16976 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16977 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016978
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016979 if (*charfields++) {
16980 word = cpu_to_le16(*wbuf);
16981 } else {
16982 word = *wbuf;
16983 }
16984 chksum += *wbuf; /* Checksum is calculated from word values. */
16985 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16986 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16987 ASC_EEP_CMD_WRITE | addr);
16988 AdvWaitEEPCmd(iop_base);
16989 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016991
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016992 /*
16993 * Write EEPROM checksum at word 21.
16994 */
16995 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16996 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16997 AdvWaitEEPCmd(iop_base);
16998 wbuf++;
16999 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017000
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017001 /*
17002 * Write EEPROM OEM name at words 22 to 29.
17003 */
17004 for (addr = ADV_EEP_DVC_CTL_BEGIN;
17005 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
17006 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017007
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017008 if (*charfields++) {
17009 word = cpu_to_le16(*wbuf);
17010 } else {
17011 word = *wbuf;
17012 }
17013 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
17014 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
17015 ASC_EEP_CMD_WRITE | addr);
17016 AdvWaitEEPCmd(iop_base);
17017 }
17018 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
17019 AdvWaitEEPCmd(iop_base);
17020 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017021}
17022
17023/*
17024 * Write the EEPROM from 'cfg_buf'.
17025 */
Randy Dunlapc8360432006-06-25 05:48:40 -070017026void __init
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017027AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017028{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017029 ushort *wbuf;
17030 ushort *charfields;
17031 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017032
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017033 wbuf = (ushort *)cfg_buf;
17034 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
17035 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017036
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017037 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
17038 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017039
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017040 /*
17041 * Write EEPROM from word 0 to word 20.
17042 */
17043 for (addr = ADV_EEP_DVC_CFG_BEGIN;
17044 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
17045 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017046
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017047 if (*charfields++) {
17048 word = cpu_to_le16(*wbuf);
17049 } else {
17050 word = *wbuf;
17051 }
17052 chksum += *wbuf; /* Checksum is calculated from word values. */
17053 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
17054 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
17055 ASC_EEP_CMD_WRITE | addr);
17056 AdvWaitEEPCmd(iop_base);
17057 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
17058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017059
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017060 /*
17061 * Write EEPROM checksum at word 21.
17062 */
17063 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
17064 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17065 AdvWaitEEPCmd(iop_base);
17066 wbuf++;
17067 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017068
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017069 /*
17070 * Write EEPROM OEM name at words 22 to 29.
17071 */
17072 for (addr = ADV_EEP_DVC_CTL_BEGIN;
17073 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
17074 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017075
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017076 if (*charfields++) {
17077 word = cpu_to_le16(*wbuf);
17078 } else {
17079 word = *wbuf;
17080 }
17081 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
17082 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
17083 ASC_EEP_CMD_WRITE | addr);
17084 AdvWaitEEPCmd(iop_base);
17085 }
17086 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
17087 AdvWaitEEPCmd(iop_base);
17088 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017089}
17090
17091/* a_advlib.c */
17092/*
17093 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
17094 *
17095 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
17096 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
17097 * RISC to notify it a new command is ready to be executed.
17098 *
17099 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
17100 * set to SCSI_MAX_RETRY.
17101 *
17102 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
17103 * for DMA addresses or math operations are byte swapped to little-endian
17104 * order.
17105 *
17106 * Return:
17107 * ADV_SUCCESS(1) - The request was successfully queued.
17108 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
17109 * request completes.
17110 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
17111 * host IC error.
17112 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017113static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017114{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017115 ulong last_int_level;
17116 AdvPortAddr iop_base;
17117 ADV_DCNT req_size;
17118 ADV_PADDR req_paddr;
17119 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017120
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017121 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017122
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017123 /*
17124 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
17125 */
17126 if (scsiq->target_id > ADV_MAX_TID) {
17127 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
17128 scsiq->done_status = QD_WITH_ERROR;
17129 return ADV_ERROR;
17130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017131
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017132 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017133
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017134 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070017135
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017136 /*
17137 * Allocate a carrier ensuring at least one carrier always
17138 * remains on the freelist and initialize fields.
17139 */
17140 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
17141 DvcLeaveCritical(last_int_level);
17142 return ADV_BUSY;
17143 }
17144 asc_dvc->carr_freelist = (ADV_CARR_T *)
17145 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
17146 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017147
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017148 /*
17149 * Set the carrier to be a stopper by setting 'next_vpa'
17150 * to the stopper value. The current stopper will be changed
17151 * below to point to the new stopper.
17152 */
17153 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017154
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017155 /*
17156 * Clear the ADV_SCSI_REQ_Q done flag.
17157 */
17158 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017159
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017160 req_size = sizeof(ADV_SCSI_REQ_Q);
17161 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
17162 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017163
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017164 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
17165 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070017166
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017167 /* Wait for assertion before making little-endian */
17168 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017169
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017170 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
17171 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
17172 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017173
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017174 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
17175 /*
17176 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
17177 * order during initialization.
17178 */
17179 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017180
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017181 /*
17182 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
17183 * the microcode. The newly allocated stopper will become the new
17184 * stopper.
17185 */
17186 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017187
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017188 /*
17189 * Set the 'next_vpa' pointer for the old stopper to be the
17190 * physical address of the new stopper. The RISC can only
17191 * follow physical addresses.
17192 */
17193 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017194
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017195 /*
17196 * Set the host adapter stopper pointer to point to the new carrier.
17197 */
17198 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017200 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
17201 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
17202 /*
17203 * Tickle the RISC to tell it to read its Command Queue Head pointer.
17204 */
17205 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
17206 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
17207 /*
17208 * Clear the tickle value. In the ASC-3550 the RISC flag
17209 * command 'clr_tickle_a' does not work unless the host
17210 * value is cleared.
17211 */
17212 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
17213 ADV_TICKLE_NOP);
17214 }
17215 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
17216 /*
17217 * Notify the RISC a carrier is ready by writing the physical
17218 * address of the new carrier stopper to the COMMA register.
17219 */
17220 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
17221 le32_to_cpu(new_carrp->carr_pa));
17222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017223
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017224 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017225
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017226 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017227}
17228
17229/*
17230 * Reset SCSI Bus and purge all outstanding requests.
17231 *
17232 * Return Value:
17233 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
17234 * ADV_FALSE(0) - Microcode command failed.
17235 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
17236 * may be hung which requires driver recovery.
17237 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017238static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017239{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017240 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017241
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017242 /*
17243 * Send the SCSI Bus Reset idle start idle command which asserts
17244 * the SCSI Bus Reset signal.
17245 */
17246 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
17247 if (status != ADV_TRUE) {
17248 return status;
17249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017250
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017251 /*
17252 * Delay for the specified SCSI Bus Reset hold time.
17253 *
17254 * The hold time delay is done on the host because the RISC has no
17255 * microsecond accurate timer.
17256 */
17257 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017258
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017259 /*
17260 * Send the SCSI Bus Reset end idle command which de-asserts
17261 * the SCSI Bus Reset signal and purges any pending requests.
17262 */
17263 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
17264 if (status != ADV_TRUE) {
17265 return status;
17266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017267
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017268 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017269
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017270 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017271}
17272
17273/*
17274 * Reset chip and SCSI Bus.
17275 *
17276 * Return Value:
17277 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
17278 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
17279 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017280static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017281{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017282 int status;
17283 ushort wdtr_able, sdtr_able, tagqng_able;
17284 ushort ppr_able = 0;
17285 uchar tid, max_cmd[ADV_MAX_TID + 1];
17286 AdvPortAddr iop_base;
17287 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017288
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017289 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017290
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017291 /*
17292 * Save current per TID negotiated values.
17293 */
17294 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
17295 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
17296 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
17297 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
17298 }
17299 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
17300 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
17301 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
17302 max_cmd[tid]);
17303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017304
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017305 /*
17306 * Force the AdvInitAsc3550/38C0800Driver() function to
17307 * perform a SCSI Bus Reset by clearing the BIOS signature word.
17308 * The initialization functions assumes a SCSI Bus Reset is not
17309 * needed if the BIOS signature word is present.
17310 */
17311 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
17312 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017313
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017314 /*
17315 * Stop chip and reset it.
17316 */
17317 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
17318 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
17319 DvcSleepMilliSecond(100);
17320 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
17321 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017322
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017323 /*
17324 * Reset Adv Library error code, if any, and try
17325 * re-initializing the chip.
17326 */
17327 asc_dvc->err_code = 0;
17328 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
17329 status = AdvInitAsc38C1600Driver(asc_dvc);
17330 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
17331 status = AdvInitAsc38C0800Driver(asc_dvc);
17332 } else {
17333 status = AdvInitAsc3550Driver(asc_dvc);
17334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017335
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017336 /* Translate initialization return value to status value. */
17337 if (status == 0) {
17338 status = ADV_TRUE;
17339 } else {
17340 status = ADV_FALSE;
17341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017342
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017343 /*
17344 * Restore the BIOS signature word.
17345 */
17346 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017347
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017348 /*
17349 * Restore per TID negotiated values.
17350 */
17351 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
17352 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
17353 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
17354 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
17355 }
17356 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
17357 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
17358 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
17359 max_cmd[tid]);
17360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017362 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017363}
17364
17365/*
17366 * Adv Library Interrupt Service Routine
17367 *
17368 * This function is called by a driver's interrupt service routine.
17369 * The function disables and re-enables interrupts.
17370 *
17371 * When a microcode idle command is completed, the ADV_DVC_VAR
17372 * 'idle_cmd_done' field is set to ADV_TRUE.
17373 *
17374 * Note: AdvISR() can be called when interrupts are disabled or even
17375 * when there is no hardware interrupt condition present. It will
17376 * always check for completed idle commands and microcode requests.
17377 * This is an important feature that shouldn't be changed because it
17378 * allows commands to be completed from polling mode loops.
17379 *
17380 * Return:
17381 * ADV_TRUE(1) - interrupt was pending
17382 * ADV_FALSE(0) - no interrupt was pending
17383 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017384static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017385{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017386 AdvPortAddr iop_base;
17387 uchar int_stat;
17388 ushort target_bit;
17389 ADV_CARR_T *free_carrp;
17390 ADV_VADDR irq_next_vpa;
17391 int flags;
17392 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017393
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017394 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070017395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017396 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017397
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017398 /* Reading the register clears the interrupt. */
17399 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017400
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017401 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
17402 ADV_INTR_STATUS_INTRC)) == 0) {
17403 DvcLeaveCritical(flags);
17404 return ADV_FALSE;
17405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017406
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017407 /*
17408 * Notify the driver of an asynchronous microcode condition by
17409 * calling the ADV_DVC_VAR.async_callback function. The function
17410 * is passed the microcode ASC_MC_INTRB_CODE byte value.
17411 */
17412 if (int_stat & ADV_INTR_STATUS_INTRB) {
17413 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017414
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017415 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017416
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017417 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
17418 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
17419 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
17420 asc_dvc->carr_pending_cnt != 0) {
17421 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
17422 ADV_TICKLE_A);
17423 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
17424 AdvWriteByteRegister(iop_base,
17425 IOPB_TICKLE,
17426 ADV_TICKLE_NOP);
17427 }
17428 }
17429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017430
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017431 if (asc_dvc->async_callback != 0) {
17432 (*asc_dvc->async_callback) (asc_dvc, intrb_code);
17433 }
17434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017435
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017436 /*
17437 * Check if the IRQ stopper carrier contains a completed request.
17438 */
17439 while (((irq_next_vpa =
17440 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
17441 /*
17442 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
17443 * The RISC will have set 'areq_vpa' to a virtual address.
17444 *
17445 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
17446 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
17447 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
17448 * in AdvExeScsiQueue().
17449 */
17450 scsiq = (ADV_SCSI_REQ_Q *)
17451 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070017452
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017453 /*
17454 * Request finished with good status and the queue was not
17455 * DMAed to host memory by the firmware. Set all status fields
17456 * to indicate good status.
17457 */
17458 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
17459 scsiq->done_status = QD_NO_ERROR;
17460 scsiq->host_status = scsiq->scsi_status = 0;
17461 scsiq->data_cnt = 0L;
17462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017463
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017464 /*
17465 * Advance the stopper pointer to the next carrier
17466 * ignoring the lower four bits. Free the previous
17467 * stopper carrier.
17468 */
17469 free_carrp = asc_dvc->irq_sp;
17470 asc_dvc->irq_sp = (ADV_CARR_T *)
17471 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070017472
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017473 free_carrp->next_vpa =
17474 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
17475 asc_dvc->carr_freelist = free_carrp;
17476 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017477
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017478 ASC_ASSERT(scsiq != NULL);
17479 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017480
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017481 /*
17482 * Clear request microcode control flag.
17483 */
17484 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017485
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017486 /*
17487 * If the command that completed was a SCSI INQUIRY and
17488 * LUN 0 was sent the command, then process the INQUIRY
17489 * command information for the device.
17490 *
17491 * Note: If data returned were either VPD or CmdDt data,
17492 * don't process the INQUIRY command information for
17493 * the device, otherwise may erroneously set *_able bits.
17494 */
17495 if (scsiq->done_status == QD_NO_ERROR &&
17496 scsiq->cdb[0] == INQUIRY &&
17497 scsiq->target_lun == 0 &&
17498 (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT)
17499 == ADV_INQ_RTN_STD_INQUIRY_DATA) {
17500 AdvInquiryHandling(asc_dvc, scsiq);
17501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017502
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017503 /*
17504 * Notify the driver of the completed request by passing
17505 * the ADV_SCSI_REQ_Q pointer to its callback function.
17506 */
17507 scsiq->a_flag |= ADV_SCSIQ_DONE;
17508 (*asc_dvc->isr_callback) (asc_dvc, scsiq);
17509 /*
17510 * Note: After the driver callback function is called, 'scsiq'
17511 * can no longer be referenced.
17512 *
17513 * Fall through and continue processing other completed
17514 * requests...
17515 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017516
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017517 /*
17518 * Disable interrupts again in case the driver inadvertently
17519 * enabled interrupts in its callback function.
17520 *
17521 * The DvcEnterCritical() return value is ignored, because
17522 * the 'flags' saved when AdvISR() was first entered will be
17523 * used to restore the interrupt flag on exit.
17524 */
17525 (void)DvcEnterCritical();
17526 }
17527 DvcLeaveCritical(flags);
17528 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017529}
17530
17531/*
17532 * Send an idle command to the chip and wait for completion.
17533 *
17534 * Command completion is polled for once per microsecond.
17535 *
17536 * The function can be called from anywhere including an interrupt handler.
17537 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
17538 * functions to prevent reentrancy.
17539 *
17540 * Return Values:
17541 * ADV_TRUE - command completed successfully
17542 * ADV_FALSE - command failed
17543 * ADV_ERROR - command timed out
17544 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017545static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070017546AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017547 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017548{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017549 ulong last_int_level;
17550 int result;
17551 ADV_DCNT i, j;
17552 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017553
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017554 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070017555
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017556 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017557
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017558 /*
17559 * Clear the idle command status which is set by the microcode
17560 * to a non-zero value to indicate when the command is completed.
17561 * The non-zero result is one of the IDLE_CMD_STATUS_* values
17562 * defined in a_advlib.h.
17563 */
17564 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017565
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017566 /*
17567 * Write the idle command value after the idle command parameter
17568 * has been written to avoid a race condition. If the order is not
17569 * followed, the microcode may process the idle command before the
17570 * parameters have been written to LRAM.
17571 */
17572 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
17573 cpu_to_le32(idle_cmd_parameter));
17574 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017575
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017576 /*
17577 * Tickle the RISC to tell it to process the idle command.
17578 */
17579 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
17580 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
17581 /*
17582 * Clear the tickle value. In the ASC-3550 the RISC flag
17583 * command 'clr_tickle_b' does not work unless the host
17584 * value is cleared.
17585 */
17586 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
17587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017588
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017589 /* Wait for up to 100 millisecond for the idle command to timeout. */
17590 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
17591 /* Poll once each microsecond for command completion. */
17592 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
17593 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
17594 result);
17595 if (result != 0) {
17596 DvcLeaveCritical(last_int_level);
17597 return result;
17598 }
17599 DvcDelayMicroSecond(asc_dvc, (ushort)1);
17600 }
17601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017602
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017603 ASC_ASSERT(0); /* The idle command should never timeout. */
17604 DvcLeaveCritical(last_int_level);
17605 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017606}
17607
17608/*
17609 * Inquiry Information Byte 7 Handling
17610 *
17611 * Handle SCSI Inquiry Command information for a device by setting
17612 * microcode operating variables that affect WDTR, SDTR, and Tag
17613 * Queuing.
17614 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017615static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017616{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017617 AdvPortAddr iop_base;
17618 uchar tid;
17619 ADV_SCSI_INQUIRY *inq;
17620 ushort tidmask;
17621 ushort cfg_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017622
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017623 /*
17624 * AdvInquiryHandling() requires up to INQUIRY information Byte 7
17625 * to be available.
17626 *
17627 * If less than 8 bytes of INQUIRY information were requested or less
17628 * than 8 bytes were transferred, then return. cdb[4] is the request
17629 * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
17630 * microcode to the transfer residual count.
17631 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017632
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017633 if (scsiq->cdb[4] < 8 ||
17634 (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) {
17635 return;
17636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017637
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017638 iop_base = asc_dvc->iop_base;
17639 tid = scsiq->target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017641 inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017642
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017643 /*
17644 * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
17645 */
17646 if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) {
17647 return;
17648 } else {
17649 /*
17650 * INQUIRY Byte 7 Handling
17651 *
17652 * Use a device's INQUIRY byte 7 to determine whether it
17653 * supports WDTR, SDTR, and Tag Queuing. If the feature
17654 * is enabled in the EEPROM and the device supports the
17655 * feature, then enable it in the microcode.
17656 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017657
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017658 tidmask = ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017659
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017660 /*
17661 * Wide Transfers
17662 *
17663 * If the EEPROM enabled WDTR for the device and the device
17664 * supports wide bus (16 bit) transfers, then turn on the
17665 * device's 'wdtr_able' bit and write the new value to the
17666 * microcode.
17667 */
17668 if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) {
17669 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
17670 if ((cfg_word & tidmask) == 0) {
17671 cfg_word |= tidmask;
17672 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
17673 cfg_word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017674
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017675 /*
17676 * Clear the microcode "SDTR negotiation" and "WDTR
17677 * negotiation" done indicators for the target to cause
17678 * it to negotiate with the new setting set above.
17679 * WDTR when accepted causes the target to enter
17680 * asynchronous mode, so SDTR must be negotiated.
17681 */
17682 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE,
17683 cfg_word);
17684 cfg_word &= ~tidmask;
17685 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE,
17686 cfg_word);
17687 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE,
17688 cfg_word);
17689 cfg_word &= ~tidmask;
17690 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE,
17691 cfg_word);
17692 }
17693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017694
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017695 /*
17696 * Synchronous Transfers
17697 *
17698 * If the EEPROM enabled SDTR for the device and the device
17699 * supports synchronous transfers, then turn on the device's
17700 * 'sdtr_able' bit. Write the new value to the microcode.
17701 */
17702 if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) {
17703 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
17704 if ((cfg_word & tidmask) == 0) {
17705 cfg_word |= tidmask;
17706 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
17707 cfg_word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017708
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017709 /*
17710 * Clear the microcode "SDTR negotiation" done indicator
17711 * for the target to cause it to negotiate with the new
17712 * setting set above.
17713 */
17714 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE,
17715 cfg_word);
17716 cfg_word &= ~tidmask;
17717 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE,
17718 cfg_word);
17719 }
17720 }
17721 /*
17722 * If the Inquiry data included enough space for the SPI-3
17723 * Clocking field, then check if DT mode is supported.
17724 */
17725 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 &&
17726 (scsiq->cdb[4] >= 57 ||
17727 (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) {
17728 /*
17729 * PPR (Parallel Protocol Request) Capable
17730 *
17731 * If the device supports DT mode, then it must be PPR capable.
17732 * The PPR message will be used in place of the SDTR and WDTR
17733 * messages to negotiate synchronous speed and offset, transfer
17734 * width, and protocol options.
17735 */
17736 if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) {
17737 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE,
17738 asc_dvc->ppr_able);
17739 asc_dvc->ppr_able |= tidmask;
17740 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE,
17741 asc_dvc->ppr_able);
17742 }
17743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017744
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017745 /*
17746 * If the EEPROM enabled Tag Queuing for the device and the
17747 * device supports Tag Queueing, then turn on the device's
17748 * 'tagqng_enable' bit in the microcode and set the microcode
17749 * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
17750 * value.
17751 *
17752 * Tag Queuing is disabled for the BIOS which runs in polled
17753 * mode and would see no benefit from Tag Queuing. Also by
17754 * disabling Tag Queuing in the BIOS devices with Tag Queuing
17755 * bugs will at least work with the BIOS.
17756 */
17757 if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) {
17758 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
17759 cfg_word |= tidmask;
17760 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
17761 cfg_word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017762
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017763 AdvWriteByteLram(iop_base,
17764 ASC_MC_NUMBER_OF_MAX_CMD + tid,
17765 asc_dvc->max_dvc_qng);
17766 }
17767 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017768}
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017769
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017770static struct Scsi_Host *__devinit
17771advansys_board_found(int iop, struct device *dev, int bus_type)
17772{
17773 struct Scsi_Host *shost;
17774 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
17775 asc_board_t *boardp;
17776 ASC_DVC_VAR *asc_dvc_varp = NULL;
17777 ADV_DVC_VAR *adv_dvc_varp = NULL;
17778 adv_sgblk_t *sgp = NULL;
17779 int share_irq = FALSE;
17780 int iolen = 0;
17781 ADV_PADDR pci_memory_address;
17782 int warn_code, err_code;
17783 int ret;
17784
17785 /*
17786 * Adapter found.
17787 *
17788 * Register the adapter, get its configuration, and
17789 * initialize it.
17790 */
17791 ASC_DBG(2, "advansys_board_found: scsi_register()\n");
17792 shost = scsi_register(&driver_template, sizeof(asc_board_t));
17793
17794 if (!shost)
17795 return NULL;
17796
17797 /* Save a pointer to the Scsi_Host of each board found. */
17798 asc_host[asc_board_count++] = shost;
17799
17800 /* Initialize private per board data */
17801 boardp = ASC_BOARDP(shost);
17802 memset(boardp, 0, sizeof(asc_board_t));
17803 boardp->id = asc_board_count - 1;
17804
17805 /* Initialize spinlock. */
17806 spin_lock_init(&boardp->lock);
17807
17808 /*
17809 * Handle both narrow and wide boards.
17810 *
17811 * If a Wide board was detected, set the board structure
17812 * wide board flag. Set-up the board structure based on
17813 * the board type.
17814 */
17815#ifdef CONFIG_PCI
17816 if (bus_type == ASC_IS_PCI &&
17817 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
17818 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
17819 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
17820 boardp->flags |= ASC_IS_WIDE_BOARD;
17821 }
17822#endif /* CONFIG_PCI */
17823
17824 if (ASC_NARROW_BOARD(boardp)) {
17825 ASC_DBG(1, "advansys_board_found: narrow board\n");
17826 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
17827 asc_dvc_varp->bus_type = bus_type;
17828 asc_dvc_varp->drv_ptr = boardp;
17829 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
17830 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
17831 asc_dvc_varp->iop_base = iop;
17832 asc_dvc_varp->isr_callback = asc_isr_callback;
17833 } else {
17834 ASC_DBG(1, "advansys_board_found: wide board\n");
17835 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
17836 adv_dvc_varp->drv_ptr = boardp;
17837 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
17838 adv_dvc_varp->isr_callback = adv_isr_callback;
17839 adv_dvc_varp->async_callback = adv_async_callback;
17840#ifdef CONFIG_PCI
17841 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
17842 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
17843 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
17844 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
17845 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
17846 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
17847 } else {
17848 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
17849 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
17850 }
17851#endif /* CONFIG_PCI */
17852
17853 /*
17854 * Map the board's registers into virtual memory for
17855 * PCI slave access. Only memory accesses are used to
17856 * access the board's registers.
17857 *
17858 * Note: The PCI register base address is not always
17859 * page aligned, but the address passed to ioremap()
17860 * must be page aligned. It is guaranteed that the
17861 * PCI register base address will not cross a page
17862 * boundary.
17863 */
17864 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
17865 iolen = ADV_3550_IOLEN;
17866 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
17867 iolen = ADV_38C0800_IOLEN;
17868 } else {
17869 iolen = ADV_38C1600_IOLEN;
17870 }
17871#ifdef CONFIG_PCI
17872 pci_memory_address = pci_resource_start(pdev, 1);
17873 ASC_DBG1(1,
17874 "advansys_board_found: pci_memory_address: 0x%lx\n",
17875 (ulong)pci_memory_address);
17876 if ((boardp->ioremap_addr =
17877 ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) {
17878 ASC_PRINT3
17879 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
17880 boardp->id, pci_memory_address, iolen);
17881 scsi_unregister(shost);
17882 asc_board_count--;
17883 return NULL;
17884 }
17885 ASC_DBG1(1,
17886 "advansys_board_found: ioremap_addr: 0x%lx\n",
17887 (ulong)boardp->ioremap_addr);
17888 adv_dvc_varp->iop_base = (AdvPortAddr)
17889 (boardp->ioremap_addr +
17890 (pci_memory_address - (pci_memory_address & PAGE_MASK)));
17891 ASC_DBG1(1,
17892 "advansys_board_found: iop_base: 0x%lx\n",
17893 adv_dvc_varp->iop_base);
17894#endif /* CONFIG_PCI */
17895
17896 /*
17897 * Even though it isn't used to access wide boards, other
17898 * than for the debug line below, save I/O Port address so
17899 * that it can be reported.
17900 */
17901 boardp->ioport = iop;
17902
17903 ASC_DBG2(1,
17904 "advansys_board_found: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
17905 (ushort)inp(iop + 1), (ushort)inpw(iop));
17906 }
17907
17908#ifdef CONFIG_PROC_FS
17909 /*
17910 * Allocate buffer for printing information from
17911 * /proc/scsi/advansys/[0...].
17912 */
17913 if ((boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
17914 ASC_PRINT3
17915 ("advansys_board_found: board %d: kmalloc(%d, %d) returned NULL\n",
17916 boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
17917 scsi_unregister(shost);
17918 asc_board_count--;
17919 return NULL;
17920 }
17921#endif /* CONFIG_PROC_FS */
17922
17923 if (ASC_NARROW_BOARD(boardp)) {
17924 asc_dvc_varp->cfg->dev = dev;
17925 /*
17926 * Set the board bus type and PCI IRQ before
17927 * calling AscInitGetConfig().
17928 */
17929 switch (asc_dvc_varp->bus_type) {
17930#ifdef CONFIG_ISA
17931 case ASC_IS_ISA:
17932 shost->unchecked_isa_dma = TRUE;
17933 share_irq = FALSE;
17934 break;
17935 case ASC_IS_VL:
17936 shost->unchecked_isa_dma = FALSE;
17937 share_irq = FALSE;
17938 break;
17939 case ASC_IS_EISA:
17940 shost->unchecked_isa_dma = FALSE;
17941 share_irq = TRUE;
17942 break;
17943#endif /* CONFIG_ISA */
17944#ifdef CONFIG_PCI
17945 case ASC_IS_PCI:
17946 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
17947 asc_dvc_varp->cfg->pci_slot_info =
17948 ASC_PCI_MKID(pdev->bus->number,
17949 PCI_SLOT(pdev->devfn),
17950 PCI_FUNC(pdev->devfn));
17951 shost->unchecked_isa_dma = FALSE;
17952 share_irq = TRUE;
17953 break;
17954#endif /* CONFIG_PCI */
17955 default:
17956 ASC_PRINT2
17957 ("advansys_board_found: board %d: unknown adapter type: %d\n",
17958 boardp->id, asc_dvc_varp->bus_type);
17959 shost->unchecked_isa_dma = TRUE;
17960 share_irq = FALSE;
17961 break;
17962 }
17963 } else {
17964 adv_dvc_varp->cfg->dev = dev;
17965 /*
17966 * For Wide boards set PCI information before calling
17967 * AdvInitGetConfig().
17968 */
17969#ifdef CONFIG_PCI
17970 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
17971 adv_dvc_varp->cfg->pci_slot_info =
17972 ASC_PCI_MKID(pdev->bus->number,
17973 PCI_SLOT(pdev->devfn),
17974 PCI_FUNC(pdev->devfn));
17975 shost->unchecked_isa_dma = FALSE;
17976 share_irq = TRUE;
17977#endif /* CONFIG_PCI */
17978 }
17979
17980 /*
17981 * Read the board configuration.
17982 */
17983 if (ASC_NARROW_BOARD(boardp)) {
17984 /*
17985 * NOTE: AscInitGetConfig() may change the board's
17986 * bus_type value. The bus_type value should no
17987 * longer be used. If the bus_type field must be
17988 * referenced only use the bit-wise AND operator "&".
17989 */
17990 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
17991 switch (ret = AscInitGetConfig(asc_dvc_varp)) {
17992 case 0: /* No error */
17993 break;
17994 case ASC_WARN_IO_PORT_ROTATE:
17995 ASC_PRINT1
17996 ("AscInitGetConfig: board %d: I/O port address modified\n",
17997 boardp->id);
17998 break;
17999 case ASC_WARN_AUTO_CONFIG:
18000 ASC_PRINT1
18001 ("AscInitGetConfig: board %d: I/O port increment switch enabled\n",
18002 boardp->id);
18003 break;
18004 case ASC_WARN_EEPROM_CHKSUM:
18005 ASC_PRINT1
18006 ("AscInitGetConfig: board %d: EEPROM checksum error\n",
18007 boardp->id);
18008 break;
18009 case ASC_WARN_IRQ_MODIFIED:
18010 ASC_PRINT1
18011 ("AscInitGetConfig: board %d: IRQ modified\n",
18012 boardp->id);
18013 break;
18014 case ASC_WARN_CMD_QNG_CONFLICT:
18015 ASC_PRINT1
18016 ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
18017 boardp->id);
18018 break;
18019 default:
18020 ASC_PRINT2
18021 ("AscInitGetConfig: board %d: unknown warning: 0x%x\n",
18022 boardp->id, ret);
18023 break;
18024 }
18025 if ((err_code = asc_dvc_varp->err_code) != 0) {
18026 ASC_PRINT3
18027 ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
18028 boardp->id,
18029 asc_dvc_varp->init_state, asc_dvc_varp->err_code);
18030 }
18031 } else {
18032 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
18033 if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
18034 ASC_PRINT2
18035 ("AdvInitGetConfig: board %d: warning: 0x%x\n",
18036 boardp->id, ret);
18037 }
18038 if ((err_code = adv_dvc_varp->err_code) != 0) {
18039 ASC_PRINT2
18040 ("AdvInitGetConfig: board %d error: err_code 0x%x\n",
18041 boardp->id, adv_dvc_varp->err_code);
18042 }
18043 }
18044
18045 if (err_code != 0) {
18046#ifdef CONFIG_PROC_FS
18047 kfree(boardp->prtbuf);
18048#endif /* CONFIG_PROC_FS */
18049 scsi_unregister(shost);
18050 asc_board_count--;
18051 return NULL;
18052 }
18053
18054 /*
18055 * Save the EEPROM configuration so that it can be displayed
18056 * from /proc/scsi/advansys/[0...].
18057 */
18058 if (ASC_NARROW_BOARD(boardp)) {
18059
18060 ASCEEP_CONFIG *ep;
18061
18062 /*
18063 * Set the adapter's target id bit in the 'init_tidmask' field.
18064 */
18065 boardp->init_tidmask |=
18066 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
18067
18068 /*
18069 * Save EEPROM settings for the board.
18070 */
18071 ep = &boardp->eep_config.asc_eep;
18072
18073 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
18074 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
18075 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
18076 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
18077 ep->start_motor = asc_dvc_varp->start_motor;
18078 ep->cntl = asc_dvc_varp->dvc_cntl;
18079 ep->no_scam = asc_dvc_varp->no_scam;
18080 ep->max_total_qng = asc_dvc_varp->max_total_qng;
18081 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
18082 /* 'max_tag_qng' is set to the same value for every device. */
18083 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
18084 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
18085 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
18086 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
18087 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
18088 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
18089 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
18090
18091 /*
18092 * Modify board configuration.
18093 */
18094 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
18095 switch (ret = AscInitSetConfig(asc_dvc_varp)) {
18096 case 0: /* No error. */
18097 break;
18098 case ASC_WARN_IO_PORT_ROTATE:
18099 ASC_PRINT1
18100 ("AscInitSetConfig: board %d: I/O port address modified\n",
18101 boardp->id);
18102 break;
18103 case ASC_WARN_AUTO_CONFIG:
18104 ASC_PRINT1
18105 ("AscInitSetConfig: board %d: I/O port increment switch enabled\n",
18106 boardp->id);
18107 break;
18108 case ASC_WARN_EEPROM_CHKSUM:
18109 ASC_PRINT1
18110 ("AscInitSetConfig: board %d: EEPROM checksum error\n",
18111 boardp->id);
18112 break;
18113 case ASC_WARN_IRQ_MODIFIED:
18114 ASC_PRINT1
18115 ("AscInitSetConfig: board %d: IRQ modified\n",
18116 boardp->id);
18117 break;
18118 case ASC_WARN_CMD_QNG_CONFLICT:
18119 ASC_PRINT1
18120 ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
18121 boardp->id);
18122 break;
18123 default:
18124 ASC_PRINT2
18125 ("AscInitSetConfig: board %d: unknown warning: 0x%x\n",
18126 boardp->id, ret);
18127 break;
18128 }
18129 if (asc_dvc_varp->err_code != 0) {
18130 ASC_PRINT3
18131 ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
18132 boardp->id,
18133 asc_dvc_varp->init_state, asc_dvc_varp->err_code);
18134#ifdef CONFIG_PROC_FS
18135 kfree(boardp->prtbuf);
18136#endif /* CONFIG_PROC_FS */
18137 scsi_unregister(shost);
18138 asc_board_count--;
18139 return NULL;
18140 }
18141
18142 /*
18143 * Finish initializing the 'Scsi_Host' structure.
18144 */
18145 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
18146 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
18147 shost->irq = asc_dvc_varp->irq_no;
18148 }
18149 } else {
18150 ADVEEP_3550_CONFIG *ep_3550;
18151 ADVEEP_38C0800_CONFIG *ep_38C0800;
18152 ADVEEP_38C1600_CONFIG *ep_38C1600;
18153
18154 /*
18155 * Save Wide EEP Configuration Information.
18156 */
18157 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
18158 ep_3550 = &boardp->eep_config.adv_3550_eep;
18159
18160 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
18161 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
18162 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
18163 ep_3550->termination = adv_dvc_varp->cfg->termination;
18164 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
18165 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
18166 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
18167 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
18168 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
18169 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
18170 ep_3550->start_motor = adv_dvc_varp->start_motor;
18171 ep_3550->scsi_reset_delay =
18172 adv_dvc_varp->scsi_reset_wait;
18173 ep_3550->serial_number_word1 =
18174 adv_dvc_varp->cfg->serial1;
18175 ep_3550->serial_number_word2 =
18176 adv_dvc_varp->cfg->serial2;
18177 ep_3550->serial_number_word3 =
18178 adv_dvc_varp->cfg->serial3;
18179 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
18180 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
18181
18182 ep_38C0800->adapter_scsi_id =
18183 adv_dvc_varp->chip_scsi_id;
18184 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
18185 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
18186 ep_38C0800->termination_lvd =
18187 adv_dvc_varp->cfg->termination;
18188 ep_38C0800->disc_enable =
18189 adv_dvc_varp->cfg->disc_enable;
18190 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
18191 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
18192 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
18193 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
18194 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
18195 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
18196 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
18197 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
18198 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
18199 ep_38C0800->scsi_reset_delay =
18200 adv_dvc_varp->scsi_reset_wait;
18201 ep_38C0800->serial_number_word1 =
18202 adv_dvc_varp->cfg->serial1;
18203 ep_38C0800->serial_number_word2 =
18204 adv_dvc_varp->cfg->serial2;
18205 ep_38C0800->serial_number_word3 =
18206 adv_dvc_varp->cfg->serial3;
18207 } else {
18208 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
18209
18210 ep_38C1600->adapter_scsi_id =
18211 adv_dvc_varp->chip_scsi_id;
18212 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
18213 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
18214 ep_38C1600->termination_lvd =
18215 adv_dvc_varp->cfg->termination;
18216 ep_38C1600->disc_enable =
18217 adv_dvc_varp->cfg->disc_enable;
18218 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
18219 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
18220 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
18221 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
18222 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
18223 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
18224 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
18225 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
18226 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
18227 ep_38C1600->scsi_reset_delay =
18228 adv_dvc_varp->scsi_reset_wait;
18229 ep_38C1600->serial_number_word1 =
18230 adv_dvc_varp->cfg->serial1;
18231 ep_38C1600->serial_number_word2 =
18232 adv_dvc_varp->cfg->serial2;
18233 ep_38C1600->serial_number_word3 =
18234 adv_dvc_varp->cfg->serial3;
18235 }
18236
18237 /*
18238 * Set the adapter's target id bit in the 'init_tidmask' field.
18239 */
18240 boardp->init_tidmask |=
18241 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
18242
18243 /*
18244 * Finish initializing the 'Scsi_Host' structure.
18245 */
18246 shost->irq = adv_dvc_varp->irq_no;
18247 }
18248
18249 /*
18250 * Channels are numbered beginning with 0. For AdvanSys one host
18251 * structure supports one channel. Multi-channel boards have a
18252 * separate host structure for each channel.
18253 */
18254 shost->max_channel = 0;
18255 if (ASC_NARROW_BOARD(boardp)) {
18256 shost->max_id = ASC_MAX_TID + 1;
18257 shost->max_lun = ASC_MAX_LUN + 1;
18258
18259 shost->io_port = asc_dvc_varp->iop_base;
18260 boardp->asc_n_io_port = ASC_IOADR_GAP;
18261 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
18262
18263 /* Set maximum number of queues the adapter can handle. */
18264 shost->can_queue = asc_dvc_varp->max_total_qng;
18265 } else {
18266 shost->max_id = ADV_MAX_TID + 1;
18267 shost->max_lun = ADV_MAX_LUN + 1;
18268
18269 /*
18270 * Save the I/O Port address and length even though
18271 * I/O ports are not used to access Wide boards.
18272 * Instead the Wide boards are accessed with
18273 * PCI Memory Mapped I/O.
18274 */
18275 shost->io_port = iop;
18276 boardp->asc_n_io_port = iolen;
18277
18278 shost->this_id = adv_dvc_varp->chip_scsi_id;
18279
18280 /* Set maximum number of queues the adapter can handle. */
18281 shost->can_queue = adv_dvc_varp->max_host_qng;
18282 }
18283
18284 /*
18285 * 'n_io_port' currently is one byte.
18286 *
18287 * Set a value to 'n_io_port', but never referenced it because
18288 * it may be truncated.
18289 */
18290 shost->n_io_port = boardp->asc_n_io_port <= 255 ?
18291 boardp->asc_n_io_port : 255;
18292
18293 /*
18294 * Following v1.3.89, 'cmd_per_lun' is no longer needed
18295 * and should be set to zero.
18296 *
18297 * But because of a bug introduced in v1.3.89 if the driver is
18298 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
18299 * SCSI function 'allocate_device' will panic. To allow the driver
18300 * to work as a module in these kernels set 'cmd_per_lun' to 1.
18301 *
18302 * Note: This is wrong. cmd_per_lun should be set to the depth
18303 * you want on untagged devices always.
18304 #ifdef MODULE
18305 */
18306 shost->cmd_per_lun = 1;
18307/* #else
18308 shost->cmd_per_lun = 0;
18309#endif */
18310
18311 /*
18312 * Set the maximum number of scatter-gather elements the
18313 * adapter can handle.
18314 */
18315 if (ASC_NARROW_BOARD(boardp)) {
18316 /*
18317 * Allow two commands with 'sg_tablesize' scatter-gather
18318 * elements to be executed simultaneously. This value is
18319 * the theoretical hardware limit. It may be decreased
18320 * below.
18321 */
18322 shost->sg_tablesize =
18323 (((asc_dvc_varp->max_total_qng - 2) / 2) *
18324 ASC_SG_LIST_PER_Q) + 1;
18325 } else {
18326 shost->sg_tablesize = ADV_MAX_SG_LIST;
18327 }
18328
18329 /*
18330 * The value of 'sg_tablesize' can not exceed the SCSI
18331 * mid-level driver definition of SG_ALL. SG_ALL also
18332 * must not be exceeded, because it is used to define the
18333 * size of the scatter-gather table in 'struct asc_sg_head'.
18334 */
18335 if (shost->sg_tablesize > SG_ALL) {
18336 shost->sg_tablesize = SG_ALL;
18337 }
18338
18339 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
18340
18341 /* BIOS start address. */
18342 if (ASC_NARROW_BOARD(boardp)) {
18343 shost->base = ((ulong)
18344 AscGetChipBiosAddress(asc_dvc_varp->
18345 iop_base,
18346 asc_dvc_varp->bus_type));
18347 } else {
18348 /*
18349 * Fill-in BIOS board variables. The Wide BIOS saves
18350 * information in LRAM that is used by the driver.
18351 */
18352 AdvReadWordLram(adv_dvc_varp->iop_base,
18353 BIOS_SIGNATURE, boardp->bios_signature);
18354 AdvReadWordLram(adv_dvc_varp->iop_base,
18355 BIOS_VERSION, boardp->bios_version);
18356 AdvReadWordLram(adv_dvc_varp->iop_base,
18357 BIOS_CODESEG, boardp->bios_codeseg);
18358 AdvReadWordLram(adv_dvc_varp->iop_base,
18359 BIOS_CODELEN, boardp->bios_codelen);
18360
18361 ASC_DBG2(1,
18362 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
18363 boardp->bios_signature, boardp->bios_version);
18364
18365 ASC_DBG2(1,
18366 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
18367 boardp->bios_codeseg, boardp->bios_codelen);
18368
18369 /*
18370 * If the BIOS saved a valid signature, then fill in
18371 * the BIOS code segment base address.
18372 */
18373 if (boardp->bios_signature == 0x55AA) {
18374 /*
18375 * Convert x86 realmode code segment to a linear
18376 * address by shifting left 4.
18377 */
18378 shost->base = ((ulong)boardp->bios_codeseg << 4);
18379 } else {
18380 shost->base = 0;
18381 }
18382 }
18383
18384 /*
18385 * Register Board Resources - I/O Port, DMA, IRQ
18386 */
18387
18388 /*
18389 * Register I/O port range.
18390 *
18391 * For Wide boards the I/O ports are not used to access
18392 * the board, but request the region anyway.
18393 *
18394 * 'shost->n_io_port' is not referenced, because it may be truncated.
18395 */
18396 ASC_DBG2(2,
18397 "advansys_board_found: request_region port 0x%lx, len 0x%x\n",
18398 (ulong)shost->io_port, boardp->asc_n_io_port);
18399 if (request_region(shost->io_port, boardp->asc_n_io_port,
18400 "advansys") == NULL) {
18401 ASC_PRINT3
18402 ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n",
18403 boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port);
18404#ifdef CONFIG_PROC_FS
18405 kfree(boardp->prtbuf);
18406#endif /* CONFIG_PROC_FS */
18407 scsi_unregister(shost);
18408 asc_board_count--;
18409 return NULL;
18410 }
18411
18412 /* Register DMA Channel for Narrow boards. */
18413 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
18414#ifdef CONFIG_ISA
18415 if (ASC_NARROW_BOARD(boardp)) {
18416 /* Register DMA channel for ISA bus. */
18417 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
18418 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
18419 if ((ret =
18420 request_dma(shost->dma_channel, "advansys")) != 0) {
18421 ASC_PRINT3
18422 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
18423 boardp->id, shost->dma_channel, ret);
18424 release_region(shost->io_port,
18425 boardp->asc_n_io_port);
18426#ifdef CONFIG_PROC_FS
18427 kfree(boardp->prtbuf);
18428#endif /* CONFIG_PROC_FS */
18429 scsi_unregister(shost);
18430 asc_board_count--;
18431 return NULL;
18432 }
18433 AscEnableIsaDma(shost->dma_channel);
18434 }
18435 }
18436#endif /* CONFIG_ISA */
18437
18438 /* Register IRQ Number. */
18439 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
18440 /*
18441 * If request_irq() fails with the IRQF_DISABLED flag set,
18442 * then try again without the IRQF_DISABLED flag set. This
18443 * allows IRQ sharing to work even with other drivers that
18444 * do not set the IRQF_DISABLED flag.
18445 *
18446 * If IRQF_DISABLED is not set, then interrupts are enabled
18447 * before the driver interrupt function is called.
18448 */
18449 if (((ret = request_irq(shost->irq, advansys_interrupt,
18450 IRQF_DISABLED | (share_irq ==
18451 TRUE ?
18452 IRQF_SHARED :
18453 0), "advansys", boardp)) != 0)
18454 &&
18455 ((ret =
18456 request_irq(shost->irq, advansys_interrupt,
18457 (share_irq == TRUE ? IRQF_SHARED : 0),
18458 "advansys", boardp)) != 0)) {
18459 if (ret == -EBUSY) {
18460 ASC_PRINT2
18461 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
18462 boardp->id, shost->irq);
18463 } else if (ret == -EINVAL) {
18464 ASC_PRINT2
18465 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
18466 boardp->id, shost->irq);
18467 } else {
18468 ASC_PRINT3
18469 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
18470 boardp->id, shost->irq, ret);
18471 }
18472 release_region(shost->io_port, boardp->asc_n_io_port);
18473 iounmap(boardp->ioremap_addr);
18474 if (shost->dma_channel != NO_ISA_DMA) {
18475 free_dma(shost->dma_channel);
18476 }
18477#ifdef CONFIG_PROC_FS
18478 kfree(boardp->prtbuf);
18479#endif /* CONFIG_PROC_FS */
18480 scsi_unregister(shost);
18481 asc_board_count--;
18482 return NULL;
18483 }
18484
18485 /*
18486 * Initialize board RISC chip and enable interrupts.
18487 */
18488 if (ASC_NARROW_BOARD(boardp)) {
18489 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
18490 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
18491 err_code = asc_dvc_varp->err_code;
18492
18493 if (warn_code || err_code) {
18494 ASC_PRINT4
18495 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
18496 boardp->id,
18497 asc_dvc_varp->init_state, warn_code, err_code);
18498 }
18499 } else {
18500 ADV_CARR_T *carrp;
18501 int req_cnt = 0;
18502 adv_req_t *reqp = NULL;
18503 int sg_cnt = 0;
18504
18505 /*
18506 * Allocate buffer carrier structures. The total size
18507 * is about 4 KB, so allocate all at once.
18508 */
18509 carrp = (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC);
18510 ASC_DBG1(1, "advansys_board_found: carrp 0x%lx\n", (ulong)carrp);
18511
18512 if (carrp == NULL) {
18513 goto kmalloc_error;
18514 }
18515
18516 /*
18517 * Allocate up to 'max_host_qng' request structures for
18518 * the Wide board. The total size is about 16 KB, so
18519 * allocate all at once. If the allocation fails decrement
18520 * and try again.
18521 */
18522 for (req_cnt = adv_dvc_varp->max_host_qng;
18523 req_cnt > 0; req_cnt--) {
18524
18525 reqp = (adv_req_t *)
18526 kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
18527
18528 ASC_DBG3(1,
18529 "advansys_board_found: reqp 0x%lx, req_cnt %d, bytes %lu\n",
18530 (ulong)reqp, req_cnt,
18531 (ulong)sizeof(adv_req_t) * req_cnt);
18532
18533 if (reqp != NULL) {
18534 break;
18535 }
18536 }
18537 if (reqp == NULL) {
18538 goto kmalloc_error;
18539 }
18540
18541 /*
18542 * Allocate up to ADV_TOT_SG_BLOCK request structures for
18543 * the Wide board. Each structure is about 136 bytes.
18544 */
18545 boardp->adv_sgblkp = NULL;
18546 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
18547
18548 sgp = (adv_sgblk_t *)
18549 kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC);
18550
18551 if (sgp == NULL) {
18552 break;
18553 }
18554
18555 sgp->next_sgblkp = boardp->adv_sgblkp;
18556 boardp->adv_sgblkp = sgp;
18557
18558 }
18559 ASC_DBG3(1,
18560 "advansys_board_found: sg_cnt %d * %u = %u bytes\n",
18561 sg_cnt, sizeof(adv_sgblk_t),
18562 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
18563
18564 /*
18565 * If no request structures or scatter-gather structures could
18566 * be allocated, then return an error. Otherwise continue with
18567 * initialization.
18568 */
18569 kmalloc_error:
18570 if (carrp == NULL) {
18571 ASC_PRINT1
18572 ("advansys_board_found: board %d error: failed to kmalloc() carrier buffer.\n",
18573 boardp->id);
18574 err_code = ADV_ERROR;
18575 } else if (reqp == NULL) {
18576 kfree(carrp);
18577 ASC_PRINT1
18578 ("advansys_board_found: board %d error: failed to kmalloc() adv_req_t buffer.\n",
18579 boardp->id);
18580 err_code = ADV_ERROR;
18581 } else if (boardp->adv_sgblkp == NULL) {
18582 kfree(carrp);
18583 kfree(reqp);
18584 ASC_PRINT1
18585 ("advansys_board_found: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n",
18586 boardp->id);
18587 err_code = ADV_ERROR;
18588 } else {
18589
18590 /* Save carrier buffer pointer. */
18591 boardp->orig_carrp = carrp;
18592
18593 /*
18594 * Save original pointer for kfree() in case the
18595 * driver is built as a module and can be unloaded.
18596 */
18597 boardp->orig_reqp = reqp;
18598
18599 adv_dvc_varp->carrier_buf = carrp;
18600
18601 /*
18602 * Point 'adv_reqp' to the request structures and
18603 * link them together.
18604 */
18605 req_cnt--;
18606 reqp[req_cnt].next_reqp = NULL;
18607 for (; req_cnt > 0; req_cnt--) {
18608 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
18609 }
18610 boardp->adv_reqp = &reqp[0];
18611
18612 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
18613 ASC_DBG(2,
18614 "advansys_board_found: AdvInitAsc3550Driver()\n");
18615 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
18616 } else if (adv_dvc_varp->chip_type ==
18617 ADV_CHIP_ASC38C0800) {
18618 ASC_DBG(2,
18619 "advansys_board_found: AdvInitAsc38C0800Driver()\n");
18620 warn_code =
18621 AdvInitAsc38C0800Driver(adv_dvc_varp);
18622 } else {
18623 ASC_DBG(2,
18624 "advansys_board_found: AdvInitAsc38C1600Driver()\n");
18625 warn_code =
18626 AdvInitAsc38C1600Driver(adv_dvc_varp);
18627 }
18628 err_code = adv_dvc_varp->err_code;
18629
18630 if (warn_code || err_code) {
18631 ASC_PRINT3
18632 ("advansys_board_found: board %d error: warn 0x%x, error 0x%x\n",
18633 boardp->id, warn_code, err_code);
18634 }
18635 }
18636 }
18637
18638 if (err_code != 0) {
18639 release_region(shost->io_port, boardp->asc_n_io_port);
18640 if (ASC_WIDE_BOARD(boardp)) {
18641 iounmap(boardp->ioremap_addr);
18642 kfree(boardp->orig_carrp);
18643 boardp->orig_carrp = NULL;
18644 if (boardp->orig_reqp) {
18645 kfree(boardp->orig_reqp);
18646 boardp->orig_reqp = boardp->adv_reqp = NULL;
18647 }
18648 while ((sgp = boardp->adv_sgblkp) != NULL) {
18649 boardp->adv_sgblkp = sgp->next_sgblkp;
18650 kfree(sgp);
18651 }
18652 }
18653 if (shost->dma_channel != NO_ISA_DMA) {
18654 free_dma(shost->dma_channel);
18655 }
18656#ifdef CONFIG_PROC_FS
18657 kfree(boardp->prtbuf);
18658#endif /* CONFIG_PROC_FS */
18659 free_irq(shost->irq, boardp);
18660 scsi_unregister(shost);
18661 asc_board_count--;
18662 return NULL;
18663 }
18664 ASC_DBG_PRT_SCSI_HOST(2, shost);
18665
18666 return shost;
18667}
18668
18669/*
18670 * advansys_detect()
18671 *
18672 * Detect function for AdvanSys adapters.
18673 *
18674 * Argument is a pointer to the host driver's scsi_hosts entry.
18675 *
18676 * Return number of adapters found.
18677 *
18678 * Note: Because this function is called during system initialization
18679 * it must not call SCSI mid-level functions including scsi_malloc()
18680 * and scsi_free().
18681 */
18682static int __init advansys_detect(struct scsi_host_template *tpnt)
18683{
18684 static int detect_called = ASC_FALSE;
18685 int iop;
18686 int bus;
18687 int ioport = 0;
18688 struct device *dev = NULL;
18689#ifdef CONFIG_PCI
18690 int pci_init_search = 0;
18691 struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED];
18692 int pci_card_cnt_max = 0;
18693 int pci_card_cnt = 0;
18694 struct pci_dev *pdev = NULL;
18695 int pci_device_id_cnt = 0;
18696 unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
18697 PCI_DEVICE_ID_ASP_1200A,
18698 PCI_DEVICE_ID_ASP_ABP940,
18699 PCI_DEVICE_ID_ASP_ABP940U,
18700 PCI_DEVICE_ID_ASP_ABP940UW,
18701 PCI_DEVICE_ID_38C0800_REV1,
18702 PCI_DEVICE_ID_38C1600_REV1
18703 };
18704#endif /* CONFIG_PCI */
18705
18706 if (detect_called == ASC_FALSE) {
18707 detect_called = ASC_TRUE;
18708 } else {
18709 printk
18710 ("AdvanSys SCSI: advansys_detect() multiple calls ignored\n");
18711 return 0;
18712 }
18713
18714 ASC_DBG(1, "advansys_detect: begin\n");
18715
18716 asc_board_count = 0;
18717
18718 /*
18719 * If I/O port probing has been modified, then verify and
18720 * clean-up the 'asc_ioport' list.
18721 */
18722 if (asc_iopflag == ASC_TRUE) {
18723 for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
18724 ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%x\n",
18725 ioport, asc_ioport[ioport]);
18726 if (asc_ioport[ioport] != 0) {
18727 for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX;
18728 iop++) {
18729 if (_asc_def_iop_base[iop] ==
18730 asc_ioport[ioport]) {
18731 break;
18732 }
18733 }
18734 if (iop == ASC_IOADR_TABLE_MAX_IX) {
18735 printk
18736 ("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
18737 asc_ioport[ioport]);
18738 asc_ioport[ioport] = 0;
18739 }
18740 }
18741 }
18742 ioport = 0;
18743 }
18744
18745 for (bus = 0; bus < ASC_NUM_BUS; bus++) {
18746
18747 ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
18748 bus, asc_bus_name[bus]);
18749 iop = 0;
18750
18751 while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
18752
18753 ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
18754 asc_board_count);
18755
18756 switch (asc_bus[bus]) {
18757 case ASC_IS_ISA:
18758 case ASC_IS_VL:
18759#ifdef CONFIG_ISA
18760 if (asc_iopflag == ASC_FALSE) {
18761 iop =
18762 AscSearchIOPortAddr(iop,
18763 asc_bus[bus]);
18764 } else {
18765 /*
18766 * ISA and VL I/O port scanning has either been
18767 * eliminated or limited to selected ports on
18768 * the LILO command line, /etc/lilo.conf, or
18769 * by setting variables when the module was loaded.
18770 */
18771 ASC_DBG(1,
18772 "advansys_detect: I/O port scanning modified\n");
18773 ioport_try_again:
18774 iop = 0;
18775 for (; ioport < ASC_NUM_IOPORT_PROBE;
18776 ioport++) {
18777 if ((iop =
18778 asc_ioport[ioport]) != 0) {
18779 break;
18780 }
18781 }
18782 if (iop) {
18783 ASC_DBG1(1,
18784 "advansys_detect: probing I/O port 0x%x...\n",
18785 iop);
18786 if (!request_region
18787 (iop, ASC_IOADR_GAP,
18788 "advansys")) {
18789 printk
18790 ("AdvanSys SCSI: specified I/O Port 0x%X is busy\n",
18791 iop);
18792 /* Don't try this I/O port twice. */
18793 asc_ioport[ioport] = 0;
18794 goto ioport_try_again;
18795 } else if (AscFindSignature(iop)
18796 == ASC_FALSE) {
18797 printk
18798 ("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n",
18799 iop);
18800 /* Don't try this I/O port twice. */
18801 release_region(iop,
18802 ASC_IOADR_GAP);
18803 asc_ioport[ioport] = 0;
18804 goto ioport_try_again;
18805 } else {
18806 /*
18807 * If this isn't an ISA board, then it must be
18808 * a VL board. If currently looking an ISA
18809 * board is being looked for then try for
18810 * another ISA board in 'asc_ioport'.
18811 */
18812 if (asc_bus[bus] ==
18813 ASC_IS_ISA
18814 &&
18815 (AscGetChipVersion
18816 (iop,
18817 ASC_IS_ISA) &
18818 ASC_CHIP_VER_ISA_BIT)
18819 == 0) {
18820 /*
18821 * Don't clear 'asc_ioport[ioport]'. Try
18822 * this board again for VL. Increment
18823 * 'ioport' past this board.
18824 */
18825 ioport++;
18826 release_region
18827 (iop,
18828 ASC_IOADR_GAP);
18829 goto ioport_try_again;
18830 }
18831 }
18832 /*
18833 * This board appears good, don't try the I/O port
18834 * again by clearing its value. Increment 'ioport'
18835 * for the next iteration.
18836 */
18837 asc_ioport[ioport++] = 0;
18838 }
18839 }
18840#endif /* CONFIG_ISA */
18841 break;
18842
18843 case ASC_IS_EISA:
18844#ifdef CONFIG_ISA
18845 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
18846#endif /* CONFIG_ISA */
18847 break;
18848
18849 case ASC_IS_PCI:
18850#ifdef CONFIG_PCI
18851 if (pci_init_search == 0) {
18852 int i, j;
18853
18854 pci_init_search = 1;
18855
18856 /* Find all PCI cards. */
18857 while (pci_device_id_cnt <
18858 ASC_PCI_DEVICE_ID_CNT) {
18859 if ((pdev =
18860 pci_find_device
18861 (PCI_VENDOR_ID_ASP,
18862 pci_device_id
18863 [pci_device_id_cnt],
18864 pdev)) == NULL) {
18865 pci_device_id_cnt++;
18866 } else {
18867 if (pci_enable_device
18868 (pdev) == 0) {
18869 pci_devicep
18870 [pci_card_cnt_max++]
18871 = pdev;
18872 }
18873 }
18874 }
18875
18876 /*
18877 * Sort PCI cards in ascending order by PCI Bus, Slot,
18878 * and Device Number.
18879 */
18880 for (i = 0; i < pci_card_cnt_max - 1;
18881 i++) {
18882 for (j = i + 1;
18883 j < pci_card_cnt_max;
18884 j++) {
18885 if ((pci_devicep[j]->
18886 bus->number <
18887 pci_devicep[i]->
18888 bus->number)
18889 ||
18890 ((pci_devicep[j]->
18891 bus->number ==
18892 pci_devicep[i]->
18893 bus->number)
18894 &&
18895 (pci_devicep[j]->
18896 devfn <
18897 pci_devicep[i]->
18898 devfn))) {
18899 pdev =
18900 pci_devicep
18901 [i];
18902 pci_devicep[i] =
18903 pci_devicep
18904 [j];
18905 pci_devicep[j] =
18906 pdev;
18907 }
18908 }
18909 }
18910
18911 pci_card_cnt = 0;
18912 } else {
18913 pci_card_cnt++;
18914 }
18915
18916 if (pci_card_cnt == pci_card_cnt_max) {
18917 iop = 0;
18918 } else {
18919 pdev = pci_devicep[pci_card_cnt];
18920
18921 ASC_DBG2(2,
18922 "advansys_detect: devfn %d, bus number %d\n",
18923 pdev->devfn,
18924 pdev->bus->number);
18925 iop = pci_resource_start(pdev, 0);
18926 ASC_DBG2(1,
18927 "advansys_detect: vendorID %X, deviceID %X\n",
18928 pdev->vendor,
18929 pdev->device);
18930 ASC_DBG2(2,
18931 "advansys_detect: iop %X, irqLine %d\n",
18932 iop, pdev->irq);
18933 }
18934 if (pdev)
18935 dev = &pdev->dev;
18936
18937#endif /* CONFIG_PCI */
18938 break;
18939
18940 default:
18941 ASC_PRINT1
18942 ("advansys_detect: unknown bus type: %d\n",
18943 asc_bus[bus]);
18944 break;
18945 }
18946 ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop);
18947
18948 /*
18949 * Adapter not found, try next bus type.
18950 */
18951 if (iop == 0) {
18952 break;
18953 }
18954
18955 advansys_board_found(iop, dev, asc_bus[bus]);
18956 }
18957 }
18958
18959 ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n",
18960 asc_board_count);
18961 return asc_board_count;
18962}
18963
18964/*
18965 * advansys_release()
18966 *
18967 * Release resources allocated for a single AdvanSys adapter.
18968 */
18969static int advansys_release(struct Scsi_Host *shost)
18970{
18971 asc_board_t *boardp;
18972
18973 ASC_DBG(1, "advansys_release: begin\n");
18974 boardp = ASC_BOARDP(shost);
18975 free_irq(shost->irq, boardp);
18976 if (shost->dma_channel != NO_ISA_DMA) {
18977 ASC_DBG(1, "advansys_release: free_dma()\n");
18978 free_dma(shost->dma_channel);
18979 }
18980 release_region(shost->io_port, boardp->asc_n_io_port);
18981 if (ASC_WIDE_BOARD(boardp)) {
18982 adv_sgblk_t *sgp = NULL;
18983
18984 iounmap(boardp->ioremap_addr);
18985 kfree(boardp->orig_carrp);
18986 boardp->orig_carrp = NULL;
18987 if (boardp->orig_reqp) {
18988 kfree(boardp->orig_reqp);
18989 boardp->orig_reqp = boardp->adv_reqp = NULL;
18990 }
18991 while ((sgp = boardp->adv_sgblkp) != NULL) {
18992 boardp->adv_sgblkp = sgp->next_sgblkp;
18993 kfree(sgp);
18994 }
18995 }
18996#ifdef CONFIG_PROC_FS
18997 ASC_ASSERT(boardp->prtbuf != NULL);
18998 kfree(boardp->prtbuf);
18999#endif /* CONFIG_PROC_FS */
19000 scsi_unregister(shost);
19001 ASC_DBG(1, "advansys_release: end\n");
19002 return 0;
19003}
19004
Randy Dunlapd8dafd82006-11-21 13:50:47 -080019005#ifdef CONFIG_PCI
Dave Jones2672ea82006-08-02 17:11:49 -040019006/* PCI Devices supported by this driver */
19007static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040019008 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
19009 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
19010 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
19011 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
19012 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
19013 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
19014 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
19015 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
19016 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
19017 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
19018 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
19019 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
19020 {}
Dave Jones2672ea82006-08-02 17:11:49 -040019021};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040019022
Dave Jones2672ea82006-08-02 17:11:49 -040019023MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Randy Dunlapd8dafd82006-11-21 13:50:47 -080019024#endif /* CONFIG_PCI */
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040019025
19026MODULE_LICENSE("GPL");