blob: 310b92678035a29c17926933b7c6d3a88d0bcac5 [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
Matthew Wilcoxc304ec92007-07-30 09:18:45 -0600283 /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
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 Wilcoxc304ec92007-07-30 09:18:45 -0600772#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -0600773#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -0400774#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775#include <linux/spinlock.h>
776#include <linux/dma-mapping.h>
777
778#include <asm/io.h>
779#include <asm/system.h>
780#include <asm/dma.h>
781
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -0400782#include <scsi/scsi_cmnd.h>
783#include <scsi/scsi_device.h>
784#include <scsi/scsi_tcq.h>
785#include <scsi/scsi.h>
786#include <scsi/scsi_host.h>
787
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -0600788/* FIXME: (by jejb@steeleye.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 *
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -0600790 * Although all of the necessary command mapping places have the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 * appropriate dma_map.. APIs, the driver still processes its internal
792 * queue using bus_to_virt() and virt_to_bus() which are illegal under
793 * the API. The entire queue processing structure will need to be
794 * altered to fix this.
795 */
796#warning this driver is still not properly converted to the DMA API
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798/*
799 * --- Driver Options
800 */
801
802/* Enable driver assertions. */
803#define ADVANSYS_ASSERT
804
805/* Enable driver /proc statistics. */
806#define ADVANSYS_STATS
807
808/* Enable driver tracing. */
809/* #define ADVANSYS_DEBUG */
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811/*
812 * --- Asc Library Constants and Macros
813 */
814
815#define ASC_LIB_VERSION_MAJOR 1
816#define ASC_LIB_VERSION_MINOR 24
817#define ASC_LIB_SERIAL_NUMBER 123
818
819/*
820 * Portable Data Types
821 *
822 * Any instance where a 32-bit long or pointer type is assumed
823 * for precision or HW defined structures, the following define
824 * types must be used. In Linux the char, short, and int types
825 * are all consistent at 8, 16, and 32 bits respectively. Pointers
826 * and long types are 64 bits on Alpha and UltraSPARC.
827 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400828#define ASC_PADDR __u32 /* Physical/Bus address data type. */
829#define ASC_VADDR __u32 /* Virtual address data type. */
830#define ASC_DCNT __u32 /* Unsigned Data count type. */
831#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833/*
834 * These macros are used to convert a virtual address to a
835 * 32-bit value. This currently can be used on Linux Alpha
836 * which uses 64-bit virtual address but a 32-bit bus address.
837 * This is likely to break in the future, but doing this now
838 * will give us time to change the HW and FW to handle 64-bit
839 * addresses.
840 */
841#define ASC_VADDR_TO_U32 virt_to_bus
842#define ASC_U32_TO_VADDR bus_to_virt
843
844typedef unsigned char uchar;
845
846#ifndef TRUE
847#define TRUE (1)
848#endif
849#ifndef FALSE
850#define FALSE (0)
851#endif
852
853#define EOF (-1)
854#define ERR (-1)
855#define UW_ERR (uint)(0xFFFF)
856#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857#define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7)
858#define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
860#define ASC_DVCLIB_CALL_DONE (1)
861#define ASC_DVCLIB_CALL_FAILED (0)
862#define ASC_DVCLIB_CALL_ERROR (-1)
863
Dave Jones2672ea82006-08-02 17:11:49 -0400864#define PCI_VENDOR_ID_ASP 0x10cd
865#define PCI_DEVICE_ID_ASP_1200A 0x1100
866#define PCI_DEVICE_ID_ASP_ABP940 0x1200
867#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
868#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
869#define PCI_DEVICE_ID_38C0800_REV1 0x2500
870#define PCI_DEVICE_ID_38C1600_REV1 0x2700
871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872/*
873 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
874 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
875 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
876 * SRB structure.
877 */
878#define CC_VERY_LONG_SG_LIST 0
879#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
880
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400881#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882#define inp(port) inb(port)
883#define outp(port, byte) outb((byte), (port))
884
885#define inpw(port) inw(port)
886#define outpw(port, word) outw((word), (port))
887
888#define ASC_MAX_SG_QUEUE 7
889#define ASC_MAX_SG_LIST 255
890
891#define ASC_CS_TYPE unsigned short
892
893#define ASC_IS_ISA (0x0001)
894#define ASC_IS_ISAPNP (0x0081)
895#define ASC_IS_EISA (0x0002)
896#define ASC_IS_PCI (0x0004)
897#define ASC_IS_PCI_ULTRA (0x0104)
898#define ASC_IS_PCMCIA (0x0008)
899#define ASC_IS_MCA (0x0020)
900#define ASC_IS_VL (0x0040)
901#define ASC_ISA_PNP_PORT_ADDR (0x279)
902#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
903#define ASC_IS_WIDESCSI_16 (0x0100)
904#define ASC_IS_WIDESCSI_32 (0x0200)
905#define ASC_IS_BIG_ENDIAN (0x8000)
906#define ASC_CHIP_MIN_VER_VL (0x01)
907#define ASC_CHIP_MAX_VER_VL (0x07)
908#define ASC_CHIP_MIN_VER_PCI (0x09)
909#define ASC_CHIP_MAX_VER_PCI (0x0F)
910#define ASC_CHIP_VER_PCI_BIT (0x08)
911#define ASC_CHIP_MIN_VER_ISA (0x11)
912#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
913#define ASC_CHIP_MAX_VER_ISA (0x27)
914#define ASC_CHIP_VER_ISA_BIT (0x30)
915#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
916#define ASC_CHIP_VER_ASYN_BUG (0x21)
917#define ASC_CHIP_VER_PCI 0x08
918#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
919#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
920#define ASC_CHIP_MIN_VER_EISA (0x41)
921#define ASC_CHIP_MAX_VER_EISA (0x47)
922#define ASC_CHIP_VER_EISA_BIT (0x40)
923#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
924#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
925#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
926#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
927#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
928#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
929#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
930#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
931#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
932#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
933#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
934
935#define ASC_SCSI_ID_BITS 3
936#define ASC_SCSI_TIX_TYPE uchar
937#define ASC_ALL_DEVICE_BIT_SET 0xFF
938#define ASC_SCSI_BIT_ID_TYPE uchar
939#define ASC_MAX_TID 7
940#define ASC_MAX_LUN 7
941#define ASC_SCSI_WIDTH_BIT_SET 0xFF
942#define ASC_MAX_SENSE_LEN 32
943#define ASC_MIN_SENSE_LEN 14
944#define ASC_MAX_CDB_LEN 12
945#define ASC_SCSI_RESET_HOLD_TIME_US 60
946
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947/*
948 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
949 * and CmdDt (Command Support Data) field bit definitions.
950 */
951#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
952#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
953#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
954#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
955
956#define ASC_SCSIDIR_NOCHK 0x00
957#define ASC_SCSIDIR_T2H 0x08
958#define ASC_SCSIDIR_H2T 0x10
959#define ASC_SCSIDIR_NODATA 0x18
960#define SCSI_ASC_NOMEDIA 0x3A
961#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
962#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
963#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
964#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
968#define ASC_SG_LIST_PER_Q 7
969#define QS_FREE 0x00
970#define QS_READY 0x01
971#define QS_DISC1 0x02
972#define QS_DISC2 0x04
973#define QS_BUSY 0x08
974#define QS_ABORTED 0x40
975#define QS_DONE 0x80
976#define QC_NO_CALLBACK 0x01
977#define QC_SG_SWAP_QUEUE 0x02
978#define QC_SG_HEAD 0x04
979#define QC_DATA_IN 0x08
980#define QC_DATA_OUT 0x10
981#define QC_URGENT 0x20
982#define QC_MSG_OUT 0x40
983#define QC_REQ_SENSE 0x80
984#define QCSG_SG_XFER_LIST 0x02
985#define QCSG_SG_XFER_MORE 0x04
986#define QCSG_SG_XFER_END 0x08
987#define QD_IN_PROGRESS 0x00
988#define QD_NO_ERROR 0x01
989#define QD_ABORTED_BY_HOST 0x02
990#define QD_WITH_ERROR 0x04
991#define QD_INVALID_REQUEST 0x80
992#define QD_INVALID_HOST_NUM 0x81
993#define QD_INVALID_DEVICE 0x82
994#define QD_ERR_INTERNAL 0xFF
995#define QHSTA_NO_ERROR 0x00
996#define QHSTA_M_SEL_TIMEOUT 0x11
997#define QHSTA_M_DATA_OVER_RUN 0x12
998#define QHSTA_M_DATA_UNDER_RUN 0x12
999#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
1000#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
1001#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1002#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
1003#define QHSTA_D_HOST_ABORT_FAILED 0x23
1004#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
1005#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1006#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
1007#define QHSTA_M_WTM_TIMEOUT 0x41
1008#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
1009#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
1010#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1011#define QHSTA_M_TARGET_STATUS_BUSY 0x45
1012#define QHSTA_M_BAD_TAG_CODE 0x46
1013#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
1014#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
1015#define QHSTA_D_LRAM_CMP_ERROR 0x81
1016#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1017#define ASC_FLAG_SCSIQ_REQ 0x01
1018#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1019#define ASC_FLAG_BIOS_ASYNC_IO 0x04
1020#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1021#define ASC_FLAG_WIN16 0x10
1022#define ASC_FLAG_WIN32 0x20
1023#define ASC_FLAG_ISA_OVER_16MB 0x40
1024#define ASC_FLAG_DOS_VM_CALLBACK 0x80
1025#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
1026#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
1027#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
1028#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
1029#define ASC_SCSIQ_CPY_BEG 4
1030#define ASC_SCSIQ_SGHD_CPY_BEG 2
1031#define ASC_SCSIQ_B_FWD 0
1032#define ASC_SCSIQ_B_BWD 1
1033#define ASC_SCSIQ_B_STATUS 2
1034#define ASC_SCSIQ_B_QNO 3
1035#define ASC_SCSIQ_B_CNTL 4
1036#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1037#define ASC_SCSIQ_D_DATA_ADDR 8
1038#define ASC_SCSIQ_D_DATA_CNT 12
1039#define ASC_SCSIQ_B_SENSE_LEN 20
1040#define ASC_SCSIQ_DONE_INFO_BEG 22
1041#define ASC_SCSIQ_D_SRBPTR 22
1042#define ASC_SCSIQ_B_TARGET_IX 26
1043#define ASC_SCSIQ_B_CDB_LEN 28
1044#define ASC_SCSIQ_B_TAG_CODE 29
1045#define ASC_SCSIQ_W_VM_ID 30
1046#define ASC_SCSIQ_DONE_STATUS 32
1047#define ASC_SCSIQ_HOST_STATUS 33
1048#define ASC_SCSIQ_SCSI_STATUS 34
1049#define ASC_SCSIQ_CDB_BEG 36
1050#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1051#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1052#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
1053#define ASC_SCSIQ_B_SG_WK_QP 49
1054#define ASC_SCSIQ_B_SG_WK_IX 50
1055#define ASC_SCSIQ_W_ALT_DC1 52
1056#define ASC_SCSIQ_B_LIST_CNT 6
1057#define ASC_SCSIQ_B_CUR_LIST_CNT 7
1058#define ASC_SGQ_B_SG_CNTL 4
1059#define ASC_SGQ_B_SG_HEAD_QP 5
1060#define ASC_SGQ_B_SG_LIST_CNT 6
1061#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1062#define ASC_SGQ_LIST_BEG 8
1063#define ASC_DEF_SCSI1_QNG 4
1064#define ASC_MAX_SCSI1_QNG 4
1065#define ASC_DEF_SCSI2_QNG 16
1066#define ASC_MAX_SCSI2_QNG 32
1067#define ASC_TAG_CODE_MASK 0x23
1068#define ASC_STOP_REQ_RISC_STOP 0x01
1069#define ASC_STOP_ACK_RISC_STOP 0x03
1070#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1071#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1072#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1073#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
1074#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
1075#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
1076#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
1077#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
1078#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
1079#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
1080
1081typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001082 uchar status;
1083 uchar q_no;
1084 uchar cntl;
1085 uchar sg_queue_cnt;
1086 uchar target_id;
1087 uchar target_lun;
1088 ASC_PADDR data_addr;
1089 ASC_DCNT data_cnt;
1090 ASC_PADDR sense_addr;
1091 uchar sense_len;
1092 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093} ASC_SCSIQ_1;
1094
1095typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001096 ASC_VADDR srb_ptr;
1097 uchar target_ix;
1098 uchar flag;
1099 uchar cdb_len;
1100 uchar tag_code;
1101 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102} ASC_SCSIQ_2;
1103
1104typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001105 uchar done_stat;
1106 uchar host_stat;
1107 uchar scsi_stat;
1108 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109} ASC_SCSIQ_3;
1110
1111typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001112 uchar cdb[ASC_MAX_CDB_LEN];
1113 uchar y_first_sg_list_qp;
1114 uchar y_working_sg_qp;
1115 uchar y_working_sg_ix;
1116 uchar y_res;
1117 ushort x_req_count;
1118 ushort x_reconnect_rtn;
1119 ASC_PADDR x_saved_data_addr;
1120 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121} ASC_SCSIQ_4;
1122
1123typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001124 ASC_SCSIQ_2 d2;
1125 ASC_SCSIQ_3 d3;
1126 uchar q_status;
1127 uchar q_no;
1128 uchar cntl;
1129 uchar sense_len;
1130 uchar extra_bytes;
1131 uchar res;
1132 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133} ASC_QDONE_INFO;
1134
1135typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001136 ASC_PADDR addr;
1137 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138} ASC_SG_LIST;
1139
1140typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001141 ushort entry_cnt;
1142 ushort queue_cnt;
1143 ushort entry_to_copy;
1144 ushort res;
1145 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146} ASC_SG_HEAD;
1147
1148#define ASC_MIN_SG_LIST 2
1149
1150typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001151 ushort entry_cnt;
1152 ushort queue_cnt;
1153 ushort entry_to_copy;
1154 ushort res;
1155 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156} ASC_MIN_SG_HEAD;
1157
1158#define QCX_SORT (0x0001)
1159#define QCX_COALEASE (0x0002)
1160
1161typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001162 ASC_SCSIQ_1 q1;
1163 ASC_SCSIQ_2 q2;
1164 uchar *cdbptr;
1165 ASC_SG_HEAD *sg_head;
1166 ushort remain_sg_entry_cnt;
1167 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168} ASC_SCSI_Q;
1169
1170typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001171 ASC_SCSIQ_1 r1;
1172 ASC_SCSIQ_2 r2;
1173 uchar *cdbptr;
1174 ASC_SG_HEAD *sg_head;
1175 uchar *sense_ptr;
1176 ASC_SCSIQ_3 r3;
1177 uchar cdb[ASC_MAX_CDB_LEN];
1178 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179} ASC_SCSI_REQ_Q;
1180
1181typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001182 ASC_SCSIQ_1 r1;
1183 ASC_SCSIQ_2 r2;
1184 uchar *cdbptr;
1185 ASC_SG_HEAD *sg_head;
1186 uchar *sense_ptr;
1187 ASC_SCSIQ_3 r3;
1188 uchar cdb[ASC_MAX_CDB_LEN];
1189 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190} ASC_SCSI_BIOS_REQ_Q;
1191
1192typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001193 uchar fwd;
1194 uchar bwd;
1195 ASC_SCSIQ_1 i1;
1196 ASC_SCSIQ_2 i2;
1197 ASC_SCSIQ_3 i3;
1198 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199} ASC_RISC_Q;
1200
1201typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001202 uchar seq_no;
1203 uchar q_no;
1204 uchar cntl;
1205 uchar sg_head_qp;
1206 uchar sg_list_cnt;
1207 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208} ASC_SG_LIST_Q;
1209
1210typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001211 uchar fwd;
1212 uchar bwd;
1213 ASC_SG_LIST_Q sg;
1214 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215} ASC_RISC_SG_LIST_Q;
1216
1217#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1218#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1219#define ASCQ_ERR_NO_ERROR 0
1220#define ASCQ_ERR_IO_NOT_FOUND 1
1221#define ASCQ_ERR_LOCAL_MEM 2
1222#define ASCQ_ERR_CHKSUM 3
1223#define ASCQ_ERR_START_CHIP 4
1224#define ASCQ_ERR_INT_TARGET_ID 5
1225#define ASCQ_ERR_INT_LOCAL_MEM 6
1226#define ASCQ_ERR_HALT_RISC 7
1227#define ASCQ_ERR_GET_ASPI_ENTRY 8
1228#define ASCQ_ERR_CLOSE_ASPI 9
1229#define ASCQ_ERR_HOST_INQUIRY 0x0A
1230#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1231#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1232#define ASCQ_ERR_Q_STATUS 0x0D
1233#define ASCQ_ERR_WR_SCSIQ 0x0E
1234#define ASCQ_ERR_PC_ADDR 0x0F
1235#define ASCQ_ERR_SYN_OFFSET 0x10
1236#define ASCQ_ERR_SYN_XFER_TIME 0x11
1237#define ASCQ_ERR_LOCK_DMA 0x12
1238#define ASCQ_ERR_UNLOCK_DMA 0x13
1239#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1240#define ASCQ_ERR_MICRO_CODE_HALT 0x15
1241#define ASCQ_ERR_SET_LRAM_ADDR 0x16
1242#define ASCQ_ERR_CUR_QNG 0x17
1243#define ASCQ_ERR_SG_Q_LINKS 0x18
1244#define ASCQ_ERR_SCSIQ_PTR 0x19
1245#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1246#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1247#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1248#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1249#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1250#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1251#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1252#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1253#define ASCQ_ERR_SEND_SCSI_Q 0x22
1254#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1255#define ASCQ_ERR_RESET_SDTR 0x24
1256
1257/*
1258 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
1259 */
1260#define ASC_WARN_NO_ERROR 0x0000
1261#define ASC_WARN_IO_PORT_ROTATE 0x0001
1262#define ASC_WARN_EEPROM_CHKSUM 0x0002
1263#define ASC_WARN_IRQ_MODIFIED 0x0004
1264#define ASC_WARN_AUTO_CONFIG 0x0008
1265#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1266#define ASC_WARN_EEPROM_RECOVER 0x0020
1267#define ASC_WARN_CFG_MSW_RECOVER 0x0040
1268#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
1269
1270/*
1271 * Error code values are set in ASC_DVC_VAR 'err_code'.
1272 */
1273#define ASC_IERR_WRITE_EEPROM 0x0001
1274#define ASC_IERR_MCODE_CHKSUM 0x0002
1275#define ASC_IERR_SET_PC_ADDR 0x0004
1276#define ASC_IERR_START_STOP_CHIP 0x0008
1277#define ASC_IERR_IRQ_NO 0x0010
1278#define ASC_IERR_SET_IRQ_NO 0x0020
1279#define ASC_IERR_CHIP_VERSION 0x0040
1280#define ASC_IERR_SET_SCSI_ID 0x0080
1281#define ASC_IERR_GET_PHY_ADDR 0x0100
1282#define ASC_IERR_BAD_SIGNATURE 0x0200
1283#define ASC_IERR_NO_BUS_TYPE 0x0400
1284#define ASC_IERR_SCAM 0x0800
1285#define ASC_IERR_SET_SDTR 0x1000
1286#define ASC_IERR_RW_LRAM 0x8000
1287
1288#define ASC_DEF_IRQ_NO 10
1289#define ASC_MAX_IRQ_NO 15
1290#define ASC_MIN_IRQ_NO 10
1291#define ASC_MIN_REMAIN_Q (0x02)
1292#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
1293#define ASC_MIN_TAG_Q_PER_DVC (0x04)
1294#define ASC_DEF_TAG_Q_PER_DVC (0x04)
1295#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1296#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
1297#define ASC_MAX_TOTAL_QNG 240
1298#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
1299#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
1300#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1301#define ASC_MAX_INRAM_TAG_QNG 16
1302#define ASC_IOADR_TABLE_MAX_IX 11
1303#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304#define ASC_LIB_SCSIQ_WK_SP 256
1305#define ASC_MAX_SYN_XFER_NO 16
1306#define ASC_SYN_MAX_OFFSET 0x0F
1307#define ASC_DEF_SDTR_OFFSET 0x0F
1308#define ASC_DEF_SDTR_INDEX 0x00
1309#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
1310#define SYN_XFER_NS_0 25
1311#define SYN_XFER_NS_1 30
1312#define SYN_XFER_NS_2 35
1313#define SYN_XFER_NS_3 40
1314#define SYN_XFER_NS_4 50
1315#define SYN_XFER_NS_5 60
1316#define SYN_XFER_NS_6 70
1317#define SYN_XFER_NS_7 85
1318#define SYN_ULTRA_XFER_NS_0 12
1319#define SYN_ULTRA_XFER_NS_1 19
1320#define SYN_ULTRA_XFER_NS_2 25
1321#define SYN_ULTRA_XFER_NS_3 32
1322#define SYN_ULTRA_XFER_NS_4 38
1323#define SYN_ULTRA_XFER_NS_5 44
1324#define SYN_ULTRA_XFER_NS_6 50
1325#define SYN_ULTRA_XFER_NS_7 57
1326#define SYN_ULTRA_XFER_NS_8 63
1327#define SYN_ULTRA_XFER_NS_9 69
1328#define SYN_ULTRA_XFER_NS_10 75
1329#define SYN_ULTRA_XFER_NS_11 82
1330#define SYN_ULTRA_XFER_NS_12 88
1331#define SYN_ULTRA_XFER_NS_13 94
1332#define SYN_ULTRA_XFER_NS_14 100
1333#define SYN_ULTRA_XFER_NS_15 107
1334
1335typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001336 uchar msg_type;
1337 uchar msg_len;
1338 uchar msg_req;
1339 union {
1340 struct {
1341 uchar sdtr_xfer_period;
1342 uchar sdtr_req_ack_offset;
1343 } sdtr;
1344 struct {
1345 uchar wdtr_width;
1346 } wdtr;
1347 struct {
1348 uchar mdp_b3;
1349 uchar mdp_b2;
1350 uchar mdp_b1;
1351 uchar mdp_b0;
1352 } mdp;
1353 } u_ext_msg;
1354 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355} EXT_MSG;
1356
1357#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
1358#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
1359#define wdtr_width u_ext_msg.wdtr.wdtr_width
1360#define mdp_b3 u_ext_msg.mdp_b3
1361#define mdp_b2 u_ext_msg.mdp_b2
1362#define mdp_b1 u_ext_msg.mdp_b1
1363#define mdp_b0 u_ext_msg.mdp_b0
1364
1365typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001366 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1367 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1368 ASC_SCSI_BIT_ID_TYPE disc_enable;
1369 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
1370 uchar chip_scsi_id;
1371 uchar isa_dma_speed;
1372 uchar isa_dma_channel;
1373 uchar chip_version;
1374 ushort lib_serial_no;
1375 ushort lib_version;
1376 ushort mcode_date;
1377 ushort mcode_version;
1378 uchar max_tag_qng[ASC_MAX_TID + 1];
1379 uchar *overrun_buf;
1380 uchar sdtr_period_offset[ASC_MAX_TID + 1];
1381 ushort pci_slot_info;
1382 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383} ASC_DVC_CFG;
1384
1385#define ASC_DEF_DVC_CNTL 0xFFFF
1386#define ASC_DEF_CHIP_SCSI_ID 7
1387#define ASC_DEF_ISA_DMA_SPEED 4
1388#define ASC_INIT_STATE_NULL 0x0000
1389#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1390#define ASC_INIT_STATE_END_GET_CFG 0x0002
1391#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1392#define ASC_INIT_STATE_END_SET_CFG 0x0008
1393#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1394#define ASC_INIT_STATE_END_LOAD_MC 0x0020
1395#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1396#define ASC_INIT_STATE_END_INQUIRY 0x0080
1397#define ASC_INIT_RESET_SCSI_DONE 0x0100
1398#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
1400#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
1401#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1402#define ASC_MIN_TAGGED_CMD 7
1403#define ASC_MAX_SCSI_RESET_WAIT 30
1404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001405struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001408 PortAddr iop_base;
1409 ushort err_code;
1410 ushort dvc_cntl;
1411 ushort bug_fix_cntl;
1412 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001413 ASC_SCSI_BIT_ID_TYPE init_sdtr;
1414 ASC_SCSI_BIT_ID_TYPE sdtr_done;
1415 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1416 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1417 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1418 ASC_SCSI_BIT_ID_TYPE start_motor;
1419 uchar scsi_reset_wait;
1420 uchar chip_no;
1421 char is_in_int;
1422 uchar max_total_qng;
1423 uchar cur_total_qng;
1424 uchar in_critical_cnt;
1425 uchar irq_no;
1426 uchar last_q_shortage;
1427 ushort init_state;
1428 uchar cur_dvc_qng[ASC_MAX_TID + 1];
1429 uchar max_dvc_qng[ASC_MAX_TID + 1];
1430 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
1431 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
1432 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
1433 ASC_DVC_CFG *cfg;
1434 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
1435 char redo_scam;
1436 ushort res2;
1437 uchar dos_int13_table[ASC_MAX_TID + 1];
1438 ASC_DCNT max_dma_count;
1439 ASC_SCSI_BIT_ID_TYPE no_scam;
1440 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1441 uchar max_sdtr_index;
1442 uchar host_init_sdtr_index;
1443 struct asc_board *drv_ptr;
1444 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445} ASC_DVC_VAR;
1446
1447typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001448 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449} ASC_DVC_INQ_INFO;
1450
1451typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001452 ASC_DCNT lba;
1453 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454} ASC_CAP_INFO;
1455
1456typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001457 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458} ASC_CAP_INFO_ARRAY;
1459
1460#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
1461#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
1462#define ASC_CNTL_INITIATOR (ushort)0x0001
1463#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
1464#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
1465#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
1466#define ASC_CNTL_NO_SCAM (ushort)0x0010
1467#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
1468#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
1469#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
1470#define ASC_CNTL_RESET_SCSI (ushort)0x0200
1471#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
1472#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
1473#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
1474#define ASC_CNTL_BURST_MODE (ushort)0x2000
1475#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
1476#define ASC_EEP_DVC_CFG_BEG_VL 2
1477#define ASC_EEP_MAX_DVC_ADDR_VL 15
1478#define ASC_EEP_DVC_CFG_BEG 32
1479#define ASC_EEP_MAX_DVC_ADDR 45
1480#define ASC_EEP_DEFINED_WORDS 10
1481#define ASC_EEP_MAX_ADDR 63
1482#define ASC_EEP_RES_WORDS 0
1483#define ASC_EEP_MAX_RETRY 20
1484#define ASC_MAX_INIT_BUSY_RETRY 8
1485#define ASC_EEP_ISA_PNP_WSIZE 16
1486
1487/*
1488 * These macros keep the chip SCSI id and ISA DMA speed
1489 * bitfields in board order. C bitfields aren't portable
1490 * between big and little-endian platforms so they are
1491 * not used.
1492 */
1493
1494#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
1495#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
1496#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
1497 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
1498#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
1499 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
1500
1501typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001502 ushort cfg_lsw;
1503 ushort cfg_msw;
1504 uchar init_sdtr;
1505 uchar disc_enable;
1506 uchar use_cmd_qng;
1507 uchar start_motor;
1508 uchar max_total_qng;
1509 uchar max_tag_qng;
1510 uchar bios_scan;
1511 uchar power_up_wait;
1512 uchar no_scam;
1513 uchar id_speed; /* low order 4 bits is chip scsi id */
1514 /* high order 4 bits is isa dma speed */
1515 uchar dos_int13_table[ASC_MAX_TID + 1];
1516 uchar adapter_info[6];
1517 ushort cntl;
1518 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519} ASCEEP_CONFIG;
1520
1521#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
1522#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
1523#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
1524
1525#define ASC_EEP_CMD_READ 0x80
1526#define ASC_EEP_CMD_WRITE 0x40
1527#define ASC_EEP_CMD_WRITE_ABLE 0x30
1528#define ASC_EEP_CMD_WRITE_DISABLE 0x00
1529#define ASC_OVERRUN_BSIZE 0x00000048UL
1530#define ASC_CTRL_BREAK_ONCE 0x0001
1531#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
1532#define ASCV_MSGOUT_BEG 0x0000
1533#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1534#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1535#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
1536#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1537#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1538#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1539#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1540#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1541#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
1542#define ASCV_BREAK_ADDR (ushort)0x0028
1543#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
1544#define ASCV_BREAK_CONTROL (ushort)0x002C
1545#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
1546
1547#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
1548#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
1549#define ASCV_MCODE_SIZE_W (ushort)0x0034
1550#define ASCV_STOP_CODE_B (ushort)0x0036
1551#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
1552#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
1553#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
1554#define ASCV_HALTCODE_W (ushort)0x0040
1555#define ASCV_CHKSUM_W (ushort)0x0042
1556#define ASCV_MC_DATE_W (ushort)0x0044
1557#define ASCV_MC_VER_W (ushort)0x0046
1558#define ASCV_NEXTRDY_B (ushort)0x0048
1559#define ASCV_DONENEXT_B (ushort)0x0049
1560#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
1561#define ASCV_SCSIBUSY_B (ushort)0x004B
1562#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
1563#define ASCV_CURCDB_B (ushort)0x004D
1564#define ASCV_RCLUN_B (ushort)0x004E
1565#define ASCV_BUSY_QHEAD_B (ushort)0x004F
1566#define ASCV_DISC1_QHEAD_B (ushort)0x0050
1567#define ASCV_DISC_ENABLE_B (ushort)0x0052
1568#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
1569#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
1570#define ASCV_MCODE_CNTL_B (ushort)0x0056
1571#define ASCV_NULL_TARGET_B (ushort)0x0057
1572#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
1573#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
1574#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
1575#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
1576#define ASCV_HOST_FLAG_B (ushort)0x005D
1577#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
1578#define ASCV_VER_SERIAL_B (ushort)0x0065
1579#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
1580#define ASCV_WTM_FLAG_B (ushort)0x0068
1581#define ASCV_RISC_FLAG_B (ushort)0x006A
1582#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
1583#define ASC_HOST_FLAG_IN_ISR 0x01
1584#define ASC_HOST_FLAG_ACK_INT 0x02
1585#define ASC_RISC_FLAG_GEN_INT 0x01
1586#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1587#define IOP_CTRL (0x0F)
1588#define IOP_STATUS (0x0E)
1589#define IOP_INT_ACK IOP_STATUS
1590#define IOP_REG_IFC (0x0D)
1591#define IOP_SYN_OFFSET (0x0B)
1592#define IOP_EXTRA_CONTROL (0x0D)
1593#define IOP_REG_PC (0x0C)
1594#define IOP_RAM_ADDR (0x0A)
1595#define IOP_RAM_DATA (0x08)
1596#define IOP_EEP_DATA (0x06)
1597#define IOP_EEP_CMD (0x07)
1598#define IOP_VERSION (0x03)
1599#define IOP_CONFIG_HIGH (0x04)
1600#define IOP_CONFIG_LOW (0x02)
1601#define IOP_SIG_BYTE (0x01)
1602#define IOP_SIG_WORD (0x00)
1603#define IOP_REG_DC1 (0x0E)
1604#define IOP_REG_DC0 (0x0C)
1605#define IOP_REG_SB (0x0B)
1606#define IOP_REG_DA1 (0x0A)
1607#define IOP_REG_DA0 (0x08)
1608#define IOP_REG_SC (0x09)
1609#define IOP_DMA_SPEED (0x07)
1610#define IOP_REG_FLAG (0x07)
1611#define IOP_FIFO_H (0x06)
1612#define IOP_FIFO_L (0x04)
1613#define IOP_REG_ID (0x05)
1614#define IOP_REG_QP (0x03)
1615#define IOP_REG_IH (0x02)
1616#define IOP_REG_IX (0x01)
1617#define IOP_REG_AX (0x00)
1618#define IFC_REG_LOCK (0x00)
1619#define IFC_REG_UNLOCK (0x09)
1620#define IFC_WR_EN_FILTER (0x10)
1621#define IFC_RD_NO_EEPROM (0x10)
1622#define IFC_SLEW_RATE (0x20)
1623#define IFC_ACT_NEG (0x40)
1624#define IFC_INP_FILTER (0x80)
1625#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
1626#define SC_SEL (uchar)(0x80)
1627#define SC_BSY (uchar)(0x40)
1628#define SC_ACK (uchar)(0x20)
1629#define SC_REQ (uchar)(0x10)
1630#define SC_ATN (uchar)(0x08)
1631#define SC_IO (uchar)(0x04)
1632#define SC_CD (uchar)(0x02)
1633#define SC_MSG (uchar)(0x01)
1634#define SEC_SCSI_CTL (uchar)(0x80)
1635#define SEC_ACTIVE_NEGATE (uchar)(0x40)
1636#define SEC_SLEW_RATE (uchar)(0x20)
1637#define SEC_ENABLE_FILTER (uchar)(0x10)
1638#define ASC_HALT_EXTMSG_IN (ushort)0x8000
1639#define ASC_HALT_CHK_CONDITION (ushort)0x8100
1640#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
1641#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
1642#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
1643#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
1644#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
1645#define ASC_MAX_QNO 0xF8
1646#define ASC_DATA_SEC_BEG (ushort)0x0080
1647#define ASC_DATA_SEC_END (ushort)0x0080
1648#define ASC_CODE_SEC_BEG (ushort)0x0080
1649#define ASC_CODE_SEC_END (ushort)0x0080
1650#define ASC_QADR_BEG (0x4000)
1651#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
1652#define ASC_QADR_END (ushort)0x7FFF
1653#define ASC_QLAST_ADR (ushort)0x7FC0
1654#define ASC_QBLK_SIZE 0x40
1655#define ASC_BIOS_DATA_QBEG 0xF8
1656#define ASC_MIN_ACTIVE_QNO 0x01
1657#define ASC_QLINK_END 0xFF
1658#define ASC_EEPROM_WORDS 0x10
1659#define ASC_MAX_MGS_LEN 0x10
1660#define ASC_BIOS_ADDR_DEF 0xDC00
1661#define ASC_BIOS_SIZE 0x3800
1662#define ASC_BIOS_RAM_OFF 0x3800
1663#define ASC_BIOS_RAM_SIZE 0x800
1664#define ASC_BIOS_MIN_ADDR 0xC000
1665#define ASC_BIOS_MAX_ADDR 0xEC00
1666#define ASC_BIOS_BANK_SIZE 0x0400
1667#define ASC_MCODE_START_ADDR 0x0080
1668#define ASC_CFG0_HOST_INT_ON 0x0020
1669#define ASC_CFG0_BIOS_ON 0x0040
1670#define ASC_CFG0_VERA_BURST_ON 0x0080
1671#define ASC_CFG0_SCSI_PARITY_ON 0x0800
1672#define ASC_CFG1_SCSI_TARGET_ON 0x0080
1673#define ASC_CFG1_LRAM_8BITS_ON 0x0800
1674#define ASC_CFG_MSW_CLR_MASK 0x3080
1675#define CSW_TEST1 (ASC_CS_TYPE)0x8000
1676#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
1677#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
1678#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
1679#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
1680#define CSW_TEST2 (ASC_CS_TYPE)0x0400
1681#define CSW_TEST3 (ASC_CS_TYPE)0x0200
1682#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
1683#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
1684#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
1685#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
1686#define CSW_HALTED (ASC_CS_TYPE)0x0010
1687#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
1688#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
1689#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
1690#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
1691#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
1692#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
1693#define CIW_TEST1 (ASC_CS_TYPE)0x0200
1694#define CIW_TEST2 (ASC_CS_TYPE)0x0400
1695#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
1696#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
1697#define CC_CHIP_RESET (uchar)0x80
1698#define CC_SCSI_RESET (uchar)0x40
1699#define CC_HALT (uchar)0x20
1700#define CC_SINGLE_STEP (uchar)0x10
1701#define CC_DMA_ABLE (uchar)0x08
1702#define CC_TEST (uchar)0x04
1703#define CC_BANK_ONE (uchar)0x02
1704#define CC_DIAG (uchar)0x01
1705#define ASC_1000_ID0W 0x04C1
1706#define ASC_1000_ID0W_FIX 0x00C1
1707#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708#define ASC_EISA_REV_IOP_MASK (0x0C83)
1709#define ASC_EISA_PID_IOP_MASK (0x0C80)
1710#define ASC_EISA_CFG_IOP_MASK (0x0C86)
1711#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712#define INS_HALTINT (ushort)0x6281
1713#define INS_HALT (ushort)0x6280
1714#define INS_SINT (ushort)0x6200
1715#define INS_RFLAG_WTM (ushort)0x7380
1716#define ASC_MC_SAVE_CODE_WSIZE 0x500
1717#define ASC_MC_SAVE_DATA_WSIZE 0x40
1718
1719typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001720 ushort data[ASC_MC_SAVE_DATA_WSIZE];
1721 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722} ASC_MC_SAVED;
1723
1724#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
1725#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1726#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1727#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1728#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1729#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1730#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1731#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1732#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1733#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1734#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1735#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1736#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1737#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1738#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1739#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1740#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1741#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1742#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1743#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1744#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1745#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1746#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1747#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1748#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1749#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1750#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1751#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1752#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1753#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1754#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1755#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1756#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1757#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1758#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1759#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1760#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1761#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1762#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1763#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1764#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1765#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1766#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1767#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1768#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1769#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1770#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1771#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1772#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1773#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1774#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1775#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1776#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1777#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1778#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1779#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1780#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1781#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1782#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1783#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1784#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1785#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1786#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1787#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1788#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1789#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1790#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1791#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1792
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001793static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1794static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1795static void AscWaitEEPRead(void);
1796static void AscWaitEEPWrite(void);
1797static ushort AscReadEEPWord(PortAddr, uchar);
1798static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1799static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1800static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1801static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1802static int AscStartChip(PortAddr);
1803static int AscStopChip(PortAddr);
1804static void AscSetChipIH(PortAddr, ushort);
1805static int AscIsChipHalted(PortAddr);
1806static void AscAckInterrupt(PortAddr);
1807static void AscDisableInterrupt(PortAddr);
1808static void AscEnableInterrupt(PortAddr);
1809static void AscSetBank(PortAddr, uchar);
1810static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001812static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001814static uchar AscReadLramByte(PortAddr, ushort);
1815static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001817static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001819static void AscWriteLramWord(PortAddr, ushort, ushort);
1820static void AscWriteLramByte(PortAddr, ushort, uchar);
1821static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1822static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1823static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1824static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1825static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1826static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1827static ushort AscInitFromEEP(ASC_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001828static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1829static int AscTestExternalLram(ASC_DVC_VAR *);
1830static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1831static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1832static void AscSetChipSDTR(PortAddr, uchar, uchar);
1833static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1834static uchar AscAllocFreeQueue(PortAddr, uchar);
1835static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1836static int AscHostReqRiscHalt(PortAddr);
1837static int AscStopQueueExe(PortAddr);
1838static int AscSendScsiQueue(ASC_DVC_VAR *,
1839 ASC_SCSI_Q *scsiq, uchar n_q_required);
1840static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1841static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1842static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1843static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1844static ushort AscInitLram(ASC_DVC_VAR *);
1845static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1846static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1847static int AscIsrChipHalted(ASC_DVC_VAR *);
1848static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1849 ASC_QDONE_INFO *, ASC_DCNT);
1850static int AscIsrQDone(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001852static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001854static uchar AscGetChipScsiCtrl(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001855static uchar AscGetChipVersion(PortAddr, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001856static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001857static void AscToggleIRQAct(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001858static inline ulong DvcEnterCritical(void);
1859static inline void DvcLeaveCritical(ulong);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001860static void DvcSleepMilliSecond(ASC_DCNT);
1861static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1862static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1863static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001864static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04001865static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001866static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1867static int AscISR(ASC_DVC_VAR *);
1868static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1869static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001871static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001873static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
1875/*
1876 * --- Adv Library Constants and Macros
1877 */
1878
1879#define ADV_LIB_VERSION_MAJOR 5
1880#define ADV_LIB_VERSION_MINOR 14
1881
1882/*
1883 * Define Adv Library required special types.
1884 */
1885
1886/*
1887 * Portable Data Types
1888 *
1889 * Any instance where a 32-bit long or pointer type is assumed
1890 * for precision or HW defined structures, the following define
1891 * types must be used. In Linux the char, short, and int types
1892 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1893 * and long types are 64 bits on Alpha and UltraSPARC.
1894 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001895#define ADV_PADDR __u32 /* Physical address data type. */
1896#define ADV_VADDR __u32 /* Virtual address data type. */
1897#define ADV_DCNT __u32 /* Unsigned Data count type. */
1898#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900/*
1901 * These macros are used to convert a virtual address to a
1902 * 32-bit value. This currently can be used on Linux Alpha
1903 * which uses 64-bit virtual address but a 32-bit bus address.
1904 * This is likely to break in the future, but doing this now
1905 * will give us time to change the HW and FW to handle 64-bit
1906 * addresses.
1907 */
1908#define ADV_VADDR_TO_U32 virt_to_bus
1909#define ADV_U32_TO_VADDR bus_to_virt
1910
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001911#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913/*
1914 * Define Adv Library required memory access macros.
1915 */
1916#define ADV_MEM_READB(addr) readb(addr)
1917#define ADV_MEM_READW(addr) readw(addr)
1918#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1919#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1920#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1921
1922#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1923
1924/*
1925 * For wide boards a CDB length maximum of 16 bytes
1926 * is supported.
1927 */
1928#define ADV_MAX_CDB_LEN 16
1929
1930/*
1931 * Define total number of simultaneous maximum element scatter-gather
1932 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1933 * maximum number of outstanding commands per wide host adapter. Each
1934 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1935 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1936 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1937 * structures or 255 scatter-gather elements.
1938 *
1939 */
1940#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1941
1942/*
1943 * Define Adv Library required maximum number of scatter-gather
1944 * elements per request.
1945 */
1946#define ADV_MAX_SG_LIST 255
1947
1948/* Number of SG blocks needed. */
1949#define ADV_NUM_SG_BLOCK \
1950 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1951
1952/* Total contiguous memory needed for SG blocks. */
1953#define ADV_SG_TOTAL_MEM_SIZE \
1954 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1955
1956#define ADV_PAGE_SIZE PAGE_SIZE
1957
1958#define ADV_NUM_PAGE_CROSSING \
1959 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1962#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001963#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1965
1966#define ADV_EEP_DELAY_MS 100
1967
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001968#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1969#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970/*
1971 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1972 * For later ICs Bit 13 controls whether the CIS (Card Information
1973 * Service Section) is loaded from EEPROM.
1974 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001975#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1976#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977/*
1978 * ASC38C1600 Bit 11
1979 *
1980 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1981 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1982 * Function 0 will specify INT B.
1983 *
1984 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1985 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1986 * Function 1 will specify INT A.
1987 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001988#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001990typedef struct adveep_3550_config {
1991 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001993 ushort cfg_lsw; /* 00 power up initialization */
1994 /* bit 13 set - Term Polarity Control */
1995 /* bit 14 set - BIOS Enable */
1996 /* bit 15 set - Big Endian Mode */
1997 ushort cfg_msw; /* 01 unused */
1998 ushort disc_enable; /* 02 disconnect enable */
1999 ushort wdtr_able; /* 03 Wide DTR able */
2000 ushort sdtr_able; /* 04 Synchronous DTR able */
2001 ushort start_motor; /* 05 send start up motor */
2002 ushort tagqng_able; /* 06 tag queuing able */
2003 ushort bios_scan; /* 07 BIOS device control */
2004 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002006 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2007 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002009 uchar scsi_reset_delay; /* 10 reset delay */
2010 uchar bios_id_lun; /* first boot device scsi id & lun */
2011 /* high nibble is lun */
2012 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002014 uchar termination; /* 11 0 - automatic */
2015 /* 1 - low off / high off */
2016 /* 2 - low off / high on */
2017 /* 3 - low on / high on */
2018 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002020 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002022 ushort bios_ctrl; /* 12 BIOS control bits */
2023 /* bit 0 BIOS don't act as initiator. */
2024 /* bit 1 BIOS > 1 GB support */
2025 /* bit 2 BIOS > 2 Disk Support */
2026 /* bit 3 BIOS don't support removables */
2027 /* bit 4 BIOS support bootable CD */
2028 /* bit 5 BIOS scan enabled */
2029 /* bit 6 BIOS support multiple LUNs */
2030 /* bit 7 BIOS display of message */
2031 /* bit 8 SCAM disabled */
2032 /* bit 9 Reset SCSI bus during init. */
2033 /* bit 10 */
2034 /* bit 11 No verbose initialization. */
2035 /* bit 12 SCSI parity enabled */
2036 /* bit 13 */
2037 /* bit 14 */
2038 /* bit 15 */
2039 ushort ultra_able; /* 13 ULTRA speed able */
2040 ushort reserved2; /* 14 reserved */
2041 uchar max_host_qng; /* 15 maximum host queuing */
2042 uchar max_dvc_qng; /* maximum per device queuing */
2043 ushort dvc_cntl; /* 16 control bit for driver */
2044 ushort bug_fix; /* 17 control bit for bug fix */
2045 ushort serial_number_word1; /* 18 Board serial number word 1 */
2046 ushort serial_number_word2; /* 19 Board serial number word 2 */
2047 ushort serial_number_word3; /* 20 Board serial number word 3 */
2048 ushort check_sum; /* 21 EEP check sum */
2049 uchar oem_name[16]; /* 22 OEM name */
2050 ushort dvc_err_code; /* 30 last device driver error code */
2051 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2052 ushort adv_err_addr; /* 32 last uc error address */
2053 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2054 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2055 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2056 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057} ADVEEP_3550_CONFIG;
2058
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002059typedef struct adveep_38C0800_config {
2060 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002062 ushort cfg_lsw; /* 00 power up initialization */
2063 /* bit 13 set - Load CIS */
2064 /* bit 14 set - BIOS Enable */
2065 /* bit 15 set - Big Endian Mode */
2066 ushort cfg_msw; /* 01 unused */
2067 ushort disc_enable; /* 02 disconnect enable */
2068 ushort wdtr_able; /* 03 Wide DTR able */
2069 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2070 ushort start_motor; /* 05 send start up motor */
2071 ushort tagqng_able; /* 06 tag queuing able */
2072 ushort bios_scan; /* 07 BIOS device control */
2073 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002075 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2076 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002078 uchar scsi_reset_delay; /* 10 reset delay */
2079 uchar bios_id_lun; /* first boot device scsi id & lun */
2080 /* high nibble is lun */
2081 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002083 uchar termination_se; /* 11 0 - automatic */
2084 /* 1 - low off / high off */
2085 /* 2 - low off / high on */
2086 /* 3 - low on / high on */
2087 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002089 uchar termination_lvd; /* 11 0 - automatic */
2090 /* 1 - low off / high off */
2091 /* 2 - low off / high on */
2092 /* 3 - low on / high on */
2093 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002095 ushort bios_ctrl; /* 12 BIOS control bits */
2096 /* bit 0 BIOS don't act as initiator. */
2097 /* bit 1 BIOS > 1 GB support */
2098 /* bit 2 BIOS > 2 Disk Support */
2099 /* bit 3 BIOS don't support removables */
2100 /* bit 4 BIOS support bootable CD */
2101 /* bit 5 BIOS scan enabled */
2102 /* bit 6 BIOS support multiple LUNs */
2103 /* bit 7 BIOS display of message */
2104 /* bit 8 SCAM disabled */
2105 /* bit 9 Reset SCSI bus during init. */
2106 /* bit 10 */
2107 /* bit 11 No verbose initialization. */
2108 /* bit 12 SCSI parity enabled */
2109 /* bit 13 */
2110 /* bit 14 */
2111 /* bit 15 */
2112 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2113 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2114 uchar max_host_qng; /* 15 maximum host queueing */
2115 uchar max_dvc_qng; /* maximum per device queuing */
2116 ushort dvc_cntl; /* 16 control bit for driver */
2117 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2118 ushort serial_number_word1; /* 18 Board serial number word 1 */
2119 ushort serial_number_word2; /* 19 Board serial number word 2 */
2120 ushort serial_number_word3; /* 20 Board serial number word 3 */
2121 ushort check_sum; /* 21 EEP check sum */
2122 uchar oem_name[16]; /* 22 OEM name */
2123 ushort dvc_err_code; /* 30 last device driver error code */
2124 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2125 ushort adv_err_addr; /* 32 last uc error address */
2126 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2127 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2128 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2129 ushort reserved36; /* 36 reserved */
2130 ushort reserved37; /* 37 reserved */
2131 ushort reserved38; /* 38 reserved */
2132 ushort reserved39; /* 39 reserved */
2133 ushort reserved40; /* 40 reserved */
2134 ushort reserved41; /* 41 reserved */
2135 ushort reserved42; /* 42 reserved */
2136 ushort reserved43; /* 43 reserved */
2137 ushort reserved44; /* 44 reserved */
2138 ushort reserved45; /* 45 reserved */
2139 ushort reserved46; /* 46 reserved */
2140 ushort reserved47; /* 47 reserved */
2141 ushort reserved48; /* 48 reserved */
2142 ushort reserved49; /* 49 reserved */
2143 ushort reserved50; /* 50 reserved */
2144 ushort reserved51; /* 51 reserved */
2145 ushort reserved52; /* 52 reserved */
2146 ushort reserved53; /* 53 reserved */
2147 ushort reserved54; /* 54 reserved */
2148 ushort reserved55; /* 55 reserved */
2149 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2150 ushort cisprt_msw; /* 57 CIS PTR MSW */
2151 ushort subsysvid; /* 58 SubSystem Vendor ID */
2152 ushort subsysid; /* 59 SubSystem ID */
2153 ushort reserved60; /* 60 reserved */
2154 ushort reserved61; /* 61 reserved */
2155 ushort reserved62; /* 62 reserved */
2156 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157} ADVEEP_38C0800_CONFIG;
2158
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002159typedef struct adveep_38C1600_config {
2160 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002162 ushort cfg_lsw; /* 00 power up initialization */
2163 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
2164 /* clear - Func. 0 INTA, Func. 1 INTB */
2165 /* bit 13 set - Load CIS */
2166 /* bit 14 set - BIOS Enable */
2167 /* bit 15 set - Big Endian Mode */
2168 ushort cfg_msw; /* 01 unused */
2169 ushort disc_enable; /* 02 disconnect enable */
2170 ushort wdtr_able; /* 03 Wide DTR able */
2171 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2172 ushort start_motor; /* 05 send start up motor */
2173 ushort tagqng_able; /* 06 tag queuing able */
2174 ushort bios_scan; /* 07 BIOS device control */
2175 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002177 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2178 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002180 uchar scsi_reset_delay; /* 10 reset delay */
2181 uchar bios_id_lun; /* first boot device scsi id & lun */
2182 /* high nibble is lun */
2183 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002185 uchar termination_se; /* 11 0 - automatic */
2186 /* 1 - low off / high off */
2187 /* 2 - low off / high on */
2188 /* 3 - low on / high on */
2189 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002191 uchar termination_lvd; /* 11 0 - automatic */
2192 /* 1 - low off / high off */
2193 /* 2 - low off / high on */
2194 /* 3 - low on / high on */
2195 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002197 ushort bios_ctrl; /* 12 BIOS control bits */
2198 /* bit 0 BIOS don't act as initiator. */
2199 /* bit 1 BIOS > 1 GB support */
2200 /* bit 2 BIOS > 2 Disk Support */
2201 /* bit 3 BIOS don't support removables */
2202 /* bit 4 BIOS support bootable CD */
2203 /* bit 5 BIOS scan enabled */
2204 /* bit 6 BIOS support multiple LUNs */
2205 /* bit 7 BIOS display of message */
2206 /* bit 8 SCAM disabled */
2207 /* bit 9 Reset SCSI bus during init. */
2208 /* bit 10 Basic Integrity Checking disabled */
2209 /* bit 11 No verbose initialization. */
2210 /* bit 12 SCSI parity enabled */
2211 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
2212 /* bit 14 */
2213 /* bit 15 */
2214 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2215 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2216 uchar max_host_qng; /* 15 maximum host queueing */
2217 uchar max_dvc_qng; /* maximum per device queuing */
2218 ushort dvc_cntl; /* 16 control bit for driver */
2219 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2220 ushort serial_number_word1; /* 18 Board serial number word 1 */
2221 ushort serial_number_word2; /* 19 Board serial number word 2 */
2222 ushort serial_number_word3; /* 20 Board serial number word 3 */
2223 ushort check_sum; /* 21 EEP check sum */
2224 uchar oem_name[16]; /* 22 OEM name */
2225 ushort dvc_err_code; /* 30 last device driver error code */
2226 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2227 ushort adv_err_addr; /* 32 last uc error address */
2228 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2229 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2230 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2231 ushort reserved36; /* 36 reserved */
2232 ushort reserved37; /* 37 reserved */
2233 ushort reserved38; /* 38 reserved */
2234 ushort reserved39; /* 39 reserved */
2235 ushort reserved40; /* 40 reserved */
2236 ushort reserved41; /* 41 reserved */
2237 ushort reserved42; /* 42 reserved */
2238 ushort reserved43; /* 43 reserved */
2239 ushort reserved44; /* 44 reserved */
2240 ushort reserved45; /* 45 reserved */
2241 ushort reserved46; /* 46 reserved */
2242 ushort reserved47; /* 47 reserved */
2243 ushort reserved48; /* 48 reserved */
2244 ushort reserved49; /* 49 reserved */
2245 ushort reserved50; /* 50 reserved */
2246 ushort reserved51; /* 51 reserved */
2247 ushort reserved52; /* 52 reserved */
2248 ushort reserved53; /* 53 reserved */
2249 ushort reserved54; /* 54 reserved */
2250 ushort reserved55; /* 55 reserved */
2251 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2252 ushort cisprt_msw; /* 57 CIS PTR MSW */
2253 ushort subsysvid; /* 58 SubSystem Vendor ID */
2254 ushort subsysid; /* 59 SubSystem ID */
2255 ushort reserved60; /* 60 reserved */
2256 ushort reserved61; /* 61 reserved */
2257 ushort reserved62; /* 62 reserved */
2258 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259} ADVEEP_38C1600_CONFIG;
2260
2261/*
2262 * EEPROM Commands
2263 */
2264#define ASC_EEP_CMD_DONE 0x0200
2265#define ASC_EEP_CMD_DONE_ERR 0x0001
2266
2267/* cfg_word */
2268#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
2269
2270/* bios_ctrl */
2271#define BIOS_CTRL_BIOS 0x0001
2272#define BIOS_CTRL_EXTENDED_XLAT 0x0002
2273#define BIOS_CTRL_GT_2_DISK 0x0004
2274#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
2275#define BIOS_CTRL_BOOTABLE_CD 0x0010
2276#define BIOS_CTRL_MULTIPLE_LUN 0x0040
2277#define BIOS_CTRL_DISPLAY_MSG 0x0080
2278#define BIOS_CTRL_NO_SCAM 0x0100
2279#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
2280#define BIOS_CTRL_INIT_VERBOSE 0x0800
2281#define BIOS_CTRL_SCSI_PARITY 0x1000
2282#define BIOS_CTRL_AIPP_DIS 0x2000
2283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002284#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002286#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
2288/*
2289 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
2290 * a special 16K Adv Library and Microcode version. After the issue is
2291 * resolved, should restore 32K support.
2292 *
2293 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
2294 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002295#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296
2297/*
2298 * Byte I/O register address from base of 'iop_base'.
2299 */
2300#define IOPB_INTR_STATUS_REG 0x00
2301#define IOPB_CHIP_ID_1 0x01
2302#define IOPB_INTR_ENABLES 0x02
2303#define IOPB_CHIP_TYPE_REV 0x03
2304#define IOPB_RES_ADDR_4 0x04
2305#define IOPB_RES_ADDR_5 0x05
2306#define IOPB_RAM_DATA 0x06
2307#define IOPB_RES_ADDR_7 0x07
2308#define IOPB_FLAG_REG 0x08
2309#define IOPB_RES_ADDR_9 0x09
2310#define IOPB_RISC_CSR 0x0A
2311#define IOPB_RES_ADDR_B 0x0B
2312#define IOPB_RES_ADDR_C 0x0C
2313#define IOPB_RES_ADDR_D 0x0D
2314#define IOPB_SOFT_OVER_WR 0x0E
2315#define IOPB_RES_ADDR_F 0x0F
2316#define IOPB_MEM_CFG 0x10
2317#define IOPB_RES_ADDR_11 0x11
2318#define IOPB_GPIO_DATA 0x12
2319#define IOPB_RES_ADDR_13 0x13
2320#define IOPB_FLASH_PAGE 0x14
2321#define IOPB_RES_ADDR_15 0x15
2322#define IOPB_GPIO_CNTL 0x16
2323#define IOPB_RES_ADDR_17 0x17
2324#define IOPB_FLASH_DATA 0x18
2325#define IOPB_RES_ADDR_19 0x19
2326#define IOPB_RES_ADDR_1A 0x1A
2327#define IOPB_RES_ADDR_1B 0x1B
2328#define IOPB_RES_ADDR_1C 0x1C
2329#define IOPB_RES_ADDR_1D 0x1D
2330#define IOPB_RES_ADDR_1E 0x1E
2331#define IOPB_RES_ADDR_1F 0x1F
2332#define IOPB_DMA_CFG0 0x20
2333#define IOPB_DMA_CFG1 0x21
2334#define IOPB_TICKLE 0x22
2335#define IOPB_DMA_REG_WR 0x23
2336#define IOPB_SDMA_STATUS 0x24
2337#define IOPB_SCSI_BYTE_CNT 0x25
2338#define IOPB_HOST_BYTE_CNT 0x26
2339#define IOPB_BYTE_LEFT_TO_XFER 0x27
2340#define IOPB_BYTE_TO_XFER_0 0x28
2341#define IOPB_BYTE_TO_XFER_1 0x29
2342#define IOPB_BYTE_TO_XFER_2 0x2A
2343#define IOPB_BYTE_TO_XFER_3 0x2B
2344#define IOPB_ACC_GRP 0x2C
2345#define IOPB_RES_ADDR_2D 0x2D
2346#define IOPB_DEV_ID 0x2E
2347#define IOPB_RES_ADDR_2F 0x2F
2348#define IOPB_SCSI_DATA 0x30
2349#define IOPB_RES_ADDR_31 0x31
2350#define IOPB_RES_ADDR_32 0x32
2351#define IOPB_SCSI_DATA_HSHK 0x33
2352#define IOPB_SCSI_CTRL 0x34
2353#define IOPB_RES_ADDR_35 0x35
2354#define IOPB_RES_ADDR_36 0x36
2355#define IOPB_RES_ADDR_37 0x37
2356#define IOPB_RAM_BIST 0x38
2357#define IOPB_PLL_TEST 0x39
2358#define IOPB_PCI_INT_CFG 0x3A
2359#define IOPB_RES_ADDR_3B 0x3B
2360#define IOPB_RFIFO_CNT 0x3C
2361#define IOPB_RES_ADDR_3D 0x3D
2362#define IOPB_RES_ADDR_3E 0x3E
2363#define IOPB_RES_ADDR_3F 0x3F
2364
2365/*
2366 * Word I/O register address from base of 'iop_base'.
2367 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002368#define IOPW_CHIP_ID_0 0x00 /* CID0 */
2369#define IOPW_CTRL_REG 0x02 /* CC */
2370#define IOPW_RAM_ADDR 0x04 /* LA */
2371#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002373#define IOPW_RISC_CSR 0x0A /* CSR */
2374#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
2375#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002377#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002379#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002381#define IOPW_EE_CMD 0x1A /* EC */
2382#define IOPW_EE_DATA 0x1C /* ED */
2383#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002385#define IOPW_Q_BASE 0x22 /* QB */
2386#define IOPW_QP 0x24 /* QP */
2387#define IOPW_IX 0x26 /* IX */
2388#define IOPW_SP 0x28 /* SP */
2389#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390#define IOPW_RES_ADDR_2C 0x2C
2391#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002392#define IOPW_SCSI_DATA 0x30 /* SD */
2393#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
2394#define IOPW_SCSI_CTRL 0x34 /* SC */
2395#define IOPW_HSHK_CFG 0x36 /* HCFG */
2396#define IOPW_SXFR_STATUS 0x36 /* SXS */
2397#define IOPW_SXFR_CNTL 0x38 /* SXL */
2398#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002400#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
2402/*
2403 * Doubleword I/O register address from base of 'iop_base'.
2404 */
2405#define IOPDW_RES_ADDR_0 0x00
2406#define IOPDW_RAM_DATA 0x04
2407#define IOPDW_RES_ADDR_8 0x08
2408#define IOPDW_RES_ADDR_C 0x0C
2409#define IOPDW_RES_ADDR_10 0x10
2410#define IOPDW_COMMA 0x14
2411#define IOPDW_COMMB 0x18
2412#define IOPDW_RES_ADDR_1C 0x1C
2413#define IOPDW_SDMA_ADDR0 0x20
2414#define IOPDW_SDMA_ADDR1 0x24
2415#define IOPDW_SDMA_COUNT 0x28
2416#define IOPDW_SDMA_ERROR 0x2C
2417#define IOPDW_RDMA_ADDR0 0x30
2418#define IOPDW_RDMA_ADDR1 0x34
2419#define IOPDW_RDMA_COUNT 0x38
2420#define IOPDW_RDMA_ERROR 0x3C
2421
2422#define ADV_CHIP_ID_BYTE 0x25
2423#define ADV_CHIP_ID_WORD 0x04C1
2424
2425#define ADV_SC_SCSI_BUS_RESET 0x2000
2426
2427#define ADV_INTR_ENABLE_HOST_INTR 0x01
2428#define ADV_INTR_ENABLE_SEL_INTR 0x02
2429#define ADV_INTR_ENABLE_DPR_INTR 0x04
2430#define ADV_INTR_ENABLE_RTA_INTR 0x08
2431#define ADV_INTR_ENABLE_RMA_INTR 0x10
2432#define ADV_INTR_ENABLE_RST_INTR 0x20
2433#define ADV_INTR_ENABLE_DPE_INTR 0x40
2434#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
2435
2436#define ADV_INTR_STATUS_INTRA 0x01
2437#define ADV_INTR_STATUS_INTRB 0x02
2438#define ADV_INTR_STATUS_INTRC 0x04
2439
2440#define ADV_RISC_CSR_STOP (0x0000)
2441#define ADV_RISC_TEST_COND (0x2000)
2442#define ADV_RISC_CSR_RUN (0x4000)
2443#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
2444
2445#define ADV_CTRL_REG_HOST_INTR 0x0100
2446#define ADV_CTRL_REG_SEL_INTR 0x0200
2447#define ADV_CTRL_REG_DPR_INTR 0x0400
2448#define ADV_CTRL_REG_RTA_INTR 0x0800
2449#define ADV_CTRL_REG_RMA_INTR 0x1000
2450#define ADV_CTRL_REG_RES_BIT14 0x2000
2451#define ADV_CTRL_REG_DPE_INTR 0x4000
2452#define ADV_CTRL_REG_POWER_DONE 0x8000
2453#define ADV_CTRL_REG_ANY_INTR 0xFF00
2454
2455#define ADV_CTRL_REG_CMD_RESET 0x00C6
2456#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
2457#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
2458#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
2459#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
2460
2461#define ADV_TICKLE_NOP 0x00
2462#define ADV_TICKLE_A 0x01
2463#define ADV_TICKLE_B 0x02
2464#define ADV_TICKLE_C 0x03
2465
2466#define ADV_SCSI_CTRL_RSTOUT 0x2000
2467
2468#define AdvIsIntPending(port) \
2469 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
2470
2471/*
2472 * SCSI_CFG0 Register bit definitions
2473 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002474#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
2475#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
2476#define EVEN_PARITY 0x1000 /* Select Even Parity */
2477#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
2478#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
2479#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
2480#define SCAM_EN 0x0080 /* Enable SCAM selection */
2481#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
2482#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
2483#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
2484#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
2486/*
2487 * SCSI_CFG1 Register bit definitions
2488 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002489#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
2490#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
2491#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
2492#define FILTER_SEL 0x0C00 /* Filter Period Selection */
2493#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
2494#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
2495#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
2496#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
2497#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
2498#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
2499#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
2500#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
2501#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
2502#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
2503#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
2505/*
2506 * Addendum for ASC-38C0800 Chip
2507 *
2508 * The ASC-38C1600 Chip uses the same definitions except that the
2509 * bus mode override bits [12:10] have been moved to byte register
2510 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
2511 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
2512 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
2513 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
2514 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
2515 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002516#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
2517#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
2518#define HVD 0x1000 /* HVD Device Detect */
2519#define LVD 0x0800 /* LVD Device Detect */
2520#define SE 0x0400 /* SE Device Detect */
2521#define TERM_LVD 0x00C0 /* LVD Termination Bits */
2522#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
2523#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
2524#define TERM_SE 0x0030 /* SE Termination Bits */
2525#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
2526#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
2527#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
2528#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
2529#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
2530#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
2531#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
2532#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533
2534#define CABLE_ILLEGAL_A 0x7
2535 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
2536
2537#define CABLE_ILLEGAL_B 0xB
2538 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
2539
2540/*
2541 * MEM_CFG Register bit definitions
2542 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002543#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
2544#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
2545#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
2546#define RAM_SZ_2KB 0x00 /* 2 KB */
2547#define RAM_SZ_4KB 0x04 /* 4 KB */
2548#define RAM_SZ_8KB 0x08 /* 8 KB */
2549#define RAM_SZ_16KB 0x0C /* 16 KB */
2550#define RAM_SZ_32KB 0x10 /* 32 KB */
2551#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
2553/*
2554 * DMA_CFG0 Register bit definitions
2555 *
2556 * This register is only accessible to the host.
2557 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002558#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
2559#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
2560#define FIFO_THRESH_16B 0x00 /* 16 bytes */
2561#define FIFO_THRESH_32B 0x20 /* 32 bytes */
2562#define FIFO_THRESH_48B 0x30 /* 48 bytes */
2563#define FIFO_THRESH_64B 0x40 /* 64 bytes */
2564#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
2565#define FIFO_THRESH_96B 0x60 /* 96 bytes */
2566#define FIFO_THRESH_112B 0x70 /* 112 bytes */
2567#define START_CTL 0x0C /* DMA start conditions */
2568#define START_CTL_TH 0x00 /* Wait threshold level (default) */
2569#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
2570#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
2571#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
2572#define READ_CMD 0x03 /* Memory Read Method */
2573#define READ_CMD_MR 0x00 /* Memory Read */
2574#define READ_CMD_MRL 0x02 /* Memory Read Long */
2575#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
2577/*
2578 * ASC-38C0800 RAM BIST Register bit definitions
2579 */
2580#define RAM_TEST_MODE 0x80
2581#define PRE_TEST_MODE 0x40
2582#define NORMAL_MODE 0x00
2583#define RAM_TEST_DONE 0x10
2584#define RAM_TEST_STATUS 0x0F
2585#define RAM_TEST_HOST_ERROR 0x08
2586#define RAM_TEST_INTRAM_ERROR 0x04
2587#define RAM_TEST_RISC_ERROR 0x02
2588#define RAM_TEST_SCSI_ERROR 0x01
2589#define RAM_TEST_SUCCESS 0x00
2590#define PRE_TEST_VALUE 0x05
2591#define NORMAL_VALUE 0x00
2592
2593/*
2594 * ASC38C1600 Definitions
2595 *
2596 * IOPB_PCI_INT_CFG Bit Field Definitions
2597 */
2598
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002599#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
2601/*
2602 * Bit 1 can be set to change the interrupt for the Function to operate in
2603 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
2604 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
2605 * mode, otherwise the operating mode is undefined.
2606 */
2607#define TOTEMPOLE 0x02
2608
2609/*
2610 * Bit 0 can be used to change the Int Pin for the Function. The value is
2611 * 0 by default for both Functions with Function 0 using INT A and Function
2612 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
2613 * INT A is used.
2614 *
2615 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
2616 * value specified in the PCI Configuration Space.
2617 */
2618#define INTAB 0x01
2619
2620/* a_advlib.h */
2621
2622/*
2623 * Adv Library Status Definitions
2624 */
2625#define ADV_TRUE 1
2626#define ADV_FALSE 0
2627#define ADV_NOERROR 1
2628#define ADV_SUCCESS 1
2629#define ADV_BUSY 0
2630#define ADV_ERROR (-1)
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632/*
2633 * ADV_DVC_VAR 'warn_code' values
2634 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002635#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
2636#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
2637#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
2638#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
2639#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002641#define ADV_MAX_TID 15 /* max. target identifier */
2642#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
2644/*
2645 * Error code values are set in ADV_DVC_VAR 'err_code'.
2646 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002647#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
2648#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
2649#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
2650#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
2651#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
2652#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
2653#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
2654#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
2655#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
2656#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
2657#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
2658#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
2659#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
2660#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
2662/*
2663 * Fixed locations of microcode operating variables.
2664 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002665#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
2666#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
2667#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
2668#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
2669#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
2670#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
2671#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
2672#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
2673#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
2674#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
2675#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
2676#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
2677#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678#define ASC_MC_CHIP_TYPE 0x009A
2679#define ASC_MC_INTRB_CODE 0x009B
2680#define ASC_MC_WDTR_ABLE 0x009C
2681#define ASC_MC_SDTR_ABLE 0x009E
2682#define ASC_MC_TAGQNG_ABLE 0x00A0
2683#define ASC_MC_DISC_ENABLE 0x00A2
2684#define ASC_MC_IDLE_CMD_STATUS 0x00A4
2685#define ASC_MC_IDLE_CMD 0x00A6
2686#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
2687#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
2688#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
2689#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
2690#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
2691#define ASC_MC_SDTR_DONE 0x00B6
2692#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
2693#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
2694#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002695#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002697#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698#define ASC_MC_ICQ 0x0160
2699#define ASC_MC_IRQ 0x0164
2700#define ASC_MC_PPR_ABLE 0x017A
2701
2702/*
2703 * BIOS LRAM variable absolute offsets.
2704 */
2705#define BIOS_CODESEG 0x54
2706#define BIOS_CODELEN 0x56
2707#define BIOS_SIGNATURE 0x58
2708#define BIOS_VERSION 0x5A
2709
2710/*
2711 * Microcode Control Flags
2712 *
2713 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
2714 * and handled by the microcode.
2715 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002716#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
2717#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
2719/*
2720 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
2721 */
2722#define HSHK_CFG_WIDE_XFR 0x8000
2723#define HSHK_CFG_RATE 0x0F00
2724#define HSHK_CFG_OFFSET 0x001F
2725
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002726#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
2727#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
2728#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
2729#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002731#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2732#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2733#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2734#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2735#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002737#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2738#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2739#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2740#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2741#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742/*
2743 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2744 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2745 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002746#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2747#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748
2749/*
2750 * All fields here are accessed by the board microcode and need to be
2751 * little-endian.
2752 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002753typedef struct adv_carr_t {
2754 ADV_VADDR carr_va; /* Carrier Virtual Address */
2755 ADV_PADDR carr_pa; /* Carrier Physical Address */
2756 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2757 /*
2758 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2759 *
2760 * next_vpa [3:1] Reserved Bits
2761 * next_vpa [0] Done Flag set in Response Queue.
2762 */
2763 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764} ADV_CARR_T;
2765
2766/*
2767 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2768 */
2769#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2770
2771#define ASC_RQ_DONE 0x00000001
2772#define ASC_RQ_GOOD 0x00000002
2773#define ASC_CQ_STOPPER 0x00000000
2774
2775#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2776
2777#define ADV_CARRIER_NUM_PAGE_CROSSING \
2778 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2779 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2780
2781#define ADV_CARRIER_BUFSIZE \
2782 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2783
2784/*
2785 * ASC_SCSI_REQ_Q 'a_flag' definitions
2786 *
2787 * The Adv Library should limit use to the lower nibble (4 bits) of
2788 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2789 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002790#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2791#define ADV_SCSIQ_DONE 0x02 /* request done */
2792#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002794#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2795#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2796#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798/*
2799 * Adapter temporary configuration structure
2800 *
2801 * This structure can be discarded after initialization. Don't add
2802 * fields here needed after initialization.
2803 *
2804 * Field naming convention:
2805 *
2806 * *_enable indicates the field enables or disables a feature. The
2807 * value of the field is never reset.
2808 */
2809typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002810 ushort disc_enable; /* enable disconnection */
2811 uchar chip_version; /* chip version */
2812 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2813 ushort lib_version; /* Adv Library version number */
2814 ushort control_flag; /* Microcode Control Flag */
2815 ushort mcode_date; /* Microcode date */
2816 ushort mcode_version; /* Microcode version */
2817 ushort pci_slot_info; /* high byte device/function number */
2818 /* bits 7-3 device num., bits 2-0 function num. */
2819 /* low byte bus num. */
2820 ushort serial1; /* EEPROM serial number word 1 */
2821 ushort serial2; /* EEPROM serial number word 2 */
2822 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823} ADV_DVC_CFG;
2824
2825struct adv_dvc_var;
2826struct adv_scsi_req_q;
2827
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828/*
2829 * Adapter operation variable structure.
2830 *
2831 * One structure is required per host adapter.
2832 *
2833 * Field naming convention:
2834 *
2835 * *_able indicates both whether a feature should be enabled or disabled
2836 * and whether a device isi capable of the feature. At initialization
2837 * this field may be set, but later if a device is found to be incapable
2838 * of the feature, the field is cleared.
2839 */
2840typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002841 AdvPortAddr iop_base; /* I/O port address */
2842 ushort err_code; /* fatal error code */
2843 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002844 ushort wdtr_able; /* try WDTR for a device */
2845 ushort sdtr_able; /* try SDTR for a device */
2846 ushort ultra_able; /* try SDTR Ultra speed for a device */
2847 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2848 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2849 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2850 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2851 ushort tagqng_able; /* try tagged queuing with a device */
2852 ushort ppr_able; /* PPR message capable per TID bitmask. */
2853 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2854 ushort start_motor; /* start motor command allowed */
2855 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2856 uchar chip_no; /* should be assigned by caller */
2857 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2858 uchar irq_no; /* IRQ number */
2859 ushort no_scam; /* scam_tolerant of EEPROM */
2860 struct asc_board *drv_ptr; /* driver pointer to private structure */
2861 uchar chip_scsi_id; /* chip SCSI target ID */
2862 uchar chip_type;
2863 uchar bist_err_code;
2864 ADV_CARR_T *carrier_buf;
2865 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2866 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2867 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2868 ushort carr_pending_cnt; /* Count of pending carriers. */
2869 /*
2870 * Note: The following fields will not be used after initialization. The
2871 * driver may discard the buffer after initialization is done.
2872 */
2873 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874} ADV_DVC_VAR;
2875
2876#define NO_OF_SG_PER_BLOCK 15
2877
2878typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002879 uchar reserved1;
2880 uchar reserved2;
2881 uchar reserved3;
2882 uchar sg_cnt; /* Valid entries in block. */
2883 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
2884 struct {
2885 ADV_PADDR sg_addr; /* SG element address. */
2886 ADV_DCNT sg_count; /* SG element count. */
2887 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888} ADV_SG_BLOCK;
2889
2890/*
2891 * ADV_SCSI_REQ_Q - microcode request structure
2892 *
2893 * All fields in this structure up to byte 60 are used by the microcode.
2894 * The microcode makes assumptions about the size and ordering of fields
2895 * in this structure. Do not change the structure definition here without
2896 * coordinating the change with the microcode.
2897 *
2898 * All fields accessed by microcode must be maintained in little_endian
2899 * order.
2900 */
2901typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002902 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2903 uchar target_cmd;
2904 uchar target_id; /* Device target identifier. */
2905 uchar target_lun; /* Device target logical unit number. */
2906 ADV_PADDR data_addr; /* Data buffer physical address. */
2907 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
2908 ADV_PADDR sense_addr;
2909 ADV_PADDR carr_pa;
2910 uchar mflag;
2911 uchar sense_len;
2912 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
2913 uchar scsi_cntl;
2914 uchar done_status; /* Completion status. */
2915 uchar scsi_status; /* SCSI status byte. */
2916 uchar host_status; /* Ucode host status. */
2917 uchar sg_working_ix;
2918 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
2919 ADV_PADDR sg_real_addr; /* SG list physical address. */
2920 ADV_PADDR scsiq_rptr;
2921 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
2922 ADV_VADDR scsiq_ptr;
2923 ADV_VADDR carr_va;
2924 /*
2925 * End of microcode structure - 60 bytes. The rest of the structure
2926 * is used by the Adv Library and ignored by the microcode.
2927 */
2928 ADV_VADDR srb_ptr;
2929 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2930 char *vdata_addr; /* Data buffer virtual address. */
2931 uchar a_flag;
2932 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933} ADV_SCSI_REQ_Q;
2934
2935/*
2936 * Microcode idle loop commands
2937 */
2938#define IDLE_CMD_COMPLETED 0
2939#define IDLE_CMD_STOP_CHIP 0x0001
2940#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2941#define IDLE_CMD_SEND_INT 0x0004
2942#define IDLE_CMD_ABORT 0x0008
2943#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002944#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
2945#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946#define IDLE_CMD_SCSIREQ 0x0080
2947
2948#define IDLE_CMD_STATUS_SUCCESS 0x0001
2949#define IDLE_CMD_STATUS_FAILURE 0x0002
2950
2951/*
2952 * AdvSendIdleCmd() flag definitions.
2953 */
2954#define ADV_NOWAIT 0x01
2955
2956/*
2957 * Wait loop time out values.
2958 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002959#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
2960#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2961#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
2962#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
2963#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002965#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2966#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2967#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2968#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002970#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
2972/*
2973 * Device drivers must define the following functions.
2974 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002975static inline ulong DvcEnterCritical(void);
2976static inline void DvcLeaveCritical(ulong);
2977static void DvcSleepMilliSecond(ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002978static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2979 uchar *, ASC_SDCNT *, int);
2980static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
2982/*
2983 * Adv Library functions available to drivers.
2984 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002985static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2986static int AdvISR(ADV_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002987static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2988static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
2989static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
2990static int AdvResetChipAndSB(ADV_DVC_VAR *);
2991static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992
2993/*
2994 * Internal Adv Library functions.
2995 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002996static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002997static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
2998static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
2999static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
3000static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3001static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3002static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3003static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3004static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
3005static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
3006static void AdvWaitEEPCmd(AdvPortAddr);
3007static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009/* Read byte from a register. */
3010#define AdvReadByteRegister(iop_base, reg_off) \
3011 (ADV_MEM_READB((iop_base) + (reg_off)))
3012
3013/* Write byte to a register. */
3014#define AdvWriteByteRegister(iop_base, reg_off, byte) \
3015 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
3016
3017/* Read word (2 bytes) from a register. */
3018#define AdvReadWordRegister(iop_base, reg_off) \
3019 (ADV_MEM_READW((iop_base) + (reg_off)))
3020
3021/* Write word (2 bytes) to a register. */
3022#define AdvWriteWordRegister(iop_base, reg_off, word) \
3023 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
3024
3025/* Write dword (4 bytes) to a register. */
3026#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
3027 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
3028
3029/* Read byte from LRAM. */
3030#define AdvReadByteLram(iop_base, addr, byte) \
3031do { \
3032 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3033 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
3034} while (0)
3035
3036/* Write byte to LRAM. */
3037#define AdvWriteByteLram(iop_base, addr, byte) \
3038 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3039 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
3040
3041/* Read word (2 bytes) from LRAM. */
3042#define AdvReadWordLram(iop_base, addr, word) \
3043do { \
3044 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3045 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
3046} while (0)
3047
3048/* Write word (2 bytes) to LRAM. */
3049#define AdvWriteWordLram(iop_base, addr, word) \
3050 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3051 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3052
3053/* Write little-endian double word (4 bytes) to LRAM */
3054/* Because of unspecified C language ordering don't use auto-increment. */
3055#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
3056 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3057 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3058 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
3059 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3060 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3061 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
3062
3063/* Read word (2 bytes) from LRAM assuming that the address is already set. */
3064#define AdvReadWordAutoIncLram(iop_base) \
3065 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
3066
3067/* Write word (2 bytes) to LRAM assuming that the address is already set. */
3068#define AdvWriteWordAutoIncLram(iop_base, word) \
3069 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3070
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071/*
3072 * Define macro to check for Condor signature.
3073 *
3074 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
3075 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
3076 */
3077#define AdvFindSignature(iop_base) \
3078 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
3079 ADV_CHIP_ID_BYTE) && \
3080 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
3081 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
3082
3083/*
3084 * Define macro to Return the version number of the chip at 'iop_base'.
3085 *
3086 * The second parameter 'bus_type' is currently unused.
3087 */
3088#define AdvGetChipVersion(iop_base, bus_type) \
3089 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
3090
3091/*
3092 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
3093 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
3094 *
3095 * If the request has not yet been sent to the device it will simply be
3096 * aborted from RISC memory. If the request is disconnected it will be
3097 * aborted on reselection by sending an Abort Message to the target ID.
3098 *
3099 * Return value:
3100 * ADV_TRUE(1) - Queue was successfully aborted.
3101 * ADV_FALSE(0) - Queue was not found on the active queue list.
3102 */
3103#define AdvAbortQueue(asc_dvc, scsiq) \
3104 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
3105 (ADV_DCNT) (scsiq))
3106
3107/*
3108 * Send a Bus Device Reset Message to the specified target ID.
3109 *
3110 * All outstanding commands will be purged if sending the
3111 * Bus Device Reset Message is successful.
3112 *
3113 * Return Value:
3114 * ADV_TRUE(1) - All requests on the target are purged.
3115 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
3116 * are not purged.
3117 */
3118#define AdvResetDevice(asc_dvc, target_id) \
3119 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
3120 (ADV_DCNT) (target_id))
3121
3122/*
3123 * SCSI Wide Type definition.
3124 */
3125#define ADV_SCSI_BIT_ID_TYPE ushort
3126
3127/*
3128 * AdvInitScsiTarget() 'cntl_flag' options.
3129 */
3130#define ADV_SCAN_LUN 0x01
3131#define ADV_CAPINFO_NOLUN 0x02
3132
3133/*
3134 * Convert target id to target id bit mask.
3135 */
3136#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
3137
3138/*
3139 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
3140 */
3141
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003142#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143#define QD_NO_ERROR 0x01
3144#define QD_ABORTED_BY_HOST 0x02
3145#define QD_WITH_ERROR 0x04
3146
3147#define QHSTA_NO_ERROR 0x00
3148#define QHSTA_M_SEL_TIMEOUT 0x11
3149#define QHSTA_M_DATA_OVER_RUN 0x12
3150#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
3151#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003152#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
3153#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
3154#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
3155#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
3156#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
3157#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
3158#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003160#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
3161#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
3162#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
3163#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
3164#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
3165#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
3166#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
3167#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168#define QHSTA_M_WTM_TIMEOUT 0x41
3169#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
3170#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
3171#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003172#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
3173#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
3174#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175
3176/*
3177 * Default EEPROM Configuration structure defined in a_init.c.
3178 */
3179static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
3180static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
3181static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
3182
3183/*
3184 * DvcGetPhyAddr() flag arguments
3185 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003186#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
3187#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
3188#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
3189#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
3190#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
3191#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
3193/* Return the address that is aligned at the next doubleword >= to 'addr'. */
3194#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
3195#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
3196#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
3197
3198/*
3199 * Total contiguous memory needed for driver SG blocks.
3200 *
3201 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
3202 * number of scatter-gather elements the driver supports in a
3203 * single request.
3204 */
3205
3206#define ADV_SG_LIST_MAX_BYTE_SIZE \
3207 (sizeof(ADV_SG_BLOCK) * \
3208 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
3209
3210/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 * --- Driver Constants and Macros
3212 */
3213
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214/* Reference Scsi_Host hostdata */
3215#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
3216
3217/* asc_board_t flags */
3218#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003219#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220#define ASC_SELECT_QUEUE_DEPTHS 0x08
3221
3222#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
3223#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
3224
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003225#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003227#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228
3229#ifdef CONFIG_PROC_FS
3230/* /proc/scsi/advansys/[0...] related definitions */
3231#define ASC_PRTBUF_SIZE 2048
3232#define ASC_PRTLINE_SIZE 160
3233
3234#define ASC_PRT_NEXT() \
3235 if (cp) { \
3236 totlen += len; \
3237 leftlen -= len; \
3238 if (leftlen == 0) { \
3239 return totlen; \
3240 } \
3241 cp += len; \
3242 }
3243#endif /* CONFIG_PROC_FS */
3244
3245/* Asc Library return codes */
3246#define ASC_TRUE 1
3247#define ASC_FALSE 0
3248#define ASC_NOERROR 1
3249#define ASC_BUSY 0
3250#define ASC_ERROR (-1)
3251
3252/* struct scsi_cmnd function return codes */
3253#define STATUS_BYTE(byte) (byte)
3254#define MSG_BYTE(byte) ((byte) << 8)
3255#define HOST_BYTE(byte) ((byte) << 16)
3256#define DRIVER_BYTE(byte) ((byte) << 24)
3257
3258/*
3259 * The following definitions and macros are OS independent interfaces to
3260 * the queue functions:
3261 * REQ - SCSI request structure
3262 * REQP - pointer to SCSI request structure
3263 * REQPTID(reqp) - reqp's target id
3264 * REQPNEXT(reqp) - reqp's next pointer
3265 * REQPNEXTP(reqp) - pointer to reqp's next pointer
3266 * REQPTIME(reqp) - reqp's time stamp value
3267 * REQTIMESTAMP() - system time stamp value
3268 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003269typedef struct scsi_cmnd REQ, *REQP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270#define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
3271#define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
3272#define REQPTID(reqp) ((reqp)->device->id)
3273#define REQPTIME(reqp) ((reqp)->SCp.this_residual)
3274#define REQTIMESTAMP() (jiffies)
3275
3276#define REQTIMESTAT(function, ascq, reqp, tid) \
3277{ \
3278 /*
3279 * If the request time stamp is less than the system time stamp, then \
3280 * maybe the system time stamp wrapped. Set the request time to zero.\
3281 */ \
3282 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
3283 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
3284 } else { \
3285 /* Indicate an error occurred with the assertion. */ \
3286 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
3287 REQPTIME(reqp) = 0; \
3288 } \
3289 /* Handle first minimum time case without external initialization. */ \
3290 if (((ascq)->q_tot_cnt[tid] == 1) || \
3291 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
3292 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
3293 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
3294 (function), (tid), (ascq)->q_min_tim[tid]); \
3295 } \
3296 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
3297 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
3298 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
3299 (function), tid, (ascq)->q_max_tim[tid]); \
3300 } \
3301 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
3302 /* Reset the time stamp field. */ \
3303 REQPTIME(reqp) = 0; \
3304}
3305
3306/* asc_enqueue() flags */
3307#define ASC_FRONT 1
3308#define ASC_BACK 2
3309
3310/* asc_dequeue_list() argument */
3311#define ASC_TID_ALL (-1)
3312
3313/* Return non-zero, if the queue is empty. */
3314#define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
3315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003317#define ASC_STATS(shost, counter)
3318#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003320#define ASC_STATS(shost, counter) \
3321 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003323#define ASC_STATS_ADD(shost, counter, count) \
3324 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325#endif /* ADVANSYS_STATS */
3326
3327#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
3328
3329/* If the result wraps when calculating tenths, return 0. */
3330#define ASC_TENTHS(num, den) \
3331 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
3332 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
3333
3334/*
3335 * Display a message to the console.
3336 */
3337#define ASC_PRINT(s) \
3338 { \
3339 printk("advansys: "); \
3340 printk(s); \
3341 }
3342
3343#define ASC_PRINT1(s, a1) \
3344 { \
3345 printk("advansys: "); \
3346 printk((s), (a1)); \
3347 }
3348
3349#define ASC_PRINT2(s, a1, a2) \
3350 { \
3351 printk("advansys: "); \
3352 printk((s), (a1), (a2)); \
3353 }
3354
3355#define ASC_PRINT3(s, a1, a2, a3) \
3356 { \
3357 printk("advansys: "); \
3358 printk((s), (a1), (a2), (a3)); \
3359 }
3360
3361#define ASC_PRINT4(s, a1, a2, a3, a4) \
3362 { \
3363 printk("advansys: "); \
3364 printk((s), (a1), (a2), (a3), (a4)); \
3365 }
3366
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367#ifndef ADVANSYS_DEBUG
3368
3369#define ASC_DBG(lvl, s)
3370#define ASC_DBG1(lvl, s, a1)
3371#define ASC_DBG2(lvl, s, a1, a2)
3372#define ASC_DBG3(lvl, s, a1, a2, a3)
3373#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
3374#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
3375#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
3376#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
3377#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3378#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
3379#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3380#define ASC_DBG_PRT_HEX(lvl, name, start, length)
3381#define ASC_DBG_PRT_CDB(lvl, cdb, len)
3382#define ASC_DBG_PRT_SENSE(lvl, sense, len)
3383#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
3384
3385#else /* ADVANSYS_DEBUG */
3386
3387/*
3388 * Debugging Message Levels:
3389 * 0: Errors Only
3390 * 1: High-Level Tracing
3391 * 2-N: Verbose Tracing
3392 */
3393
3394#define ASC_DBG(lvl, s) \
3395 { \
3396 if (asc_dbglvl >= (lvl)) { \
3397 printk(s); \
3398 } \
3399 }
3400
3401#define ASC_DBG1(lvl, s, a1) \
3402 { \
3403 if (asc_dbglvl >= (lvl)) { \
3404 printk((s), (a1)); \
3405 } \
3406 }
3407
3408#define ASC_DBG2(lvl, s, a1, a2) \
3409 { \
3410 if (asc_dbglvl >= (lvl)) { \
3411 printk((s), (a1), (a2)); \
3412 } \
3413 }
3414
3415#define ASC_DBG3(lvl, s, a1, a2, a3) \
3416 { \
3417 if (asc_dbglvl >= (lvl)) { \
3418 printk((s), (a1), (a2), (a3)); \
3419 } \
3420 }
3421
3422#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
3423 { \
3424 if (asc_dbglvl >= (lvl)) { \
3425 printk((s), (a1), (a2), (a3), (a4)); \
3426 } \
3427 }
3428
3429#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
3430 { \
3431 if (asc_dbglvl >= (lvl)) { \
3432 asc_prt_scsi_host(s); \
3433 } \
3434 }
3435
3436#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
3437 { \
3438 if (asc_dbglvl >= (lvl)) { \
3439 asc_prt_scsi_cmnd(s); \
3440 } \
3441 }
3442
3443#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
3444 { \
3445 if (asc_dbglvl >= (lvl)) { \
3446 asc_prt_asc_scsi_q(scsiqp); \
3447 } \
3448 }
3449
3450#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
3451 { \
3452 if (asc_dbglvl >= (lvl)) { \
3453 asc_prt_asc_qdone_info(qdone); \
3454 } \
3455 }
3456
3457#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
3458 { \
3459 if (asc_dbglvl >= (lvl)) { \
3460 asc_prt_adv_scsi_req_q(scsiqp); \
3461 } \
3462 }
3463
3464#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
3465 { \
3466 if (asc_dbglvl >= (lvl)) { \
3467 asc_prt_hex((name), (start), (length)); \
3468 } \
3469 }
3470
3471#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
3472 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
3473
3474#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
3475 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
3476
3477#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
3478 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
3479#endif /* ADVANSYS_DEBUG */
3480
3481#ifndef ADVANSYS_ASSERT
3482#define ASC_ASSERT(a)
3483#else /* ADVANSYS_ASSERT */
3484
3485#define ASC_ASSERT(a) \
3486 { \
3487 if (!(a)) { \
3488 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
3489 __FILE__, __LINE__); \
3490 } \
3491 }
3492
3493#endif /* ADVANSYS_ASSERT */
3494
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495/*
3496 * --- Driver Structures
3497 */
3498
3499#ifdef ADVANSYS_STATS
3500
3501/* Per board statistics structure */
3502struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003503 /* Driver Entrypoint Statistics */
3504 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
3505 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
3506 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
3507 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
3508 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
3509 ADV_DCNT done; /* # calls to request's scsi_done function */
3510 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
3511 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
3512 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
3513 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
3514 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
3515 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
3516 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
3517 ADV_DCNT exe_unknown; /* # unknown returns. */
3518 /* Data Transfer Statistics */
3519 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
3520 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
3521 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
3522 ADV_DCNT sg_elem; /* # scatter-gather elements */
3523 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524};
3525#endif /* ADVANSYS_STATS */
3526
3527/*
3528 * Request queuing structure
3529 */
3530typedef struct asc_queue {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003531 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
3532 REQP q_first[ADV_MAX_TID + 1]; /* first queued request */
3533 REQP q_last[ADV_MAX_TID + 1]; /* last queued request */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003535 short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */
3536 short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */
3537 ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */
3538 ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */
3539 ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */
3540 ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */
3541#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542} asc_queue_t;
3543
3544/*
3545 * Adv Library Request Structures
3546 *
3547 * The following two structures are used to process Wide Board requests.
3548 *
3549 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
3550 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
3551 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
3552 * Mid-Level SCSI request structure.
3553 *
3554 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
3555 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
3556 * up to 255 scatter-gather elements may be used per request or
3557 * ADV_SCSI_REQ_Q.
3558 *
3559 * Both structures must be 32 byte aligned.
3560 */
3561typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003562 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
3563 uchar align[32]; /* Sgblock structure padding. */
3564 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565} adv_sgblk_t;
3566
3567typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003568 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
3569 uchar align[32]; /* Request structure padding. */
3570 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
3571 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
3572 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573} adv_req_t;
3574
3575/*
3576 * Structure allocated for each board.
3577 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003578 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 * of the 'Scsi_Host' structure starting at the 'hostdata'
3580 * field. It is guaranteed to be allocated from DMA-able memory.
3581 */
3582typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003583 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003584 int id; /* Board Id */
3585 uint flags; /* Board flags */
3586 union {
3587 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
3588 ADV_DVC_VAR adv_dvc_var; /* Wide board */
3589 } dvc_var;
3590 union {
3591 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
3592 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
3593 } dvc_cfg;
3594 ushort asc_n_io_port; /* Number I/O ports. */
3595 asc_queue_t active; /* Active command queue */
3596 asc_queue_t waiting; /* Waiting command queue */
3597 asc_queue_t done; /* Done command queue */
3598 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
3599 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
3600 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
3601 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
3602 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
3603 union {
3604 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
3605 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
3606 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
3607 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
3608 } eep_config;
3609 ulong last_reset; /* Saved last reset time */
3610 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003611 /* /proc/scsi/advansys/[0...] */
3612 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003614 struct asc_stats asc_stats; /* Board statistics */
3615#endif /* ADVANSYS_STATS */
3616 /*
3617 * The following fields are used only for Narrow Boards.
3618 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003619 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
3620 /*
3621 * The following fields are used only for Wide Boards.
3622 */
3623 void __iomem *ioremap_addr; /* I/O Memory remap address. */
3624 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06003625 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003626 adv_req_t *orig_reqp; /* adv_req_t memory block. */
3627 adv_req_t *adv_reqp; /* Request structures. */
3628 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
3629 ushort bios_signature; /* BIOS Signature. */
3630 ushort bios_version; /* BIOS Version. */
3631 ushort bios_codeseg; /* BIOS Code Segment. */
3632 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633} asc_board_t;
3634
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06003636static int asc_board_count;
3637
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003639static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640
3641/*
3642 * Global structures required to issue a command.
3643 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003644static ASC_SCSI_Q asc_scsi_q = { {0} };
3645static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003648static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649#endif /* ADVANSYS_DEBUG */
3650
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651/*
3652 * --- Driver Function Prototypes
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 */
3654
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003655static int advansys_slave_configure(struct scsi_device *);
3656static void asc_scsi_done_list(struct scsi_cmnd *);
3657static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
3658static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
3659static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
3660static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003661static void asc_enqueue(asc_queue_t *, REQP, int);
3662static REQP asc_dequeue(asc_queue_t *, int);
3663static REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
3664static int asc_rmqueue(asc_queue_t *, REQP);
3665static void asc_execute_queue(asc_queue_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003667static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
3668static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
3669static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
3670static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
3671static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
3672static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
3673static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
3674static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
3675static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
3676static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677#endif /* CONFIG_PROC_FS */
3678
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679/* Statistics function prototypes. */
3680#ifdef ADVANSYS_STATS
3681#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003682static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
3683static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684#endif /* CONFIG_PROC_FS */
3685#endif /* ADVANSYS_STATS */
3686
3687/* Debug function prototypes. */
3688#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003689static void asc_prt_scsi_host(struct Scsi_Host *);
3690static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
3691static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
3692static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
3693static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
3694static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
3695static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
3696static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
3697static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
3698static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
3699static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700#endif /* ADVANSYS_DEBUG */
3701
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702#ifdef CONFIG_PROC_FS
3703/*
Matthew Wilcoxc304ec92007-07-30 09:18:45 -06003704 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 *
3706 * *buffer: I/O buffer
3707 * **start: if inout == FALSE pointer into buffer where user read should start
3708 * offset: current offset into a /proc/scsi/advansys/[0...] file
3709 * length: length of buffer
3710 * hostno: Scsi_Host host_no
3711 * inout: TRUE - user is writing; FALSE - user is reading
3712 *
3713 * Return the number of bytes read from or written to a
3714 * /proc/scsi/advansys/[0...] file.
3715 *
3716 * Note: This function uses the per board buffer 'prtbuf' which is
3717 * allocated when the board is initialized in advansys_detect(). The
3718 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
3719 * used to write to the buffer. The way asc_proc_copy() is written
3720 * if 'prtbuf' is too small it will not be overwritten. Instead the
3721 * user just won't get all the available statistics.
3722 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003723static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003725 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003727 asc_board_t *boardp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003728 char *cp;
3729 int cplen;
3730 int cnt;
3731 int totcnt;
3732 int leftlen;
3733 char *curbuf;
3734 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003736 int tgt_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737#endif /* ADVANSYS_STATS */
3738
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003739 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003741 /*
3742 * User write not supported.
3743 */
3744 if (inout == TRUE) {
3745 return (-ENOSYS);
3746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003748 /*
3749 * User read of /proc/scsi/advansys/[0...] file.
3750 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
Matthew Wilcox2a437952007-07-26 11:00:51 -04003752 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003754 /* Copy read data starting at the beginning of the buffer. */
3755 *start = buffer;
3756 curbuf = buffer;
3757 advoffset = 0;
3758 totcnt = 0;
3759 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003761 /*
3762 * Get board configuration information.
3763 *
3764 * advansys_info() returns the board string from its own static buffer.
3765 */
Matthew Wilcox2a437952007-07-26 11:00:51 -04003766 cp = (char *)advansys_info(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003767 strcat(cp, "\n");
3768 cplen = strlen(cp);
3769 /* Copy board information. */
3770 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3771 totcnt += cnt;
3772 leftlen -= cnt;
3773 if (leftlen == 0) {
3774 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3775 return totcnt;
3776 }
3777 advoffset += cplen;
3778 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003780 /*
3781 * Display Wide Board BIOS Information.
3782 */
3783 if (ASC_WIDE_BOARD(boardp)) {
3784 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003785 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003786 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003787 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003788 cplen);
3789 totcnt += cnt;
3790 leftlen -= cnt;
3791 if (leftlen == 0) {
3792 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3793 return totcnt;
3794 }
3795 advoffset += cplen;
3796 curbuf += cnt;
3797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003799 /*
3800 * Display driver information for each device attached to the board.
3801 */
3802 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003803 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003804 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3805 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3806 totcnt += cnt;
3807 leftlen -= cnt;
3808 if (leftlen == 0) {
3809 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3810 return totcnt;
3811 }
3812 advoffset += cplen;
3813 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003815 /*
3816 * Display EEPROM configuration for the board.
3817 */
3818 cp = boardp->prtbuf;
3819 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003820 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003821 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003822 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003823 }
3824 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3825 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3826 totcnt += cnt;
3827 leftlen -= cnt;
3828 if (leftlen == 0) {
3829 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3830 return totcnt;
3831 }
3832 advoffset += cplen;
3833 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003835 /*
3836 * Display driver configuration and information for the board.
3837 */
3838 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003839 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003840 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3841 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3842 totcnt += cnt;
3843 leftlen -= cnt;
3844 if (leftlen == 0) {
3845 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3846 return totcnt;
3847 }
3848 advoffset += cplen;
3849 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
3851#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003852 /*
3853 * Display driver statistics for the board.
3854 */
3855 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003856 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003857 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
3858 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3859 totcnt += cnt;
3860 leftlen -= cnt;
3861 if (leftlen == 0) {
3862 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3863 return totcnt;
3864 }
3865 advoffset += cplen;
3866 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003868 /*
3869 * Display driver statistics for each target.
3870 */
3871 for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
3872 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003873 cplen = asc_prt_target_stats(shost, tgt_id, cp,
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003874 ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003875 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003876 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
3877 cplen);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003878 totcnt += cnt;
3879 leftlen -= cnt;
3880 if (leftlen == 0) {
3881 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3882 return totcnt;
3883 }
3884 advoffset += cplen;
3885 curbuf += cnt;
3886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887#endif /* ADVANSYS_STATS */
3888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003889 /*
3890 * Display Asc Library dynamic configuration information
3891 * for the board.
3892 */
3893 cp = boardp->prtbuf;
3894 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003895 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003896 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003897 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003898 }
3899 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3900 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3901 totcnt += cnt;
3902 leftlen -= cnt;
3903 if (leftlen == 0) {
3904 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3905 return totcnt;
3906 }
3907 advoffset += cplen;
3908 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003910 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003912 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913}
3914#endif /* CONFIG_PROC_FS */
3915
3916/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 * advansys_info()
3918 *
3919 * Return suitable for printing on the console with the argument
3920 * adapter's configuration information.
3921 *
3922 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
3923 * otherwise the static 'info' array will be overrun.
3924 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003925static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003927 static char info[ASC_INFO_SIZE];
3928 asc_board_t *boardp;
3929 ASC_DVC_VAR *asc_dvc_varp;
3930 ADV_DVC_VAR *adv_dvc_varp;
3931 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003932 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003934 boardp = ASC_BOARDP(shost);
3935 if (ASC_NARROW_BOARD(boardp)) {
3936 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3937 ASC_DBG(1, "advansys_info: begin\n");
3938 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3939 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
3940 ASC_IS_ISAPNP) {
3941 busname = "ISA PnP";
3942 } else {
3943 busname = "ISA";
3944 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003945 sprintf(info,
3946 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
3947 ASC_VERSION, busname,
3948 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003949 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3950 shost->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003951 } else {
3952 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
3953 busname = "VL";
3954 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
3955 busname = "EISA";
3956 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
3957 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
3958 == ASC_IS_PCI_ULTRA) {
3959 busname = "PCI Ultra";
3960 } else {
3961 busname = "PCI";
3962 }
3963 } else {
3964 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003965 ASC_PRINT2("advansys_info: board %d: unknown "
3966 "bus type %d\n", boardp->id,
3967 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003968 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003969 sprintf(info,
3970 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003971 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003972 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3973 shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003974 }
3975 } else {
3976 /*
3977 * Wide Adapter Information
3978 *
3979 * Memory-mapped I/O is used instead of I/O space to access
3980 * the adapter, but display the I/O Port range. The Memory
3981 * I/O address is displayed through the driver /proc file.
3982 */
3983 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3984 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003985 widename = "Ultra-Wide";
3986 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003987 widename = "Ultra2-Wide";
3988 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003989 widename = "Ultra3-Wide";
3990 }
3991 sprintf(info,
3992 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
3993 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003994 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003995 }
3996 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
3997 ASC_DBG(1, "advansys_info: end\n");
3998 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999}
4000
4001/*
4002 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
4003 *
4004 * This function always returns 0. Command return status is saved
4005 * in the 'scp' result field.
4006 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004007static int
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004008advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004010 struct Scsi_Host *shost;
4011 asc_board_t *boardp;
4012 ulong flags;
4013 struct scsi_cmnd *done_scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004015 shost = scp->device->host;
4016 boardp = ASC_BOARDP(shost);
4017 ASC_STATS(shost, queuecommand);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004019 /* host_lock taken by mid-level prior to call but need to protect */
4020 /* against own ISR */
4021 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004023 /*
4024 * Block new commands while handling a reset or abort request.
4025 */
4026 if (boardp->flags & ASC_HOST_IN_RESET) {
4027 ASC_DBG1(1,
4028 "advansys_queuecommand: scp 0x%lx blocked for reset request\n",
4029 (ulong)scp);
4030 scp->result = HOST_BYTE(DID_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004032 /*
4033 * Add blocked requests to the board's 'done' queue. The queued
4034 * requests will be completed at the end of the abort or reset
4035 * handling.
4036 */
4037 asc_enqueue(&boardp->done, scp, ASC_BACK);
4038 spin_unlock_irqrestore(&boardp->lock, flags);
4039 return 0;
4040 }
4041
4042 /*
4043 * Attempt to execute any waiting commands for the board.
4044 */
4045 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4046 ASC_DBG(1,
4047 "advansys_queuecommand: before asc_execute_queue() waiting\n");
4048 asc_execute_queue(&boardp->waiting);
4049 }
4050
4051 /*
4052 * Save the function pointer to Linux mid-level 'done' function
4053 * and attempt to execute the command.
4054 *
4055 * If ASC_NOERROR is returned the request has been added to the
4056 * board's 'active' queue and will be completed by the interrupt
4057 * handler.
4058 *
4059 * If ASC_BUSY is returned add the request to the board's per
4060 * target waiting list. This is the first time the request has
4061 * been tried. Add it to the back of the waiting list. It will be
4062 * retried later.
4063 *
4064 * If an error occurred, the request will have been placed on the
4065 * board's 'done' queue and must be completed before returning.
4066 */
4067 scp->scsi_done = done;
4068 switch (asc_execute_scsi_cmnd(scp)) {
4069 case ASC_NOERROR:
4070 break;
4071 case ASC_BUSY:
4072 asc_enqueue(&boardp->waiting, scp, ASC_BACK);
4073 break;
4074 case ASC_ERROR:
4075 default:
4076 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
4077 /* Interrupts could be enabled here. */
4078 asc_scsi_done_list(done_scp);
4079 break;
4080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004083 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084}
4085
4086/*
4087 * advansys_reset()
4088 *
4089 * Reset the bus associated with the command 'scp'.
4090 *
4091 * This function runs its own thread. Interrupts must be blocked but
4092 * sleeping is allowed and no locking other than for host structures is
4093 * required. Returns SUCCESS or FAILED.
4094 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004095static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004097 struct Scsi_Host *shost;
4098 asc_board_t *boardp;
4099 ASC_DVC_VAR *asc_dvc_varp;
4100 ADV_DVC_VAR *adv_dvc_varp;
4101 ulong flags;
4102 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4103 struct scsi_cmnd *tscp, *new_last_scp;
4104 int status;
4105 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004107 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
4109#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004110 if (scp->device->host != NULL) {
4111 ASC_STATS(scp->device->host, reset);
4112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113#endif /* ADVANSYS_STATS */
4114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004115 if ((shost = scp->device->host) == NULL) {
4116 scp->result = HOST_BYTE(DID_ERROR);
4117 return FAILED;
4118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004120 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004122 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
4123 boardp->id);
4124 /*
4125 * Check for re-entrancy.
4126 */
4127 spin_lock_irqsave(&boardp->lock, flags);
4128 if (boardp->flags & ASC_HOST_IN_RESET) {
4129 spin_unlock_irqrestore(&boardp->lock, flags);
4130 return FAILED;
4131 }
4132 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004135 if (ASC_NARROW_BOARD(boardp)) {
4136 /*
4137 * Narrow Board
4138 */
4139 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004141 /*
4142 * Reset the chip and SCSI bus.
4143 */
4144 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
4145 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004147 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
4148 if (asc_dvc_varp->err_code) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004149 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
4150 "error: 0x%x\n", boardp->id,
4151 asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004152 ret = FAILED;
4153 } else if (status) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004154 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
4155 "warning: 0x%x\n", boardp->id, status);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004156 } else {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004157 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
4158 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004161 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
4162 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004164 } else {
4165 /*
4166 * Wide Board
4167 *
4168 * If the suggest reset bus flags are set, then reset the bus.
4169 * Otherwise only reset the device.
4170 */
4171 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004173 /*
4174 * Reset the target's SCSI bus.
4175 */
4176 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
4177 switch (AdvResetChipAndSB(adv_dvc_varp)) {
4178 case ASC_TRUE:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004179 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
4180 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004181 break;
4182 case ASC_FALSE:
4183 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004184 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
4185 "error.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004186 ret = FAILED;
4187 break;
4188 }
4189 spin_lock_irqsave(&boardp->lock, flags);
4190 (void)AdvISR(adv_dvc_varp);
4191 }
4192 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004194 /*
4195 * Dequeue all board 'done' requests. A pointer to the last request
4196 * is returned in 'last_scp'.
4197 */
4198 done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004200 /*
4201 * Dequeue all board 'active' requests for all devices and set
4202 * the request status to DID_RESET. A pointer to the last request
4203 * is returned in 'last_scp'.
4204 */
4205 if (done_scp == NULL) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004206 done_scp = asc_dequeue_list(&boardp->active, &last_scp,
4207 ASC_TID_ALL);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004208 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
4209 tscp->result = HOST_BYTE(DID_RESET);
4210 }
4211 } else {
4212 /* Append to 'done_scp' at the end with 'last_scp'. */
4213 ASC_ASSERT(last_scp != NULL);
4214 last_scp->host_scribble =
4215 (unsigned char *)asc_dequeue_list(&boardp->active,
4216 &new_last_scp,
4217 ASC_TID_ALL);
4218 if (new_last_scp != NULL) {
4219 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4220 for (tscp = REQPNEXT(last_scp); tscp;
4221 tscp = REQPNEXT(tscp)) {
4222 tscp->result = HOST_BYTE(DID_RESET);
4223 }
4224 last_scp = new_last_scp;
4225 }
4226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004228 /*
4229 * Dequeue all 'waiting' requests and set the request status
4230 * to DID_RESET.
4231 */
4232 if (done_scp == NULL) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004233 done_scp = asc_dequeue_list(&boardp->waiting, &last_scp,
4234 ASC_TID_ALL);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004235 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
4236 tscp->result = HOST_BYTE(DID_RESET);
4237 }
4238 } else {
4239 /* Append to 'done_scp' at the end with 'last_scp'. */
4240 ASC_ASSERT(last_scp != NULL);
4241 last_scp->host_scribble =
4242 (unsigned char *)asc_dequeue_list(&boardp->waiting,
4243 &new_last_scp,
4244 ASC_TID_ALL);
4245 if (new_last_scp != NULL) {
4246 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4247 for (tscp = REQPNEXT(last_scp); tscp;
4248 tscp = REQPNEXT(tscp)) {
4249 tscp->result = HOST_BYTE(DID_RESET);
4250 }
4251 last_scp = new_last_scp;
4252 }
4253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004255 /* Save the time of the most recently completed reset. */
4256 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004258 /* Clear reset flag. */
4259 boardp->flags &= ~ASC_HOST_IN_RESET;
4260 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004262 /*
4263 * Complete all the 'done_scp' requests.
4264 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004265 if (done_scp)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004266 asc_scsi_done_list(done_scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004268 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004270 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
4273/*
4274 * advansys_biosparam()
4275 *
4276 * Translate disk drive geometry if the "BIOS greater than 1 GB"
4277 * support is enabled for a drive.
4278 *
4279 * ip (information pointer) is an int array with the following definition:
4280 * ip[0]: heads
4281 * ip[1]: sectors
4282 * ip[2]: cylinders
4283 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004284static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004286 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004288 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004290 ASC_DBG(1, "advansys_biosparam: begin\n");
4291 ASC_STATS(sdev->host, biosparam);
4292 boardp = ASC_BOARDP(sdev->host);
4293 if (ASC_NARROW_BOARD(boardp)) {
4294 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
4295 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
4296 ip[0] = 255;
4297 ip[1] = 63;
4298 } else {
4299 ip[0] = 64;
4300 ip[1] = 32;
4301 }
4302 } else {
4303 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
4304 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
4305 ip[0] = 255;
4306 ip[1] = 63;
4307 } else {
4308 ip[0] = 64;
4309 ip[1] = 32;
4310 }
4311 }
4312 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
4313 ASC_DBG(1, "advansys_biosparam: end\n");
4314 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315}
4316
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06004317static struct scsi_host_template advansys_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004318 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004320 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004322 .name = "advansys",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004323 .info = advansys_info,
4324 .queuecommand = advansys_queuecommand,
4325 .eh_bus_reset_handler = advansys_reset,
4326 .bios_param = advansys_biosparam,
4327 .slave_configure = advansys_slave_configure,
4328 /*
4329 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06004330 * must be set. The flag will be cleared in advansys_board_found
4331 * for non-ISA adapters.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004332 */
4333 .unchecked_isa_dma = 1,
4334 /*
4335 * All adapters controlled by this driver are capable of large
4336 * scatter-gather lists. According to the mid-level SCSI documentation
4337 * this obviates any performance gain provided by setting
4338 * 'use_clustering'. But empirically while CPU utilization is increased
4339 * by enabling clustering, I/O throughput increases as well.
4340 */
4341 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344/*
4345 * --- Miscellaneous Driver Functions
4346 */
4347
4348/*
4349 * First-level interrupt handler.
4350 *
4351 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
4352 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
4353 * is not referenced. 'dev_id' could be used to identify an interrupt passed
4354 * to the AdvanSys driver which is for a device sharing an interrupt with
4355 * an AdvanSys adapter.
4356 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004357static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358{
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004359 unsigned long flags;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004360 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4361 struct scsi_cmnd *new_last_scp;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004362 struct Scsi_Host *shost = dev_id;
4363 asc_board_t *boardp = ASC_BOARDP(shost);
4364 irqreturn_t result = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004366 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
4367 spin_lock_irqsave(&boardp->lock, flags);
4368 if (ASC_NARROW_BOARD(boardp)) {
4369 /*
4370 * Narrow Board
4371 */
4372 if (AscIsIntPending(shost->io_port)) {
4373 result = IRQ_HANDLED;
4374 ASC_STATS(shost, interrupt);
4375 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
4376 AscISR(&boardp->dvc_var.asc_dvc_var);
4377 }
4378 } else {
4379 /*
4380 * Wide Board
4381 */
4382 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
4383 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
4384 result = IRQ_HANDLED;
4385 ASC_STATS(shost, interrupt);
4386 }
4387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004389 /*
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004390 * Start waiting requests and create a list of completed requests.
4391 *
4392 * If a reset request is being performed for the board, the reset
4393 * handler will complete pending requests after it has completed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004394 */
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004395 if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
4396 ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, "
4397 "last_scp 0x%p\n", done_scp, last_scp);
4398
4399 /* Start any waiting commands for the board. */
4400 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4401 ASC_DBG(1, "advansys_interrupt: before "
4402 "asc_execute_queue()\n");
4403 asc_execute_queue(&boardp->waiting);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004406 /*
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004407 * Add to the list of requests that must be completed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004408 *
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004409 * 'done_scp' will always be NULL on the first iteration of
4410 * this loop. 'last_scp' is set at the same time as 'done_scp'.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004411 */
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004412 if (done_scp == NULL) {
4413 done_scp = asc_dequeue_list(&boardp->done,
4414 &last_scp, ASC_TID_ALL);
4415 } else {
4416 ASC_ASSERT(last_scp != NULL);
4417 last_scp->host_scribble =
4418 (unsigned char *)asc_dequeue_list(&boardp->
4419 done,
4420 &new_last_scp,
4421 ASC_TID_ALL);
4422 if (new_last_scp != NULL) {
4423 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4424 last_scp = new_last_scp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004425 }
4426 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004427 }
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004428 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004430 /*
4431 * If interrupts were enabled on entry, then they
4432 * are now enabled here.
4433 *
4434 * Complete all requests on the done list.
4435 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004437 asc_scsi_done_list(done_scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004439 ASC_DBG(1, "advansys_interrupt: end\n");
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004440 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441}
4442
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004443static void
4444advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
4445{
4446 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
4447 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
4448
4449 if (sdev->lun == 0) {
4450 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
4451 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
4452 asc_dvc->init_sdtr |= tid_bit;
4453 } else {
4454 asc_dvc->init_sdtr &= ~tid_bit;
4455 }
4456
4457 if (orig_init_sdtr != asc_dvc->init_sdtr)
4458 AscAsyncFix(asc_dvc, sdev);
4459 }
4460
4461 if (sdev->tagged_supported) {
4462 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
4463 if (sdev->lun == 0) {
4464 asc_dvc->cfg->can_tagged_qng |= tid_bit;
4465 asc_dvc->use_tagged_qng |= tid_bit;
4466 }
4467 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
4468 asc_dvc->max_dvc_qng[sdev->id]);
4469 }
4470 } else {
4471 if (sdev->lun == 0) {
4472 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
4473 asc_dvc->use_tagged_qng &= ~tid_bit;
4474 }
4475 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
4476 }
4477
4478 if ((sdev->lun == 0) &&
4479 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
4480 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
4481 asc_dvc->cfg->disc_enable);
4482 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
4483 asc_dvc->use_tagged_qng);
4484 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
4485 asc_dvc->cfg->can_tagged_qng);
4486
4487 asc_dvc->max_dvc_qng[sdev->id] =
4488 asc_dvc->cfg->max_tag_qng[sdev->id];
4489 AscWriteLramByte(asc_dvc->iop_base,
4490 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
4491 asc_dvc->max_dvc_qng[sdev->id]);
4492 }
4493}
4494
4495/*
4496 * Wide Transfers
4497 *
4498 * If the EEPROM enabled WDTR for the device and the device supports wide
4499 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
4500 * write the new value to the microcode.
4501 */
4502static void
4503advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
4504{
4505 unsigned short cfg_word;
4506 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
4507 if ((cfg_word & tidmask) != 0)
4508 return;
4509
4510 cfg_word |= tidmask;
4511 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
4512
4513 /*
4514 * Clear the microcode SDTR and WDTR negotiation done indicators for
4515 * the target to cause it to negotiate with the new setting set above.
4516 * WDTR when accepted causes the target to enter asynchronous mode, so
4517 * SDTR must be negotiated.
4518 */
4519 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
4520 cfg_word &= ~tidmask;
4521 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
4522 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
4523 cfg_word &= ~tidmask;
4524 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
4525}
4526
4527/*
4528 * Synchronous Transfers
4529 *
4530 * If the EEPROM enabled SDTR for the device and the device
4531 * supports synchronous transfers, then turn on the device's
4532 * 'sdtr_able' bit. Write the new value to the microcode.
4533 */
4534static void
4535advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
4536{
4537 unsigned short cfg_word;
4538 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
4539 if ((cfg_word & tidmask) != 0)
4540 return;
4541
4542 cfg_word |= tidmask;
4543 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
4544
4545 /*
4546 * Clear the microcode "SDTR negotiation" done indicator for the
4547 * target to cause it to negotiate with the new setting set above.
4548 */
4549 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
4550 cfg_word &= ~tidmask;
4551 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
4552}
4553
4554/*
4555 * PPR (Parallel Protocol Request) Capable
4556 *
4557 * If the device supports DT mode, then it must be PPR capable.
4558 * The PPR message will be used in place of the SDTR and WDTR
4559 * messages to negotiate synchronous speed and offset, transfer
4560 * width, and protocol options.
4561 */
4562static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
4563 AdvPortAddr iop_base, unsigned short tidmask)
4564{
4565 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
4566 adv_dvc->ppr_able |= tidmask;
4567 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
4568}
4569
4570static void
4571advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
4572{
4573 AdvPortAddr iop_base = adv_dvc->iop_base;
4574 unsigned short tidmask = 1 << sdev->id;
4575
4576 if (sdev->lun == 0) {
4577 /*
4578 * Handle WDTR, SDTR, and Tag Queuing. If the feature
4579 * is enabled in the EEPROM and the device supports the
4580 * feature, then enable it in the microcode.
4581 */
4582
4583 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
4584 advansys_wide_enable_wdtr(iop_base, tidmask);
4585 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
4586 advansys_wide_enable_sdtr(iop_base, tidmask);
4587 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
4588 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
4589
4590 /*
4591 * Tag Queuing is disabled for the BIOS which runs in polled
4592 * mode and would see no benefit from Tag Queuing. Also by
4593 * disabling Tag Queuing in the BIOS devices with Tag Queuing
4594 * bugs will at least work with the BIOS.
4595 */
4596 if ((adv_dvc->tagqng_able & tidmask) &&
4597 sdev->tagged_supported) {
4598 unsigned short cfg_word;
4599 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
4600 cfg_word |= tidmask;
4601 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
4602 cfg_word);
4603 AdvWriteByteLram(iop_base,
4604 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
4605 adv_dvc->max_dvc_qng);
4606 }
4607 }
4608
4609 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
4610 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
4611 adv_dvc->max_dvc_qng);
4612 } else {
4613 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
4614 }
4615}
4616
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617/*
4618 * Set the number of commands to queue per device for the
4619 * specified host adapter.
4620 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004621static int advansys_slave_configure(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004623 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004624 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004625
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004626 /*
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004627 * Save a pointer to the sdev and set its initial/maximum
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004628 * queue depth. Only save the pointer for a lun0 dev though.
4629 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004630 if (sdev->lun == 0)
4631 boardp->device[sdev->id] = sdev;
4632
4633 if (ASC_NARROW_BOARD(boardp))
4634 advansys_narrow_slave_configure(sdev,
4635 &boardp->dvc_var.asc_dvc_var);
4636 else
4637 advansys_wide_slave_configure(sdev,
4638 &boardp->dvc_var.adv_dvc_var);
4639
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004640 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641}
4642
4643/*
4644 * Complete all requests on the singly linked list pointed
4645 * to by 'scp'.
4646 *
4647 * Interrupts can be enabled on entry.
4648 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004649static void asc_scsi_done_list(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004651 struct scsi_cmnd *tscp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004653 ASC_DBG(2, "asc_scsi_done_list: begin\n");
4654 while (scp != NULL) {
4655 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004657 ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
4658 tscp = REQPNEXT(scp);
4659 scp->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004661 boardp = ASC_BOARDP(scp->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004663 if (scp->use_sg)
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004664 dma_unmap_sg(boardp->dev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004665 (struct scatterlist *)scp->request_buffer,
4666 scp->use_sg, scp->sc_data_direction);
4667 else if (scp->request_bufflen)
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004668 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004669 scp->request_bufflen,
4670 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004672 ASC_STATS(scp->device->host, done);
4673 ASC_ASSERT(scp->scsi_done != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004675 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004677 scp = tscp;
4678 }
4679 ASC_DBG(2, "asc_scsi_done_list: done\n");
4680 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681}
4682
4683/*
4684 * Execute a single 'Scsi_Cmnd'.
4685 *
4686 * The function 'done' is called when the request has been completed.
4687 *
4688 * Scsi_Cmnd:
4689 *
4690 * host - board controlling device
4691 * device - device to send command
4692 * target - target of device
4693 * lun - lun of device
4694 * cmd_len - length of SCSI CDB
4695 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
4696 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
4697 *
4698 * if (use_sg == 0) {
4699 * request_buffer - buffer address for request
4700 * request_bufflen - length of request buffer
4701 * } else {
4702 * request_buffer - pointer to scatterlist structure
4703 * }
4704 *
4705 * sense_buffer - sense command buffer
4706 *
4707 * result (4 bytes of an int):
4708 * Byte Meaning
4709 * 0 SCSI Status Byte Code
4710 * 1 SCSI One Byte Message Code
4711 * 2 Host Error Code
4712 * 3 Mid-Level Error Code
4713 *
4714 * host driver fields:
4715 * SCp - Scsi_Pointer used for command processing status
4716 * scsi_done - used to save caller's done function
4717 * host_scribble - used for pointer to another struct scsi_cmnd
4718 *
4719 * If this function returns ASC_NOERROR the request has been enqueued
4720 * on the board's 'active' queue and will be completed from the
4721 * interrupt handler.
4722 *
4723 * If this function returns ASC_NOERROR the request has been enqueued
4724 * on the board's 'done' queue and must be completed by the caller.
4725 *
4726 * If ASC_BUSY is returned the request will be enqueued by the
4727 * caller on the target's waiting queue and re-tried later.
4728 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004729static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004730{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004731 asc_board_t *boardp;
4732 ASC_DVC_VAR *asc_dvc_varp;
4733 ADV_DVC_VAR *adv_dvc_varp;
4734 ADV_SCSI_REQ_Q *adv_scsiqp;
4735 struct scsi_device *device;
4736 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004738 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
4739 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004741 boardp = ASC_BOARDP(scp->device->host);
4742 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004744 if (ASC_NARROW_BOARD(boardp)) {
4745 /*
4746 * Build and execute Narrow Board request.
4747 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004749 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004751 /*
4752 * Build Asc Library request structure using the
4753 * global structures 'asc_scsi_req' and 'asc_sg_head'.
4754 *
4755 * If an error is returned, then the request has been
4756 * queued on the board done queue. It will be completed
4757 * by the caller.
4758 *
4759 * asc_build_req() can not return ASC_BUSY.
4760 */
4761 if (asc_build_req(boardp, scp) == ASC_ERROR) {
4762 ASC_STATS(scp->device->host, build_error);
4763 return ASC_ERROR;
4764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004765
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004766 /*
4767 * Execute the command. If there is no error, add the command
4768 * to the active queue.
4769 */
4770 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
4771 case ASC_NOERROR:
4772 ASC_STATS(scp->device->host, exe_noerror);
4773 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004774 * Increment monotonically increasing per device
4775 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004776 */
4777 boardp->reqcnt[scp->device->id]++;
4778 asc_enqueue(&boardp->active, scp, ASC_BACK);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004779 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), "
4780 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004781 break;
4782 case ASC_BUSY:
4783 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004784 * Caller will enqueue request on the target's waiting
4785 * queue and retry later.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004786 */
4787 ASC_STATS(scp->device->host, exe_busy);
4788 break;
4789 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004790 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
4791 "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
4792 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004793 ASC_STATS(scp->device->host, exe_error);
4794 scp->result = HOST_BYTE(DID_ERROR);
4795 asc_enqueue(&boardp->done, scp, ASC_BACK);
4796 break;
4797 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004798 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
4799 "AscExeScsiQueue() unknown, err_code 0x%x\n",
4800 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004801 ASC_STATS(scp->device->host, exe_unknown);
4802 scp->result = HOST_BYTE(DID_ERROR);
4803 asc_enqueue(&boardp->done, scp, ASC_BACK);
4804 break;
4805 }
4806 } else {
4807 /*
4808 * Build and execute Wide Board request.
4809 */
4810 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004811
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004812 /*
4813 * Build and get a pointer to an Adv Library request structure.
4814 *
4815 * If the request is successfully built then send it below,
4816 * otherwise return with an error.
4817 */
4818 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
4819 case ASC_NOERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004820 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
4821 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004822 break;
4823 case ASC_BUSY:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004824 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
4825 "ASC_BUSY\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004826 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004827 * If busy is returned the request has not been
4828 * enqueued. It will be enqueued by the caller on the
4829 * target's waiting queue and retried later.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004830 *
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004831 * The asc_stats fields 'adv_build_noreq' and
4832 * 'adv_build_nosg' count wide board busy conditions.
4833 * They are updated in adv_build_req and
4834 * adv_get_sglist, respectively.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004835 */
4836 return ASC_BUSY;
4837 case ASC_ERROR:
4838 /*
4839 * If an error is returned, then the request has been
4840 * queued on the board done queue. It will be completed
4841 * by the caller.
4842 */
4843 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004844 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
4845 "ASC_ERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004846 ASC_STATS(scp->device->host, build_error);
4847 return ASC_ERROR;
4848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004850 /*
4851 * Execute the command. If there is no error, add the command
4852 * to the active queue.
4853 */
4854 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
4855 case ASC_NOERROR:
4856 ASC_STATS(scp->device->host, exe_noerror);
4857 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004858 * Increment monotonically increasing per device
4859 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004860 */
4861 boardp->reqcnt[scp->device->id]++;
4862 asc_enqueue(&boardp->active, scp, ASC_BACK);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004863 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), "
4864 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004865 break;
4866 case ASC_BUSY:
4867 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004868 * Caller will enqueue request on the target's waiting
4869 * queue and retry later.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004870 */
4871 ASC_STATS(scp->device->host, exe_busy);
4872 break;
4873 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004874 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
4875 "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
4876 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004877 ASC_STATS(scp->device->host, exe_error);
4878 scp->result = HOST_BYTE(DID_ERROR);
4879 asc_enqueue(&boardp->done, scp, ASC_BACK);
4880 break;
4881 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004882 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
4883 "AdvExeScsiQueue() unknown, err_code 0x%x\n",
4884 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004885 ASC_STATS(scp->device->host, exe_unknown);
4886 scp->result = HOST_BYTE(DID_ERROR);
4887 asc_enqueue(&boardp->done, scp, ASC_BACK);
4888 break;
4889 }
4890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004892 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
4893 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894}
4895
4896/*
4897 * Build a request structure for the Asc Library (Narrow Board).
4898 *
4899 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
4900 * used to build the request.
4901 *
4902 * If an error occurs, then queue the request on the board done
4903 * queue and return ASC_ERROR.
4904 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004905static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004907 /*
4908 * Mutually exclusive access is required to 'asc_scsi_q' and
4909 * 'asc_sg_head' until after the request is started.
4910 */
4911 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004913 /*
4914 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
4915 */
4916 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004918 /*
4919 * Build the ASC_SCSI_Q request.
4920 *
4921 * For narrow boards a CDB length maximum of 12 bytes
4922 * is supported.
4923 */
4924 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004925 ASC_PRINT3("asc_build_req: board %d: cmd_len %d > "
4926 "ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len,
4927 ASC_MAX_CDB_LEN);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004928 scp->result = HOST_BYTE(DID_ERROR);
4929 asc_enqueue(&boardp->done, scp, ASC_BACK);
4930 return ASC_ERROR;
4931 }
4932 asc_scsi_q.cdbptr = &scp->cmnd[0];
4933 asc_scsi_q.q2.cdb_len = scp->cmd_len;
4934 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
4935 asc_scsi_q.q1.target_lun = scp->device->lun;
4936 asc_scsi_q.q2.target_ix =
4937 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
4938 asc_scsi_q.q1.sense_addr =
4939 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4940 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004942 /*
4943 * If there are any outstanding requests for the current target,
4944 * then every 255th request send an ORDERED request. This heuristic
4945 * tries to retain the benefit of request sorting while preventing
4946 * request starvation. 255 is the max number of tags or pending commands
4947 * a device may have outstanding.
4948 *
4949 * The request count is incremented below for every successfully
4950 * started request.
4951 *
4952 */
4953 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
4954 (boardp->reqcnt[scp->device->id] % 255) == 0) {
4955 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
4956 } else {
4957 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
4958 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004960 /*
4961 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
4962 * buffer command.
4963 */
4964 if (scp->use_sg == 0) {
4965 /*
4966 * CDB request of single contiguous buffer.
4967 */
4968 ASC_STATS(scp->device->host, cont_cnt);
4969 scp->SCp.dma_handle = scp->request_bufflen ?
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004970 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004971 scp->request_bufflen,
4972 scp->sc_data_direction) : 0;
4973 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
4974 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
4975 ASC_STATS_ADD(scp->device->host, cont_xfer,
4976 ASC_CEILING(scp->request_bufflen, 512));
4977 asc_scsi_q.q1.sg_queue_cnt = 0;
4978 asc_scsi_q.sg_head = NULL;
4979 } else {
4980 /*
4981 * CDB scatter-gather request list.
4982 */
4983 int sgcnt;
4984 int use_sg;
4985 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004987 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004988 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4989 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004991 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004992 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
4993 "sg_tablesize %d\n", boardp->id, use_sg,
4994 scp->device->host->sg_tablesize);
4995 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004996 scp->sc_data_direction);
4997 scp->result = HOST_BYTE(DID_ERROR);
4998 asc_enqueue(&boardp->done, scp, ASC_BACK);
4999 return ASC_ERROR;
5000 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005002 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005004 /*
5005 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
5006 * structure to point to it.
5007 */
5008 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005010 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
5011 asc_scsi_q.sg_head = &asc_sg_head;
5012 asc_scsi_q.q1.data_cnt = 0;
5013 asc_scsi_q.q1.data_addr = 0;
5014 /* This is a byte value, otherwise it would need to be swapped. */
5015 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
5016 ASC_STATS_ADD(scp->device->host, sg_elem,
5017 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005019 /*
5020 * Convert scatter-gather list into ASC_SG_HEAD list.
5021 */
5022 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
5023 asc_sg_head.sg_list[sgcnt].addr =
5024 cpu_to_le32(sg_dma_address(slp));
5025 asc_sg_head.sg_list[sgcnt].bytes =
5026 cpu_to_le32(sg_dma_len(slp));
5027 ASC_STATS_ADD(scp->device->host, sg_xfer,
5028 ASC_CEILING(sg_dma_len(slp), 512));
5029 }
5030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005032 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
5033 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005035 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036}
5037
5038/*
5039 * Build a request structure for the Adv Library (Wide Board).
5040 *
5041 * If an adv_req_t can not be allocated to issue the request,
5042 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
5043 *
5044 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
5045 * microcode for DMA addresses or math operations are byte swapped
5046 * to little-endian order.
5047 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005048static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005050 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005052 adv_req_t *reqp;
5053 ADV_SCSI_REQ_Q *scsiqp;
5054 int i;
5055 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005057 /*
5058 * Allocate an adv_req_t structure from the board to execute
5059 * the command.
5060 */
5061 if (boardp->adv_reqp == NULL) {
5062 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
5063 ASC_STATS(scp->device->host, adv_build_noreq);
5064 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005066 reqp = boardp->adv_reqp;
5067 boardp->adv_reqp = reqp->next_reqp;
5068 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005071 /*
5072 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
5073 */
5074 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005076 /*
5077 * Initialize the structure.
5078 */
5079 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005081 /*
5082 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
5083 */
5084 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005086 /*
5087 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
5088 */
5089 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005091 /*
5092 * Build the ADV_SCSI_REQ_Q request.
5093 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005095 /*
5096 * Set CDB length and copy it to the request structure.
5097 * For wide boards a CDB length maximum of 16 bytes
5098 * is supported.
5099 */
5100 if (scp->cmd_len > ADV_MAX_CDB_LEN) {
5101 ASC_PRINT3
5102 ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
5103 boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
5104 scp->result = HOST_BYTE(DID_ERROR);
5105 asc_enqueue(&boardp->done, scp, ASC_BACK);
5106 return ASC_ERROR;
5107 }
5108 scsiqp->cdb_len = scp->cmd_len;
5109 /* Copy first 12 CDB bytes to cdb[]. */
5110 for (i = 0; i < scp->cmd_len && i < 12; i++) {
5111 scsiqp->cdb[i] = scp->cmnd[i];
5112 }
5113 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
5114 for (; i < scp->cmd_len; i++) {
5115 scsiqp->cdb16[i - 12] = scp->cmnd[i];
5116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005118 scsiqp->target_id = scp->device->id;
5119 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005121 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
5122 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005124 /*
5125 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
5126 * buffer command.
5127 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005129 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
5130 scsiqp->vdata_addr = scp->request_buffer;
5131 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
5132
5133 if (scp->use_sg == 0) {
5134 /*
5135 * CDB request of single contiguous buffer.
5136 */
5137 reqp->sgblkp = NULL;
5138 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
5139 if (scp->request_bufflen) {
5140 scsiqp->vdata_addr = scp->request_buffer;
5141 scp->SCp.dma_handle =
Matthew Wilcox394dbf32007-07-26 11:56:40 -04005142 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005143 scp->request_bufflen,
5144 scp->sc_data_direction);
5145 } else {
5146 scsiqp->vdata_addr = NULL;
5147 scp->SCp.dma_handle = 0;
5148 }
5149 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
5150 scsiqp->sg_list_ptr = NULL;
5151 scsiqp->sg_real_addr = 0;
5152 ASC_STATS(scp->device->host, cont_cnt);
5153 ASC_STATS_ADD(scp->device->host, cont_xfer,
5154 ASC_CEILING(scp->request_bufflen, 512));
5155 } else {
5156 /*
5157 * CDB scatter-gather request list.
5158 */
5159 struct scatterlist *slp;
5160 int use_sg;
5161
5162 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04005163 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
5164 scp->sc_data_direction);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005165
5166 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04005167 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
5168 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
5169 scp->device->host->sg_tablesize);
5170 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005171 scp->sc_data_direction);
5172 scp->result = HOST_BYTE(DID_ERROR);
5173 asc_enqueue(&boardp->done, scp, ASC_BACK);
5174
5175 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04005176 * Free the 'adv_req_t' structure by adding it back
5177 * to the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005178 */
5179 reqp->next_reqp = boardp->adv_reqp;
5180 boardp->adv_reqp = reqp;
5181
5182 return ASC_ERROR;
5183 }
5184
Matthew Wilcox394dbf32007-07-26 11:56:40 -04005185 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
5186 if (ret != ADV_SUCCESS) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005187 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04005188 * Free the adv_req_t structure by adding it back to
5189 * the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005190 */
5191 reqp->next_reqp = boardp->adv_reqp;
5192 boardp->adv_reqp = reqp;
5193
5194 return ret;
5195 }
5196
5197 ASC_STATS(scp->device->host, sg_cnt);
5198 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
5199 }
5200
5201 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
5202 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
5203
5204 *adv_scsiqpp = scsiqp;
5205
5206 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207}
5208
5209/*
5210 * Build scatter-gather list for Adv Library (Wide Board).
5211 *
5212 * Additional ADV_SG_BLOCK structures will need to be allocated
5213 * if the total number of scatter-gather elements exceeds
5214 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
5215 * assumed to be physically contiguous.
5216 *
5217 * Return:
5218 * ADV_SUCCESS(1) - SG List successfully created
5219 * ADV_ERROR(-1) - SG List creation failed
5220 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005221static int
5222adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
5223 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005225 adv_sgblk_t *sgblkp;
5226 ADV_SCSI_REQ_Q *scsiqp;
5227 struct scatterlist *slp;
5228 int sg_elem_cnt;
5229 ADV_SG_BLOCK *sg_block, *prev_sg_block;
5230 ADV_PADDR sg_block_paddr;
5231 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005233 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
5234 slp = (struct scatterlist *)scp->request_buffer;
5235 sg_elem_cnt = use_sg;
5236 prev_sg_block = NULL;
5237 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005239 do {
5240 /*
5241 * Allocate a 'adv_sgblk_t' structure from the board free
5242 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
5243 * (15) scatter-gather elements.
5244 */
5245 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
5246 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
5247 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005249 /*
5250 * Allocation failed. Free 'adv_sgblk_t' structures already
5251 * allocated for the request.
5252 */
5253 while ((sgblkp = reqp->sgblkp) != NULL) {
5254 /* Remove 'sgblkp' from the request list. */
5255 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005257 /* Add 'sgblkp' to the board free list. */
5258 sgblkp->next_sgblkp = boardp->adv_sgblkp;
5259 boardp->adv_sgblkp = sgblkp;
5260 }
5261 return ASC_BUSY;
5262 } else {
5263 /* Complete 'adv_sgblk_t' board allocation. */
5264 boardp->adv_sgblkp = sgblkp->next_sgblkp;
5265 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005267 /*
5268 * Get 8 byte aligned virtual and physical addresses for
5269 * the allocated ADV_SG_BLOCK structure.
5270 */
5271 sg_block =
5272 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
5273 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005275 /*
5276 * Check if this is the first 'adv_sgblk_t' for the request.
5277 */
5278 if (reqp->sgblkp == NULL) {
5279 /* Request's first scatter-gather block. */
5280 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005282 /*
5283 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
5284 * address pointers.
5285 */
5286 scsiqp->sg_list_ptr = sg_block;
5287 scsiqp->sg_real_addr =
5288 cpu_to_le32(sg_block_paddr);
5289 } else {
5290 /* Request's second or later scatter-gather block. */
5291 sgblkp->next_sgblkp = reqp->sgblkp;
5292 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005294 /*
5295 * Point the previous ADV_SG_BLOCK structure to
5296 * the newly allocated ADV_SG_BLOCK structure.
5297 */
5298 ASC_ASSERT(prev_sg_block != NULL);
5299 prev_sg_block->sg_ptr =
5300 cpu_to_le32(sg_block_paddr);
5301 }
5302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005304 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
5305 sg_block->sg_list[i].sg_addr =
5306 cpu_to_le32(sg_dma_address(slp));
5307 sg_block->sg_list[i].sg_count =
5308 cpu_to_le32(sg_dma_len(slp));
5309 ASC_STATS_ADD(scp->device->host, sg_xfer,
5310 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005312 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
5313 sg_block->sg_cnt = i + 1;
5314 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
5315 return ADV_SUCCESS;
5316 }
5317 slp++;
5318 }
5319 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
5320 prev_sg_block = sg_block;
5321 }
5322 while (1);
5323 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324}
5325
5326/*
5327 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
5328 *
5329 * Interrupt callback function for the Narrow SCSI Asc Library.
5330 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005331static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005333 asc_board_t *boardp;
5334 struct scsi_cmnd *scp;
5335 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005337 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
5338 (ulong)asc_dvc_varp, (ulong)qdonep);
5339 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005340
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005341 /*
5342 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
5343 * command that has been completed.
5344 */
5345 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
5346 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005348 if (scp == NULL) {
5349 ASC_PRINT("asc_isr_callback: scp is NULL\n");
5350 return;
5351 }
5352 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005354 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005355 ASC_STATS(shost, callback);
5356 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005358 /*
5359 * If the request isn't found on the active queue, it may
5360 * have been removed to handle a reset request.
5361 * Display a message and return.
5362 */
5363 boardp = ASC_BOARDP(shost);
5364 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
5365 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
5366 ASC_PRINT2
5367 ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n",
5368 boardp->id, (ulong)scp);
5369 return;
5370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005372 /*
5373 * 'qdonep' contains the command's ending status.
5374 */
5375 switch (qdonep->d3.done_stat) {
5376 case QD_NO_ERROR:
5377 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
5378 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005380 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005381 * Check for an underrun condition.
5382 *
5383 * If there was no error and an underrun condition, then
Matthew Wilcox47d853c2007-07-26 11:41:33 -04005384 * return the number of underrun bytes.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005385 */
5386 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
5387 qdonep->remain_bytes <= scp->request_bufflen) {
5388 ASC_DBG1(1,
5389 "asc_isr_callback: underrun condition %u bytes\n",
5390 (unsigned)qdonep->remain_bytes);
5391 scp->resid = qdonep->remain_bytes;
5392 }
5393 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005395 case QD_WITH_ERROR:
5396 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
5397 switch (qdonep->d3.host_stat) {
5398 case QHSTA_NO_ERROR:
5399 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
5400 ASC_DBG(2,
5401 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
5402 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
5403 sizeof(scp->sense_buffer));
5404 /*
5405 * Note: The 'status_byte()' macro used by target drivers
5406 * defined in scsi.h shifts the status byte returned by
5407 * host drivers right by 1 bit. This is why target drivers
5408 * also use right shifted status byte definitions. For
5409 * instance target drivers use CHECK_CONDITION, defined to
5410 * 0x1, instead of the SCSI defined check condition value
5411 * of 0x2. Host drivers are supposed to return the status
5412 * byte as it is defined by SCSI.
5413 */
5414 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
5415 STATUS_BYTE(qdonep->d3.scsi_stat);
5416 } else {
5417 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
5418 }
5419 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005421 default:
5422 /* QHSTA error occurred */
5423 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
5424 qdonep->d3.host_stat);
5425 scp->result = HOST_BYTE(DID_BAD_TARGET);
5426 break;
5427 }
5428 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005430 case QD_ABORTED_BY_HOST:
5431 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
5432 scp->result =
5433 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
5434 scsi_msg) |
5435 STATUS_BYTE(qdonep->d3.scsi_stat);
5436 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005438 default:
5439 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
5440 qdonep->d3.done_stat);
5441 scp->result =
5442 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
5443 scsi_msg) |
5444 STATUS_BYTE(qdonep->d3.scsi_stat);
5445 break;
5446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005448 /*
5449 * If the 'init_tidmask' bit isn't already set for the target and the
5450 * current request finished normally, then set the bit for the target
5451 * to indicate that a device is present.
5452 */
5453 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
5454 qdonep->d3.done_stat == QD_NO_ERROR &&
5455 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
5456 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
5457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005459 /*
5460 * Because interrupts may be enabled by the 'struct scsi_cmnd' done
5461 * function, add the command to the end of the board's done queue.
5462 * The done function for the command will be called from
5463 * advansys_interrupt().
5464 */
5465 asc_enqueue(&boardp->done, scp, ASC_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005467 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468}
5469
5470/*
5471 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
5472 *
5473 * Callback function for the Wide SCSI Adv Library.
5474 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005475static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005477 asc_board_t *boardp;
5478 adv_req_t *reqp;
5479 adv_sgblk_t *sgblkp;
5480 struct scsi_cmnd *scp;
5481 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005482 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
5485 (ulong)adv_dvc_varp, (ulong)scsiqp);
5486 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005488 /*
5489 * Get the adv_req_t structure for the command that has been
5490 * completed. The adv_req_t structure actually contains the
5491 * completed ADV_SCSI_REQ_Q structure.
5492 */
5493 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
5494 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
5495 if (reqp == NULL) {
5496 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
5497 return;
5498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005500 /*
5501 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
5502 * command that has been completed.
5503 *
5504 * Note: The adv_req_t request structure and adv_sgblk_t structure,
5505 * if any, are dropped, because a board structure pointer can not be
5506 * determined.
5507 */
5508 scp = reqp->cmndp;
5509 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
5510 if (scp == NULL) {
5511 ASC_PRINT
5512 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
5513 return;
5514 }
5515 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005517 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005518 ASC_STATS(shost, callback);
5519 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005521 /*
5522 * If the request isn't found on the active queue, it may have been
5523 * removed to handle a reset request. Display a message and return.
5524 *
5525 * Note: Because the structure may still be in use don't attempt
5526 * to free the adv_req_t and adv_sgblk_t, if any, structures.
5527 */
5528 boardp = ASC_BOARDP(shost);
5529 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
5530 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
5531 ASC_PRINT2
5532 ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n",
5533 boardp->id, (ulong)scp);
5534 return;
5535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005537 /*
5538 * 'done_status' contains the command's ending status.
5539 */
5540 switch (scsiqp->done_status) {
5541 case QD_NO_ERROR:
5542 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
5543 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005545 /*
5546 * Check for an underrun condition.
5547 *
5548 * If there was no error and an underrun condition, then
5549 * then return the number of underrun bytes.
5550 */
5551 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
5552 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
5553 resid_cnt <= scp->request_bufflen) {
5554 ASC_DBG1(1,
5555 "adv_isr_callback: underrun condition %lu bytes\n",
5556 (ulong)resid_cnt);
5557 scp->resid = resid_cnt;
5558 }
5559 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005561 case QD_WITH_ERROR:
5562 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
5563 switch (scsiqp->host_status) {
5564 case QHSTA_NO_ERROR:
5565 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
5566 ASC_DBG(2,
5567 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
5568 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
5569 sizeof(scp->sense_buffer));
5570 /*
5571 * Note: The 'status_byte()' macro used by target drivers
5572 * defined in scsi.h shifts the status byte returned by
5573 * host drivers right by 1 bit. This is why target drivers
5574 * also use right shifted status byte definitions. For
5575 * instance target drivers use CHECK_CONDITION, defined to
5576 * 0x1, instead of the SCSI defined check condition value
5577 * of 0x2. Host drivers are supposed to return the status
5578 * byte as it is defined by SCSI.
5579 */
5580 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
5581 STATUS_BYTE(scsiqp->scsi_status);
5582 } else {
5583 scp->result = STATUS_BYTE(scsiqp->scsi_status);
5584 }
5585 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005587 default:
5588 /* Some other QHSTA error occurred. */
5589 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
5590 scsiqp->host_status);
5591 scp->result = HOST_BYTE(DID_BAD_TARGET);
5592 break;
5593 }
5594 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005596 case QD_ABORTED_BY_HOST:
5597 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
5598 scp->result =
5599 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
5600 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005602 default:
5603 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
5604 scsiqp->done_status);
5605 scp->result =
5606 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
5607 break;
5608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005610 /*
5611 * If the 'init_tidmask' bit isn't already set for the target and the
5612 * current request finished normally, then set the bit for the target
5613 * to indicate that a device is present.
5614 */
5615 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
5616 scsiqp->done_status == QD_NO_ERROR &&
5617 scsiqp->host_status == QHSTA_NO_ERROR) {
5618 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
5619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005621 /*
5622 * Because interrupts may be enabled by the 'struct scsi_cmnd' done
5623 * function, add the command to the end of the board's done queue.
5624 * The done function for the command will be called from
5625 * advansys_interrupt().
5626 */
5627 asc_enqueue(&boardp->done, scp, ASC_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005629 /*
5630 * Free all 'adv_sgblk_t' structures allocated for the request.
5631 */
5632 while ((sgblkp = reqp->sgblkp) != NULL) {
5633 /* Remove 'sgblkp' from the request list. */
5634 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005636 /* Add 'sgblkp' to the board free list. */
5637 sgblkp->next_sgblkp = boardp->adv_sgblkp;
5638 boardp->adv_sgblkp = sgblkp;
5639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005640
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005641 /*
5642 * Free the adv_req_t structure used with the command by adding
5643 * it back to the board free list.
5644 */
5645 reqp->next_reqp = boardp->adv_reqp;
5646 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005648 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005650 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651}
5652
5653/*
5654 * adv_async_callback() - Adv Library asynchronous event callback function.
5655 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005656static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005658 switch (code) {
5659 case ADV_ASYNC_SCSI_BUS_RESET_DET:
5660 /*
5661 * The firmware detected a SCSI Bus reset.
5662 */
5663 ASC_DBG(0,
5664 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
5665 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005667 case ADV_ASYNC_RDMA_FAILURE:
5668 /*
5669 * Handle RDMA failure by resetting the SCSI Bus and
5670 * possibly the chip if it is unresponsive. Log the error
5671 * with a unique code.
5672 */
5673 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
5674 AdvResetChipAndSB(adv_dvc_varp);
5675 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005676
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005677 case ADV_HOST_SCSI_BUS_RESET:
5678 /*
5679 * Host generated SCSI bus reset occurred.
5680 */
5681 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
5682 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005684 default:
5685 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
5686 break;
5687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688}
5689
5690/*
5691 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
5692 * to indicate a command is queued for the device.
5693 *
5694 * 'flag' may be either ASC_FRONT or ASC_BACK.
5695 *
5696 * 'REQPNEXT(reqp)' returns reqp's next pointer.
5697 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005698static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005699{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005700 int tid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005702 ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n",
5703 (ulong)ascq, (ulong)reqp, flag);
5704 ASC_ASSERT(reqp != NULL);
5705 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
5706 tid = REQPTID(reqp);
5707 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
5708 if (flag == ASC_FRONT) {
5709 reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
5710 ascq->q_first[tid] = reqp;
5711 /* If the queue was empty, set the last pointer. */
5712 if (ascq->q_last[tid] == NULL) {
5713 ascq->q_last[tid] = reqp;
5714 }
5715 } else { /* ASC_BACK */
5716 if (ascq->q_last[tid] != NULL) {
5717 ascq->q_last[tid]->host_scribble =
5718 (unsigned char *)reqp;
5719 }
5720 ascq->q_last[tid] = reqp;
5721 reqp->host_scribble = NULL;
5722 /* If the queue was empty, set the first pointer. */
5723 if (ascq->q_first[tid] == NULL) {
5724 ascq->q_first[tid] = reqp;
5725 }
5726 }
5727 /* The queue has at least one entry, set its bit. */
5728 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005730 /* Maintain request queue statistics. */
5731 ascq->q_tot_cnt[tid]++;
5732 ascq->q_cur_cnt[tid]++;
5733 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
5734 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
5735 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
5736 tid, ascq->q_max_cnt[tid]);
5737 }
5738 REQPTIME(reqp) = REQTIMESTAMP();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005740 ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp);
5741 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742}
5743
5744/*
5745 * Return first queued 'REQP' on the specified queue for
5746 * the specified target device. Clear the 'tidmask' bit for
5747 * the device if no more commands are left queued for it.
5748 *
5749 * 'REQPNEXT(reqp)' returns reqp's next pointer.
5750 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005751static REQP asc_dequeue(asc_queue_t *ascq, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005753 REQP reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005754
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005755 ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
5756 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
5757 if ((reqp = ascq->q_first[tid]) != NULL) {
5758 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
5759 ascq->q_first[tid] = REQPNEXT(reqp);
5760 /* If the queue is empty, clear its bit and the last pointer. */
5761 if (ascq->q_first[tid] == NULL) {
5762 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
5763 ASC_ASSERT(ascq->q_last[tid] == reqp);
5764 ascq->q_last[tid] = NULL;
5765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005767 /* Maintain request queue statistics. */
5768 ascq->q_cur_cnt[tid]--;
5769 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
5770 REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005772 }
5773 ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp);
5774 return reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775}
5776
5777/*
5778 * Return a pointer to a singly linked list of all the requests queued
5779 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
5780 *
5781 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
5782 * the last request returned in the singly linked list.
5783 *
5784 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
5785 * then all queued requests are concatenated into one list and
5786 * returned.
5787 *
5788 * Note: If 'lastpp' is used to append a new list to the end of
5789 * an old list, only change the old list last pointer if '*lastpp'
5790 * (or the function return value) is not NULL, i.e. use a temporary
5791 * variable for 'lastpp' and check its value after the function return
5792 * before assigning it to the list last pointer.
5793 *
5794 * Unfortunately collecting queuing time statistics adds overhead to
5795 * the function that isn't inherent to the function's algorithm.
5796 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005797static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005799 REQP firstp, lastp;
5800 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005802 ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
5803 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005805 /*
5806 * If 'tid' is not ASC_TID_ALL, return requests only for
5807 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
5808 * requests for all tids.
5809 */
5810 if (tid != ASC_TID_ALL) {
5811 /* Return all requests for the specified 'tid'. */
5812 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
5813 /* List is empty; Set first and last return pointers to NULL. */
5814 firstp = lastp = NULL;
5815 } else {
5816 firstp = ascq->q_first[tid];
5817 lastp = ascq->q_last[tid];
5818 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
5819 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005821 {
5822 REQP reqp;
5823 ascq->q_cur_cnt[tid] = 0;
5824 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
5825 REQTIMESTAT("asc_dequeue_list", ascq,
5826 reqp, tid);
5827 }
5828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005830 }
5831 } else {
5832 /* Return all requests for all tids. */
5833 firstp = lastp = NULL;
5834 for (i = 0; i <= ADV_MAX_TID; i++) {
5835 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
5836 if (firstp == NULL) {
5837 firstp = ascq->q_first[i];
5838 lastp = ascq->q_last[i];
5839 } else {
5840 ASC_ASSERT(lastp != NULL);
5841 lastp->host_scribble =
5842 (unsigned char *)ascq->q_first[i];
5843 lastp = ascq->q_last[i];
5844 }
5845 ascq->q_first[i] = ascq->q_last[i] = NULL;
5846 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005848 ascq->q_cur_cnt[i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005850 }
5851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005853 {
5854 REQP reqp;
5855 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
5856 REQTIMESTAT("asc_dequeue_list", ascq, reqp,
5857 reqp->device->id);
5858 }
5859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005861 }
5862 if (lastpp) {
5863 *lastpp = lastp;
5864 }
5865 ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp);
5866 return firstp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867}
5868
5869/*
5870 * Remove the specified 'REQP' from the specified queue for
5871 * the specified target device. Clear the 'tidmask' bit for the
5872 * device if no more commands are left queued for it.
5873 *
5874 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
5875 *
5876 * Return ASC_TRUE if the command was found and removed,
5877 * otherwise return ASC_FALSE.
5878 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005879static int asc_rmqueue(asc_queue_t *ascq, REQP reqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005881 REQP currp, prevp;
5882 int tid;
5883 int ret = ASC_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005885 ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n",
5886 (ulong)ascq, (ulong)reqp);
5887 ASC_ASSERT(reqp != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005889 tid = REQPTID(reqp);
5890 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005892 /*
5893 * Handle the common case of 'reqp' being the first
5894 * entry on the queue.
5895 */
5896 if (reqp == ascq->q_first[tid]) {
5897 ret = ASC_TRUE;
5898 ascq->q_first[tid] = REQPNEXT(reqp);
5899 /* If the queue is now empty, clear its bit and the last pointer. */
5900 if (ascq->q_first[tid] == NULL) {
5901 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
5902 ASC_ASSERT(ascq->q_last[tid] == reqp);
5903 ascq->q_last[tid] = NULL;
5904 }
5905 } else if (ascq->q_first[tid] != NULL) {
5906 ASC_ASSERT(ascq->q_last[tid] != NULL);
5907 /*
5908 * Because the case of 'reqp' being the first entry has been
5909 * handled above and it is known the queue is not empty, if
5910 * 'reqp' is found on the queue it is guaranteed the queue will
5911 * not become empty and that 'q_first[tid]' will not be changed.
5912 *
5913 * Set 'prevp' to the first entry, 'currp' to the second entry,
5914 * and search for 'reqp'.
5915 */
5916 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
5917 currp; prevp = currp, currp = REQPNEXT(currp)) {
5918 if (currp == reqp) {
5919 ret = ASC_TRUE;
5920 prevp->host_scribble =
5921 (unsigned char *)REQPNEXT(currp);
5922 reqp->host_scribble = NULL;
5923 if (ascq->q_last[tid] == reqp) {
5924 ascq->q_last[tid] = prevp;
5925 }
5926 break;
5927 }
5928 }
5929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005931 /* Maintain request queue statistics. */
5932 if (ret == ASC_TRUE) {
5933 ascq->q_cur_cnt[tid]--;
5934 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
5935 }
5936 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005938 ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret);
5939 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005940}
5941
5942/*
5943 * Execute as many queued requests as possible for the specified queue.
5944 *
5945 * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd.
5946 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005947static void asc_execute_queue(asc_queue_t *ascq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005948{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005949 ADV_SCSI_BIT_ID_TYPE scan_tidmask;
5950 REQP reqp;
5951 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005953 ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq);
5954 /*
5955 * Execute queued commands for devices attached to
5956 * the current board in round-robin fashion.
5957 */
5958 scan_tidmask = ascq->q_tidmask;
5959 do {
5960 for (i = 0; i <= ADV_MAX_TID; i++) {
5961 if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
5962 if ((reqp = asc_dequeue(ascq, i)) == NULL) {
5963 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
5964 } else
5965 if (asc_execute_scsi_cmnd
5966 ((struct scsi_cmnd *)reqp)
5967 == ASC_BUSY) {
5968 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
5969 /*
5970 * The request returned ASC_BUSY. Enqueue at the front of
5971 * target's waiting list to maintain correct ordering.
5972 */
5973 asc_enqueue(ascq, reqp, ASC_FRONT);
5974 }
5975 }
5976 }
5977 } while (scan_tidmask);
5978 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979}
5980
5981#ifdef CONFIG_PROC_FS
5982/*
5983 * asc_prt_board_devices()
5984 *
5985 * Print driver information for devices attached to the board.
5986 *
5987 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5988 * cf. asc_prt_line().
5989 *
5990 * Return the number of characters copied into 'cp'. No more than
5991 * 'cplen' characters will be copied to 'cp'.
5992 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005993static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005995 asc_board_t *boardp;
5996 int leftlen;
5997 int totlen;
5998 int len;
5999 int chip_scsi_id;
6000 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006002 boardp = ASC_BOARDP(shost);
6003 leftlen = cplen;
6004 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006006 len = asc_prt_line(cp, leftlen,
6007 "\nDevice Information for AdvanSys SCSI Host %d:\n",
6008 shost->host_no);
6009 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006011 if (ASC_NARROW_BOARD(boardp)) {
6012 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6013 } else {
6014 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006017 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
6018 ASC_PRT_NEXT();
6019 for (i = 0; i <= ADV_MAX_TID; i++) {
6020 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
6021 len = asc_prt_line(cp, leftlen, " %X,", i);
6022 ASC_PRT_NEXT();
6023 }
6024 }
6025 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
6026 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006028 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029}
6030
6031/*
6032 * Display Wide Board BIOS Information.
6033 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006034static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006036 asc_board_t *boardp;
6037 int leftlen;
6038 int totlen;
6039 int len;
6040 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006042 boardp = ASC_BOARDP(shost);
6043 leftlen = cplen;
6044 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006046 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
6047 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006049 /*
6050 * If the BIOS saved a valid signature, then fill in
6051 * the BIOS code segment base address.
6052 */
6053 if (boardp->bios_signature != 0x55AA) {
6054 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
6055 ASC_PRT_NEXT();
6056 len = asc_prt_line(cp, leftlen,
6057 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
6058 ASC_PRT_NEXT();
6059 len = asc_prt_line(cp, leftlen,
6060 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
6061 ASC_PRT_NEXT();
6062 } else {
6063 major = (boardp->bios_version >> 12) & 0xF;
6064 minor = (boardp->bios_version >> 8) & 0xF;
6065 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006067 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
6068 major, minor,
6069 letter >= 26 ? '?' : letter + 'A');
6070 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006072 /*
6073 * Current available ROM BIOS release is 3.1I for UW
6074 * and 3.2I for U2W. This code doesn't differentiate
6075 * UW and U2W boards.
6076 */
6077 if (major < 3 || (major <= 3 && minor < 1) ||
6078 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
6079 len = asc_prt_line(cp, leftlen,
6080 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
6081 ASC_PRT_NEXT();
6082 len = asc_prt_line(cp, leftlen,
6083 "ftp://ftp.connectcom.net/pub\n");
6084 ASC_PRT_NEXT();
6085 }
6086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006088 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089}
6090
6091/*
6092 * Add serial number to information bar if signature AAh
6093 * is found in at bit 15-9 (7 bits) of word 1.
6094 *
6095 * Serial Number consists fo 12 alpha-numeric digits.
6096 *
6097 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
6098 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
6099 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
6100 * 5 - Product revision (A-J) Word0: " "
6101 *
6102 * Signature Word1: 15-9 (7 bits)
6103 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
6104 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
6105 *
6106 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
6107 *
6108 * Note 1: Only production cards will have a serial number.
6109 *
6110 * Note 2: Signature is most significant 7 bits (0xFE).
6111 *
6112 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
6113 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006114static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006116 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006118 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
6119 return ASC_FALSE;
6120 } else {
6121 /*
6122 * First word - 6 digits.
6123 */
6124 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006125
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006126 /* Product type - 1st digit. */
6127 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
6128 /* Product type is P=Prototype */
6129 *cp += 0x8;
6130 }
6131 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006133 /* Manufacturing location - 2nd digit. */
6134 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006136 /* Product ID - 3rd, 4th digits. */
6137 num = w & 0x3FF;
6138 *cp++ = '0' + (num / 100);
6139 num %= 100;
6140 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006142 /* Product revision - 5th digit. */
6143 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006145 /*
6146 * Second word
6147 */
6148 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006150 /*
6151 * Year - 6th digit.
6152 *
6153 * If bit 15 of third word is set, then the
6154 * last digit of the year is greater than 7.
6155 */
6156 if (serialnum[2] & 0x8000) {
6157 *cp++ = '8' + ((w & 0x1C0) >> 6);
6158 } else {
6159 *cp++ = '0' + ((w & 0x1C0) >> 6);
6160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006162 /* Week of year - 7th, 8th digits. */
6163 num = w & 0x003F;
6164 *cp++ = '0' + num / 10;
6165 num %= 10;
6166 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006168 /*
6169 * Third word
6170 */
6171 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006173 /* Serial number - 9th digit. */
6174 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006175
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006176 /* 10th, 11th, 12th digits. */
6177 num = w % 1000;
6178 *cp++ = '0' + num / 100;
6179 num %= 100;
6180 *cp++ = '0' + num / 10;
6181 num %= 10;
6182 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006184 *cp = '\0'; /* Null Terminate the string. */
6185 return ASC_TRUE;
6186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187}
6188
6189/*
6190 * asc_prt_asc_board_eeprom()
6191 *
6192 * Print board EEPROM configuration.
6193 *
6194 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6195 * cf. asc_prt_line().
6196 *
6197 * Return the number of characters copied into 'cp'. No more than
6198 * 'cplen' characters will be copied to 'cp'.
6199 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006200static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006202 asc_board_t *boardp;
6203 ASC_DVC_VAR *asc_dvc_varp;
6204 int leftlen;
6205 int totlen;
6206 int len;
6207 ASCEEP_CONFIG *ep;
6208 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006209#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006210 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07006211#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006212 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006214 boardp = ASC_BOARDP(shost);
6215 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6216 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006218 leftlen = cplen;
6219 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006221 len = asc_prt_line(cp, leftlen,
6222 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
6223 shost->host_no);
6224 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006226 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
6227 == ASC_TRUE) {
6228 len =
6229 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
6230 serialstr);
6231 ASC_PRT_NEXT();
6232 } else {
6233 if (ep->adapter_info[5] == 0xBB) {
6234 len = asc_prt_line(cp, leftlen,
6235 " Default Settings Used for EEPROM-less Adapter.\n");
6236 ASC_PRT_NEXT();
6237 } else {
6238 len = asc_prt_line(cp, leftlen,
6239 " Serial Number Signature Not Present.\n");
6240 ASC_PRT_NEXT();
6241 }
6242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006244 len = asc_prt_line(cp, leftlen,
6245 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6246 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
6247 ep->max_tag_qng);
6248 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006250 len = asc_prt_line(cp, leftlen,
6251 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
6252 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006254 len = asc_prt_line(cp, leftlen, " Target ID: ");
6255 ASC_PRT_NEXT();
6256 for (i = 0; i <= ASC_MAX_TID; i++) {
6257 len = asc_prt_line(cp, leftlen, " %d", i);
6258 ASC_PRT_NEXT();
6259 }
6260 len = asc_prt_line(cp, leftlen, "\n");
6261 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006263 len = asc_prt_line(cp, leftlen, " Disconnects: ");
6264 ASC_PRT_NEXT();
6265 for (i = 0; i <= ASC_MAX_TID; i++) {
6266 len = asc_prt_line(cp, leftlen, " %c",
6267 (ep->
6268 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6269 'N');
6270 ASC_PRT_NEXT();
6271 }
6272 len = asc_prt_line(cp, leftlen, "\n");
6273 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006275 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
6276 ASC_PRT_NEXT();
6277 for (i = 0; i <= ASC_MAX_TID; i++) {
6278 len = asc_prt_line(cp, leftlen, " %c",
6279 (ep->
6280 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6281 'N');
6282 ASC_PRT_NEXT();
6283 }
6284 len = asc_prt_line(cp, leftlen, "\n");
6285 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006286
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006287 len = asc_prt_line(cp, leftlen, " Start Motor: ");
6288 ASC_PRT_NEXT();
6289 for (i = 0; i <= ASC_MAX_TID; i++) {
6290 len = asc_prt_line(cp, leftlen, " %c",
6291 (ep->
6292 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6293 'N');
6294 ASC_PRT_NEXT();
6295 }
6296 len = asc_prt_line(cp, leftlen, "\n");
6297 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006299 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6300 ASC_PRT_NEXT();
6301 for (i = 0; i <= ASC_MAX_TID; i++) {
6302 len = asc_prt_line(cp, leftlen, " %c",
6303 (ep->
6304 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6305 'N');
6306 ASC_PRT_NEXT();
6307 }
6308 len = asc_prt_line(cp, leftlen, "\n");
6309 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310
6311#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006312 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
6313 len = asc_prt_line(cp, leftlen,
6314 " Host ISA DMA speed: %d MB/S\n",
6315 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
6316 ASC_PRT_NEXT();
6317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006318#endif /* CONFIG_ISA */
6319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006321}
6322
6323/*
6324 * asc_prt_adv_board_eeprom()
6325 *
6326 * Print board EEPROM configuration.
6327 *
6328 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6329 * cf. asc_prt_line().
6330 *
6331 * Return the number of characters copied into 'cp'. No more than
6332 * 'cplen' characters will be copied to 'cp'.
6333 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006334static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006336 asc_board_t *boardp;
6337 ADV_DVC_VAR *adv_dvc_varp;
6338 int leftlen;
6339 int totlen;
6340 int len;
6341 int i;
6342 char *termstr;
6343 uchar serialstr[13];
6344 ADVEEP_3550_CONFIG *ep_3550 = NULL;
6345 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
6346 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
6347 ushort word;
6348 ushort *wordp;
6349 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006351 boardp = ASC_BOARDP(shost);
6352 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6353 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6354 ep_3550 = &boardp->eep_config.adv_3550_eep;
6355 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6356 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
6357 } else {
6358 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
6359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006361 leftlen = cplen;
6362 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006364 len = asc_prt_line(cp, leftlen,
6365 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
6366 shost->host_no);
6367 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006368
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006369 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6370 wordp = &ep_3550->serial_number_word1;
6371 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6372 wordp = &ep_38C0800->serial_number_word1;
6373 } else {
6374 wordp = &ep_38C1600->serial_number_word1;
6375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006377 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
6378 len =
6379 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
6380 serialstr);
6381 ASC_PRT_NEXT();
6382 } else {
6383 len = asc_prt_line(cp, leftlen,
6384 " Serial Number Signature Not Present.\n");
6385 ASC_PRT_NEXT();
6386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006387
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006388 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6389 len = asc_prt_line(cp, leftlen,
6390 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6391 ep_3550->adapter_scsi_id,
6392 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
6393 ASC_PRT_NEXT();
6394 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6395 len = asc_prt_line(cp, leftlen,
6396 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6397 ep_38C0800->adapter_scsi_id,
6398 ep_38C0800->max_host_qng,
6399 ep_38C0800->max_dvc_qng);
6400 ASC_PRT_NEXT();
6401 } else {
6402 len = asc_prt_line(cp, leftlen,
6403 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6404 ep_38C1600->adapter_scsi_id,
6405 ep_38C1600->max_host_qng,
6406 ep_38C1600->max_dvc_qng);
6407 ASC_PRT_NEXT();
6408 }
6409 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6410 word = ep_3550->termination;
6411 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6412 word = ep_38C0800->termination_lvd;
6413 } else {
6414 word = ep_38C1600->termination_lvd;
6415 }
6416 switch (word) {
6417 case 1:
6418 termstr = "Low Off/High Off";
6419 break;
6420 case 2:
6421 termstr = "Low Off/High On";
6422 break;
6423 case 3:
6424 termstr = "Low On/High On";
6425 break;
6426 default:
6427 case 0:
6428 termstr = "Automatic";
6429 break;
6430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006432 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6433 len = asc_prt_line(cp, leftlen,
6434 " termination: %u (%s), bios_ctrl: 0x%x\n",
6435 ep_3550->termination, termstr,
6436 ep_3550->bios_ctrl);
6437 ASC_PRT_NEXT();
6438 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6439 len = asc_prt_line(cp, leftlen,
6440 " termination: %u (%s), bios_ctrl: 0x%x\n",
6441 ep_38C0800->termination_lvd, termstr,
6442 ep_38C0800->bios_ctrl);
6443 ASC_PRT_NEXT();
6444 } else {
6445 len = asc_prt_line(cp, leftlen,
6446 " termination: %u (%s), bios_ctrl: 0x%x\n",
6447 ep_38C1600->termination_lvd, termstr,
6448 ep_38C1600->bios_ctrl);
6449 ASC_PRT_NEXT();
6450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006452 len = asc_prt_line(cp, leftlen, " Target ID: ");
6453 ASC_PRT_NEXT();
6454 for (i = 0; i <= ADV_MAX_TID; i++) {
6455 len = asc_prt_line(cp, leftlen, " %X", i);
6456 ASC_PRT_NEXT();
6457 }
6458 len = asc_prt_line(cp, leftlen, "\n");
6459 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006461 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6462 word = ep_3550->disc_enable;
6463 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6464 word = ep_38C0800->disc_enable;
6465 } else {
6466 word = ep_38C1600->disc_enable;
6467 }
6468 len = asc_prt_line(cp, leftlen, " Disconnects: ");
6469 ASC_PRT_NEXT();
6470 for (i = 0; i <= ADV_MAX_TID; i++) {
6471 len = asc_prt_line(cp, leftlen, " %c",
6472 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6473 ASC_PRT_NEXT();
6474 }
6475 len = asc_prt_line(cp, leftlen, "\n");
6476 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006478 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6479 word = ep_3550->tagqng_able;
6480 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6481 word = ep_38C0800->tagqng_able;
6482 } else {
6483 word = ep_38C1600->tagqng_able;
6484 }
6485 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
6486 ASC_PRT_NEXT();
6487 for (i = 0; i <= ADV_MAX_TID; i++) {
6488 len = asc_prt_line(cp, leftlen, " %c",
6489 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6490 ASC_PRT_NEXT();
6491 }
6492 len = asc_prt_line(cp, leftlen, "\n");
6493 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006494
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006495 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6496 word = ep_3550->start_motor;
6497 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6498 word = ep_38C0800->start_motor;
6499 } else {
6500 word = ep_38C1600->start_motor;
6501 }
6502 len = asc_prt_line(cp, leftlen, " Start Motor: ");
6503 ASC_PRT_NEXT();
6504 for (i = 0; i <= ADV_MAX_TID; i++) {
6505 len = asc_prt_line(cp, leftlen, " %c",
6506 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6507 ASC_PRT_NEXT();
6508 }
6509 len = asc_prt_line(cp, leftlen, "\n");
6510 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006511
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006512 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6513 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6514 ASC_PRT_NEXT();
6515 for (i = 0; i <= ADV_MAX_TID; i++) {
6516 len = asc_prt_line(cp, leftlen, " %c",
6517 (ep_3550->
6518 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
6519 'Y' : 'N');
6520 ASC_PRT_NEXT();
6521 }
6522 len = asc_prt_line(cp, leftlen, "\n");
6523 ASC_PRT_NEXT();
6524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006525
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006526 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6527 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
6528 ASC_PRT_NEXT();
6529 for (i = 0; i <= ADV_MAX_TID; i++) {
6530 len = asc_prt_line(cp, leftlen, " %c",
6531 (ep_3550->
6532 ultra_able & ADV_TID_TO_TIDMASK(i))
6533 ? 'Y' : 'N');
6534 ASC_PRT_NEXT();
6535 }
6536 len = asc_prt_line(cp, leftlen, "\n");
6537 ASC_PRT_NEXT();
6538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006540 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6541 word = ep_3550->wdtr_able;
6542 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6543 word = ep_38C0800->wdtr_able;
6544 } else {
6545 word = ep_38C1600->wdtr_able;
6546 }
6547 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
6548 ASC_PRT_NEXT();
6549 for (i = 0; i <= ADV_MAX_TID; i++) {
6550 len = asc_prt_line(cp, leftlen, " %c",
6551 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6552 ASC_PRT_NEXT();
6553 }
6554 len = asc_prt_line(cp, leftlen, "\n");
6555 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006557 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
6558 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
6559 len = asc_prt_line(cp, leftlen,
6560 " Synchronous Transfer Speed (Mhz):\n ");
6561 ASC_PRT_NEXT();
6562 for (i = 0; i <= ADV_MAX_TID; i++) {
6563 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006564
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006565 if (i == 0) {
6566 sdtr_speed = adv_dvc_varp->sdtr_speed1;
6567 } else if (i == 4) {
6568 sdtr_speed = adv_dvc_varp->sdtr_speed2;
6569 } else if (i == 8) {
6570 sdtr_speed = adv_dvc_varp->sdtr_speed3;
6571 } else if (i == 12) {
6572 sdtr_speed = adv_dvc_varp->sdtr_speed4;
6573 }
6574 switch (sdtr_speed & ADV_MAX_TID) {
6575 case 0:
6576 speed_str = "Off";
6577 break;
6578 case 1:
6579 speed_str = " 5";
6580 break;
6581 case 2:
6582 speed_str = " 10";
6583 break;
6584 case 3:
6585 speed_str = " 20";
6586 break;
6587 case 4:
6588 speed_str = " 40";
6589 break;
6590 case 5:
6591 speed_str = " 80";
6592 break;
6593 default:
6594 speed_str = "Unk";
6595 break;
6596 }
6597 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
6598 ASC_PRT_NEXT();
6599 if (i == 7) {
6600 len = asc_prt_line(cp, leftlen, "\n ");
6601 ASC_PRT_NEXT();
6602 }
6603 sdtr_speed >>= 4;
6604 }
6605 len = asc_prt_line(cp, leftlen, "\n");
6606 ASC_PRT_NEXT();
6607 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006608
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006609 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006610}
6611
6612/*
6613 * asc_prt_driver_conf()
6614 *
6615 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6616 * cf. asc_prt_line().
6617 *
6618 * Return the number of characters copied into 'cp'. No more than
6619 * 'cplen' characters will be copied to 'cp'.
6620 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006621static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006622{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006623 asc_board_t *boardp;
6624 int leftlen;
6625 int totlen;
6626 int len;
6627 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006629 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006630
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006631 leftlen = cplen;
6632 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006633
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006634 len = asc_prt_line(cp, leftlen,
6635 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
6636 shost->host_no);
6637 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006638
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006639 len = asc_prt_line(cp, leftlen,
6640 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
6641 shost->host_busy, shost->last_reset, shost->max_id,
6642 shost->max_lun, shost->max_channel);
6643 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006644
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006645 len = asc_prt_line(cp, leftlen,
6646 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
6647 shost->unique_id, shost->can_queue, shost->this_id,
6648 shost->sg_tablesize, shost->cmd_per_lun);
6649 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006651 len = asc_prt_line(cp, leftlen,
6652 " unchecked_isa_dma %d, use_clustering %d\n",
6653 shost->unchecked_isa_dma, shost->use_clustering);
6654 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006655
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006656 len = asc_prt_line(cp, leftlen,
6657 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
6658 boardp->flags, boardp->last_reset, jiffies,
6659 boardp->asc_n_io_port);
6660 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006661
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04006662 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006663 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006664
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006665 if (ASC_NARROW_BOARD(boardp)) {
6666 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6667 } else {
6668 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006671 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006672}
6673
6674/*
6675 * asc_prt_asc_board_info()
6676 *
6677 * Print dynamic board configuration information.
6678 *
6679 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6680 * cf. asc_prt_line().
6681 *
6682 * Return the number of characters copied into 'cp'. No more than
6683 * 'cplen' characters will be copied to 'cp'.
6684 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006685static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006686{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006687 asc_board_t *boardp;
6688 int chip_scsi_id;
6689 int leftlen;
6690 int totlen;
6691 int len;
6692 ASC_DVC_VAR *v;
6693 ASC_DVC_CFG *c;
6694 int i;
6695 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006697 boardp = ASC_BOARDP(shost);
6698 v = &boardp->dvc_var.asc_dvc_var;
6699 c = &boardp->dvc_cfg.asc_dvc_cfg;
6700 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006702 leftlen = cplen;
6703 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006705 len = asc_prt_line(cp, leftlen,
6706 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
6707 shost->host_no);
6708 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006709
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006710 len = asc_prt_line(cp, leftlen,
6711 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
6712 c->chip_version, c->lib_version, c->lib_serial_no,
6713 c->mcode_date);
6714 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006716 len = asc_prt_line(cp, leftlen,
6717 " mcode_version 0x%x, err_code %u\n",
6718 c->mcode_version, v->err_code);
6719 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006721 /* Current number of commands waiting for the host. */
6722 len = asc_prt_line(cp, leftlen,
6723 " Total Command Pending: %d\n", v->cur_total_qng);
6724 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006725
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006726 len = asc_prt_line(cp, leftlen, " Command Queuing:");
6727 ASC_PRT_NEXT();
6728 for (i = 0; i <= ASC_MAX_TID; i++) {
6729 if ((chip_scsi_id == i) ||
6730 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6731 continue;
6732 }
6733 len = asc_prt_line(cp, leftlen, " %X:%c",
6734 i,
6735 (v->
6736 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
6737 '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 /* Current number of commands waiting for a device. */
6744 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
6745 ASC_PRT_NEXT();
6746 for (i = 0; i <= ASC_MAX_TID; i++) {
6747 if ((chip_scsi_id == i) ||
6748 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6749 continue;
6750 }
6751 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
6752 ASC_PRT_NEXT();
6753 }
6754 len = asc_prt_line(cp, leftlen, "\n");
6755 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006756
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006757 /* Current limit on number of commands that can be sent to a device. */
6758 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
6759 ASC_PRT_NEXT();
6760 for (i = 0; i <= ASC_MAX_TID; i++) {
6761 if ((chip_scsi_id == i) ||
6762 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6763 continue;
6764 }
6765 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
6766 ASC_PRT_NEXT();
6767 }
6768 len = asc_prt_line(cp, leftlen, "\n");
6769 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006770
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006771 /* Indicate whether the device has returned queue full status. */
6772 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
6773 ASC_PRT_NEXT();
6774 for (i = 0; i <= ASC_MAX_TID; i++) {
6775 if ((chip_scsi_id == i) ||
6776 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6777 continue;
6778 }
6779 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
6780 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
6781 i, boardp->queue_full_cnt[i]);
6782 } else {
6783 len = asc_prt_line(cp, leftlen, " %X:N", i);
6784 }
6785 ASC_PRT_NEXT();
6786 }
6787 len = asc_prt_line(cp, leftlen, "\n");
6788 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006789
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006790 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6791 ASC_PRT_NEXT();
6792 for (i = 0; i <= ASC_MAX_TID; i++) {
6793 if ((chip_scsi_id == i) ||
6794 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6795 continue;
6796 }
6797 len = asc_prt_line(cp, leftlen, " %X:%c",
6798 i,
6799 (v->
6800 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6801 'N');
6802 ASC_PRT_NEXT();
6803 }
6804 len = asc_prt_line(cp, leftlen, "\n");
6805 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006807 for (i = 0; i <= ASC_MAX_TID; i++) {
6808 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006809
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006810 if ((chip_scsi_id == i) ||
6811 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
6812 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
6813 continue;
6814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006815
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006816 len = asc_prt_line(cp, leftlen, " %X:", i);
6817 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006818
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006819 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
6820 len = asc_prt_line(cp, leftlen, " Asynchronous");
6821 ASC_PRT_NEXT();
6822 } else {
6823 syn_period_ix =
6824 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
6825 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006826
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006827 len = asc_prt_line(cp, leftlen,
6828 " Transfer Period Factor: %d (%d.%d Mhz),",
6829 v->sdtr_period_tbl[syn_period_ix],
6830 250 /
6831 v->sdtr_period_tbl[syn_period_ix],
6832 ASC_TENTHS(250,
6833 v->
6834 sdtr_period_tbl
6835 [syn_period_ix]));
6836 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006838 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
6839 boardp->
6840 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
6841 ASC_PRT_NEXT();
6842 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006844 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
6845 len = asc_prt_line(cp, leftlen, "*\n");
6846 renegotiate = 1;
6847 } else {
6848 len = asc_prt_line(cp, leftlen, "\n");
6849 }
6850 ASC_PRT_NEXT();
6851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006852
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006853 if (renegotiate) {
6854 len = asc_prt_line(cp, leftlen,
6855 " * = Re-negotiation pending before next command.\n");
6856 ASC_PRT_NEXT();
6857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006859 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006860}
6861
6862/*
6863 * asc_prt_adv_board_info()
6864 *
6865 * Print dynamic board configuration information.
6866 *
6867 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6868 * cf. asc_prt_line().
6869 *
6870 * Return the number of characters copied into 'cp'. No more than
6871 * 'cplen' characters will be copied to 'cp'.
6872 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006873static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006874{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006875 asc_board_t *boardp;
6876 int leftlen;
6877 int totlen;
6878 int len;
6879 int i;
6880 ADV_DVC_VAR *v;
6881 ADV_DVC_CFG *c;
6882 AdvPortAddr iop_base;
6883 ushort chip_scsi_id;
6884 ushort lramword;
6885 uchar lrambyte;
6886 ushort tagqng_able;
6887 ushort sdtr_able, wdtr_able;
6888 ushort wdtr_done, sdtr_done;
6889 ushort period = 0;
6890 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006891
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006892 boardp = ASC_BOARDP(shost);
6893 v = &boardp->dvc_var.adv_dvc_var;
6894 c = &boardp->dvc_cfg.adv_dvc_cfg;
6895 iop_base = v->iop_base;
6896 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006897
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006898 leftlen = cplen;
6899 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006900
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006901 len = asc_prt_line(cp, leftlen,
6902 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
6903 shost->host_no);
6904 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006906 len = asc_prt_line(cp, leftlen,
6907 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
6908 v->iop_base,
6909 AdvReadWordRegister(iop_base,
6910 IOPW_SCSI_CFG1) & CABLE_DETECT,
6911 v->err_code);
6912 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006913
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006914 len = asc_prt_line(cp, leftlen,
6915 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
6916 c->chip_version, c->lib_version, c->mcode_date,
6917 c->mcode_version);
6918 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006920 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6921 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
6922 ASC_PRT_NEXT();
6923 for (i = 0; i <= ADV_MAX_TID; i++) {
6924 if ((chip_scsi_id == i) ||
6925 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6926 continue;
6927 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006929 len = asc_prt_line(cp, leftlen, " %X:%c",
6930 i,
6931 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6932 'N');
6933 ASC_PRT_NEXT();
6934 }
6935 len = asc_prt_line(cp, leftlen, "\n");
6936 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006938 len = asc_prt_line(cp, leftlen, " Queue Limit:");
6939 ASC_PRT_NEXT();
6940 for (i = 0; i <= ADV_MAX_TID; i++) {
6941 if ((chip_scsi_id == i) ||
6942 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6943 continue;
6944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006945
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006946 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
6947 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006949 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
6950 ASC_PRT_NEXT();
6951 }
6952 len = asc_prt_line(cp, leftlen, "\n");
6953 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006954
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006955 len = asc_prt_line(cp, leftlen, " Command Pending:");
6956 ASC_PRT_NEXT();
6957 for (i = 0; i <= ADV_MAX_TID; i++) {
6958 if ((chip_scsi_id == i) ||
6959 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6960 continue;
6961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006963 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
6964 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006966 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
6967 ASC_PRT_NEXT();
6968 }
6969 len = asc_prt_line(cp, leftlen, "\n");
6970 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006972 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6973 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
6974 ASC_PRT_NEXT();
6975 for (i = 0; i <= ADV_MAX_TID; i++) {
6976 if ((chip_scsi_id == i) ||
6977 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6978 continue;
6979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006981 len = asc_prt_line(cp, leftlen, " %X:%c",
6982 i,
6983 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6984 'N');
6985 ASC_PRT_NEXT();
6986 }
6987 len = asc_prt_line(cp, leftlen, "\n");
6988 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006990 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
6991 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
6992 ASC_PRT_NEXT();
6993 for (i = 0; i <= ADV_MAX_TID; i++) {
6994 if ((chip_scsi_id == i) ||
6995 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6996 continue;
6997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006999 AdvReadWordLram(iop_base,
7000 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
7001 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007003 len = asc_prt_line(cp, leftlen, " %X:%d",
7004 i, (lramword & 0x8000) ? 16 : 8);
7005 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007006
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007007 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
7008 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7009 len = asc_prt_line(cp, leftlen, "*");
7010 ASC_PRT_NEXT();
7011 renegotiate = 1;
7012 }
7013 }
7014 len = asc_prt_line(cp, leftlen, "\n");
7015 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007017 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7018 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
7019 ASC_PRT_NEXT();
7020 for (i = 0; i <= ADV_MAX_TID; i++) {
7021 if ((chip_scsi_id == i) ||
7022 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7023 continue;
7024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007025
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007026 len = asc_prt_line(cp, leftlen, " %X:%c",
7027 i,
7028 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7029 'N');
7030 ASC_PRT_NEXT();
7031 }
7032 len = asc_prt_line(cp, leftlen, "\n");
7033 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007035 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
7036 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007038 AdvReadWordLram(iop_base,
7039 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
7040 lramword);
7041 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007043 if ((chip_scsi_id == i) ||
7044 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
7045 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
7046 continue;
7047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007048
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007049 len = asc_prt_line(cp, leftlen, " %X:", i);
7050 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007051
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007052 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
7053 len = asc_prt_line(cp, leftlen, " Asynchronous");
7054 ASC_PRT_NEXT();
7055 } else {
7056 len =
7057 asc_prt_line(cp, leftlen,
7058 " Transfer Period Factor: ");
7059 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007061 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
7062 len =
7063 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
7064 ASC_PRT_NEXT();
7065 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
7066 len =
7067 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
7068 ASC_PRT_NEXT();
7069 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007071 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007073 if (period == 0) { /* Should never happen. */
7074 len =
7075 asc_prt_line(cp, leftlen,
7076 "%d (? Mhz), ");
7077 ASC_PRT_NEXT();
7078 } else {
7079 len = asc_prt_line(cp, leftlen,
7080 "%d (%d.%d Mhz),",
7081 period, 250 / period,
7082 ASC_TENTHS(250,
7083 period));
7084 ASC_PRT_NEXT();
7085 }
7086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007088 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
7089 lramword & 0x1F);
7090 ASC_PRT_NEXT();
7091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007092
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007093 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7094 len = asc_prt_line(cp, leftlen, "*\n");
7095 renegotiate = 1;
7096 } else {
7097 len = asc_prt_line(cp, leftlen, "\n");
7098 }
7099 ASC_PRT_NEXT();
7100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007102 if (renegotiate) {
7103 len = asc_prt_line(cp, leftlen,
7104 " * = Re-negotiation pending before next command.\n");
7105 ASC_PRT_NEXT();
7106 }
7107
7108 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007109}
7110
7111/*
7112 * asc_proc_copy()
7113 *
7114 * Copy proc information to a read buffer taking into account the current
7115 * read offset in the file and the remaining space in the read buffer.
7116 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007117static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07007118asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007119 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007120{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007121 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007122
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007123 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
7124 (unsigned)offset, (unsigned)advoffset, cplen);
7125 if (offset <= advoffset) {
7126 /* Read offset below current offset, copy everything. */
7127 cnt = min(cplen, leftlen);
7128 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
7129 (ulong)curbuf, (ulong)cp, cnt);
7130 memcpy(curbuf, cp, cnt);
7131 } else if (offset < advoffset + cplen) {
7132 /* Read offset within current range, partial copy. */
7133 cnt = (advoffset + cplen) - offset;
7134 cp = (cp + cplen) - cnt;
7135 cnt = min(cnt, leftlen);
7136 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
7137 (ulong)curbuf, (ulong)cp, cnt);
7138 memcpy(curbuf, cp, cnt);
7139 }
7140 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007141}
7142
7143/*
7144 * asc_prt_line()
7145 *
7146 * If 'cp' is NULL print to the console, otherwise print to a buffer.
7147 *
7148 * Return 0 if printing to the console, otherwise return the number of
7149 * bytes written to the buffer.
7150 *
7151 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
7152 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
7153 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007154static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007155{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007156 va_list args;
7157 int ret;
7158 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007159
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007160 va_start(args, fmt);
7161 ret = vsprintf(s, fmt, args);
7162 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
7163 if (buf == NULL) {
7164 (void)printk(s);
7165 ret = 0;
7166 } else {
7167 ret = min(buflen, ret);
7168 memcpy(buf, s, ret);
7169 }
7170 va_end(args);
7171 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172}
7173#endif /* CONFIG_PROC_FS */
7174
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175/*
7176 * --- Functions Required by the Asc Library
7177 */
7178
7179/*
7180 * Delay for 'n' milliseconds. Don't use the 'jiffies'
7181 * global variable which is incremented once every 5 ms
7182 * from a timer interrupt, because this function may be
7183 * called when interrupts are disabled.
7184 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007185static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007186{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007187 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
7188 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007189}
7190
7191/*
7192 * Currently and inline noop but leave as a placeholder.
7193 * Leave DvcEnterCritical() as a noop placeholder.
7194 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007195static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007196{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007197 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007198}
7199
7200/*
7201 * Critical sections are all protected by the board spinlock.
7202 * Leave DvcLeaveCritical() as a noop placeholder.
7203 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007204static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007205{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007206 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007207}
7208
7209/*
7210 * void
7211 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
7212 *
7213 * Calling/Exit State:
7214 * none
7215 *
7216 * Description:
7217 * Output an ASC_SCSI_Q structure to the chip
7218 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007219static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07007220DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
7221{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007222 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007224 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
7225 AscSetChipLramAddr(iop_base, s_addr);
7226 for (i = 0; i < 2 * words; i += 2) {
7227 if (i == 4 || i == 20) {
7228 continue;
7229 }
7230 outpw(iop_base + IOP_RAM_DATA,
7231 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
7232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233}
7234
7235/*
7236 * void
7237 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
7238 *
7239 * Calling/Exit State:
7240 * none
7241 *
7242 * Description:
7243 * Input an ASC_QDONE_INFO structure from the chip
7244 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007245static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07007246DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
7247{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007248 int i;
7249 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007251 AscSetChipLramAddr(iop_base, s_addr);
7252 for (i = 0; i < 2 * words; i += 2) {
7253 if (i == 10) {
7254 continue;
7255 }
7256 word = inpw(iop_base + IOP_RAM_DATA);
7257 inbuf[i] = word & 0xff;
7258 inbuf[i + 1] = (word >> 8) & 0xff;
7259 }
7260 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261}
7262
7263/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264 * Return the BIOS address of the adapter at the specified
7265 * I/O port and with the specified bus type.
7266 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007267static unsigned short __devinit
7268AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007269{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007270 unsigned short cfg_lsw;
7271 unsigned short bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007273 /*
7274 * The PCI BIOS is re-located by the motherboard BIOS. Because
7275 * of this the driver can not determine where a PCI BIOS is
7276 * loaded and executes.
7277 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007278 if (bus_type & ASC_IS_PCI)
7279 return 0;
7280
Linus Torvalds1da177e2005-04-16 15:20:36 -07007281#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007282 if ((bus_type & ASC_IS_EISA) != 0) {
7283 cfg_lsw = AscGetEisaChipCfg(iop_base);
7284 cfg_lsw &= 0x000F;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007285 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
7286 return bios_addr;
7287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007288#endif /* CONFIG_ISA */
7289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007290 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007292 /*
7293 * ISA PnP uses the top bit as the 32K BIOS flag
7294 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007295 if (bus_type == ASC_IS_ISAPNP)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007296 cfg_lsw &= 0x7FFF;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007297 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
7298 return bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299}
7300
Linus Torvalds1da177e2005-04-16 15:20:36 -07007301/*
7302 * --- Functions Required by the Adv Library
7303 */
7304
7305/*
7306 * DvcGetPhyAddr()
7307 *
7308 * Return the physical address of 'vaddr' and set '*lenp' to the
7309 * number of physically contiguous bytes that follow 'vaddr'.
7310 * 'flag' indicates the type of structure whose physical address
7311 * is being translated.
7312 *
7313 * Note: Because Linux currently doesn't page the kernel and all
7314 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
7315 */
7316ADV_PADDR
7317DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007318 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007319{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007320 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007321
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007322 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007323
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007324 ASC_DBG4(4,
7325 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
7326 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
7327 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007328
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007329 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007330}
7331
7332/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07007333 * --- Tracing and Debugging Functions
7334 */
7335
7336#ifdef ADVANSYS_STATS
7337#ifdef CONFIG_PROC_FS
7338/*
7339 * asc_prt_board_stats()
7340 *
7341 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7342 * cf. asc_prt_line().
7343 *
7344 * Return the number of characters copied into 'cp'. No more than
7345 * 'cplen' characters will be copied to 'cp'.
7346 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007347static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007348{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007349 int leftlen;
7350 int totlen;
7351 int len;
7352 struct asc_stats *s;
7353 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007354
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007355 leftlen = cplen;
7356 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007358 boardp = ASC_BOARDP(shost);
7359 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007361 len = asc_prt_line(cp, leftlen,
7362 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
7363 shost->host_no);
7364 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007366 len = asc_prt_line(cp, leftlen,
7367 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
7368 s->queuecommand, s->reset, s->biosparam,
7369 s->interrupt);
7370 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 len = asc_prt_line(cp, leftlen,
7373 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
7374 s->callback, s->done, s->build_error,
7375 s->adv_build_noreq, s->adv_build_nosg);
7376 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007377
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007378 len = asc_prt_line(cp, leftlen,
7379 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
7380 s->exe_noerror, s->exe_busy, s->exe_error,
7381 s->exe_unknown);
7382 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007383
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007384 /*
7385 * Display data transfer statistics.
7386 */
7387 if (s->cont_cnt > 0) {
7388 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
7389 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007391 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
7392 s->cont_xfer / 2,
7393 ASC_TENTHS(s->cont_xfer, 2));
7394 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007395
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007396 /* Contiguous transfer average size */
7397 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
7398 (s->cont_xfer / 2) / s->cont_cnt,
7399 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
7400 ASC_PRT_NEXT();
7401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007402
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007403 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007405 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
7406 s->sg_cnt, s->sg_elem);
7407 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007409 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
7410 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
7411 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007413 /* Scatter gather transfer statistics */
7414 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
7415 s->sg_elem / s->sg_cnt,
7416 ASC_TENTHS(s->sg_elem, s->sg_cnt));
7417 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007418
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007419 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
7420 (s->sg_xfer / 2) / s->sg_elem,
7421 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
7422 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007424 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
7425 (s->sg_xfer / 2) / s->sg_cnt,
7426 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
7427 ASC_PRT_NEXT();
7428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007430 /*
7431 * Display request queuing statistics.
7432 */
7433 len = asc_prt_line(cp, leftlen,
7434 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
7435 HZ);
7436 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007438 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007439}
7440
7441/*
7442 * asc_prt_target_stats()
7443 *
7444 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7445 * cf. asc_prt_line().
7446 *
7447 * This is separated from asc_prt_board_stats because a full set
7448 * of targets will overflow ASC_PRTBUF_SIZE.
7449 *
7450 * Return the number of characters copied into 'cp'. No more than
7451 * 'cplen' characters will be copied to 'cp'.
7452 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007453static int
7454asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007455{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007456 int leftlen;
7457 int totlen;
7458 int len;
7459 struct asc_stats *s;
7460 ushort chip_scsi_id;
7461 asc_board_t *boardp;
7462 asc_queue_t *active;
7463 asc_queue_t *waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007464
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007465 leftlen = cplen;
7466 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007467
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007468 boardp = ASC_BOARDP(shost);
7469 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007470
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007471 active = &ASC_BOARDP(shost)->active;
7472 waiting = &ASC_BOARDP(shost)->waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007473
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007474 if (ASC_NARROW_BOARD(boardp)) {
7475 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
7476 } else {
7477 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
7478 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007479
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007480 if ((chip_scsi_id == tgt_id) ||
7481 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) {
7482 return 0;
7483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007485 do {
7486 if (active->q_tot_cnt[tgt_id] > 0
7487 || waiting->q_tot_cnt[tgt_id] > 0) {
7488 len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id);
7489 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007490
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007491 len = asc_prt_line(cp, leftlen,
7492 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
7493 active->q_cur_cnt[tgt_id],
7494 active->q_max_cnt[tgt_id],
7495 active->q_tot_cnt[tgt_id],
7496 active->q_min_tim[tgt_id],
7497 active->q_max_tim[tgt_id],
7498 (active->q_tot_cnt[tgt_id] ==
7499 0) ? 0 : (active->
7500 q_tot_tim[tgt_id] /
7501 active->
7502 q_tot_cnt[tgt_id]),
7503 (active->q_tot_cnt[tgt_id] ==
7504 0) ? 0 : ASC_TENTHS(active->
7505 q_tot_tim
7506 [tgt_id],
7507 active->
7508 q_tot_cnt
7509 [tgt_id]));
7510 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007511
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007512 len = asc_prt_line(cp, leftlen,
7513 " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
7514 waiting->q_cur_cnt[tgt_id],
7515 waiting->q_max_cnt[tgt_id],
7516 waiting->q_tot_cnt[tgt_id],
7517 waiting->q_min_tim[tgt_id],
7518 waiting->q_max_tim[tgt_id],
7519 (waiting->q_tot_cnt[tgt_id] ==
7520 0) ? 0 : (waiting->
7521 q_tot_tim[tgt_id] /
7522 waiting->
7523 q_tot_cnt[tgt_id]),
7524 (waiting->q_tot_cnt[tgt_id] ==
7525 0) ? 0 : ASC_TENTHS(waiting->
7526 q_tot_tim
7527 [tgt_id],
7528 waiting->
7529 q_tot_cnt
7530 [tgt_id]));
7531 ASC_PRT_NEXT();
7532 }
7533 } while (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007535 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536}
7537#endif /* CONFIG_PROC_FS */
7538#endif /* ADVANSYS_STATS */
7539
7540#ifdef ADVANSYS_DEBUG
7541/*
7542 * asc_prt_scsi_host()
7543 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007544static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007545{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007546 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007548 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007549
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007550 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
7551 printk(" host_busy %u, host_no %d, last_reset %d,\n",
7552 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007553
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04007554 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
7555 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007557 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
7558 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007559
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007560 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
7561 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007563 if (ASC_NARROW_BOARD(boardp)) {
7564 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
7565 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
7566 } else {
7567 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
7568 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
7569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007570}
7571
7572/*
7573 * asc_prt_scsi_cmnd()
7574 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007575static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007576{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007577 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007578
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007579 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
7580 (ulong)s->device->host, (ulong)s->device, s->device->id,
7581 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007582
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007583 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007584
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007585 printk("sc_data_direction %u, resid %d\n",
7586 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007588 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007589
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007590 printk(" serial_number 0x%x, retries %d, allowed %d\n",
7591 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007592
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007593 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007594
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007595 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
7596 s->scsi_done, s->done, s->host_scribble, s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007598 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007599}
7600
7601/*
7602 * asc_prt_asc_dvc_var()
7603 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007604static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007605{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007606 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007607
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007608 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
7609 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007610
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007611 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
7612 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007613
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007614 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
7615 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
7616 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
7617 (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007618
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007619 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
7620 "%u,\n", (unsigned)h->queue_full_or_busy,
7621 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007622
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007623 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
7624 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
7625 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
7626 (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007627
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007628 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
7629 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
7630 (unsigned)h->init_state, (unsigned)h->no_scam,
7631 (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007632
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007633 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007634}
7635
7636/*
7637 * asc_prt_asc_dvc_cfg()
7638 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007639static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007640{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007641 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007642
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007643 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
7644 h->can_tagged_qng, h->cmd_qng_enabled);
7645 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
7646 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007648 printk
7649 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
7650 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
7651 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007652
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007653 printk
7654 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
7655 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
7656 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007657
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007658 printk(" mcode_version %d, overrun_buf 0x%lx\n",
7659 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007660}
7661
7662/*
7663 * asc_prt_asc_scsi_q()
7664 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007665static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007666{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007667 ASC_SG_HEAD *sgp;
7668 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007669
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007670 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007672 printk
7673 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
7674 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
7675 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007676
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007677 printk
7678 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
7679 (ulong)le32_to_cpu(q->q1.data_addr),
7680 (ulong)le32_to_cpu(q->q1.data_cnt),
7681 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007682
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007683 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
7684 (ulong)q->cdbptr, q->q2.cdb_len,
7685 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007686
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007687 if (q->sg_head) {
7688 sgp = q->sg_head;
7689 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
7690 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
7691 sgp->queue_cnt);
7692 for (i = 0; i < sgp->entry_cnt; i++) {
7693 printk(" [%u]: addr 0x%lx, bytes %lu\n",
7694 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
7695 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
7696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007697
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007699}
7700
7701/*
7702 * asc_prt_asc_qdone_info()
7703 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007704static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007705{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007706 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
7707 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
7708 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
7709 q->d2.tag_code);
7710 printk
7711 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
7712 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007713}
7714
7715/*
7716 * asc_prt_adv_dvc_var()
7717 *
7718 * Display an ADV_DVC_VAR structure.
7719 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007720static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007721{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007722 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007723
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007724 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
7725 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007726
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007727 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
7728 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
7729 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007731 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
7732 (unsigned)h->start_motor,
7733 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007735 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
7736 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
7737 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007738
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007739 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
7740 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007742 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
7743 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007745 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
7746 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007747}
7748
7749/*
7750 * asc_prt_adv_dvc_cfg()
7751 *
7752 * Display an ADV_DVC_CFG structure.
7753 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007754static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007755{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007756 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007757
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007758 printk(" disc_enable 0x%x, termination 0x%x\n",
7759 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007761 printk(" chip_version 0x%x, mcode_date 0x%x\n",
7762 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007764 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
7765 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007767 printk(" control_flag 0x%x, pci_slot_info 0x%x\n",
7768 h->control_flag, h->pci_slot_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007769}
7770
7771/*
7772 * asc_prt_adv_scsi_req_q()
7773 *
7774 * Display an ADV_SCSI_REQ_Q structure.
7775 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007776static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007777{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007778 int sg_blk_cnt;
7779 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007781 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007783 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
7784 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007785
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007786 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
7787 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007788
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007789 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
7790 (ulong)le32_to_cpu(q->data_cnt),
7791 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007792
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007793 printk
7794 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
7795 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007796
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007797 printk(" sg_working_ix 0x%x, target_cmd %u\n",
7798 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007799
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007800 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
7801 (ulong)le32_to_cpu(q->scsiq_rptr),
7802 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007803
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007804 /* Display the request's ADV_SG_BLOCK structures. */
7805 if (q->sg_list_ptr != NULL) {
7806 sg_blk_cnt = 0;
7807 while (1) {
7808 /*
7809 * 'sg_ptr' is a physical address. Convert it to a virtual
7810 * address by indexing 'sg_blk_cnt' into the virtual address
7811 * array 'sg_list_ptr'.
7812 *
7813 * XXX - Assumes all SG physical blocks are virtually contiguous.
7814 */
7815 sg_ptr =
7816 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
7817 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
7818 if (sg_ptr->sg_ptr == 0) {
7819 break;
7820 }
7821 sg_blk_cnt++;
7822 }
7823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007824}
7825
7826/*
7827 * asc_prt_adv_sgblock()
7828 *
7829 * Display an ADV_SG_BLOCK structure.
7830 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007831static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007832{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007833 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007834
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007835 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
7836 (ulong)b, sgblockno);
7837 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
7838 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
7839 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
7840 if (b->sg_ptr != 0) {
7841 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
7842 }
7843 for (i = 0; i < b->sg_cnt; i++) {
7844 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
7845 i, (ulong)b->sg_list[i].sg_addr,
7846 (ulong)b->sg_list[i].sg_count);
7847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007848}
7849
7850/*
7851 * asc_prt_hex()
7852 *
7853 * Print hexadecimal output in 4 byte groupings 32 bytes
7854 * or 8 double-words per line.
7855 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007856static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007857{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007858 int i;
7859 int j;
7860 int k;
7861 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007863 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007864
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007865 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007866
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007867 /* Display a maximum of 8 double-words per line. */
7868 if ((k = (l - i) / 4) >= 8) {
7869 k = 8;
7870 m = 0;
7871 } else {
7872 m = (l - i) % 4;
7873 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007875 for (j = 0; j < k; j++) {
7876 printk(" %2.2X%2.2X%2.2X%2.2X",
7877 (unsigned)s[i + (j * 4)],
7878 (unsigned)s[i + (j * 4) + 1],
7879 (unsigned)s[i + (j * 4) + 2],
7880 (unsigned)s[i + (j * 4) + 3]);
7881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007882
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007883 switch (m) {
7884 case 0:
7885 default:
7886 break;
7887 case 1:
7888 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
7889 break;
7890 case 2:
7891 printk(" %2.2X%2.2X",
7892 (unsigned)s[i + (j * 4)],
7893 (unsigned)s[i + (j * 4) + 1]);
7894 break;
7895 case 3:
7896 printk(" %2.2X%2.2X%2.2X",
7897 (unsigned)s[i + (j * 4) + 1],
7898 (unsigned)s[i + (j * 4) + 2],
7899 (unsigned)s[i + (j * 4) + 3]);
7900 break;
7901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007902
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007903 printk("\n");
7904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007905}
7906#endif /* ADVANSYS_DEBUG */
7907
7908/*
7909 * --- Asc Library Functions
7910 */
7911
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007912static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007913{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007914 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007916 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
7917 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
7918 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007919}
7920
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007921static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007922{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007923 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007925 if (AscGetChipScsiID(iop_base) == new_host_id) {
7926 return (new_host_id);
7927 }
7928 cfg_lsw = AscGetChipCfgLsw(iop_base);
7929 cfg_lsw &= 0xF8FF;
7930 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
7931 AscSetChipCfgLsw(iop_base, cfg_lsw);
7932 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007933}
7934
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007935static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007936{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007937 unsigned char sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007938
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007939 AscSetBank(iop_base, 1);
7940 sc = inp(iop_base + IOP_REG_SC);
7941 AscSetBank(iop_base, 0);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007942 return sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007943}
7944
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007945static unsigned char __devinit
7946AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007947{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007948 if (bus_type & ASC_IS_EISA) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007949 PortAddr eisa_iop;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007950 unsigned char revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007951 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
7952 (PortAddr) ASC_EISA_REV_IOP_MASK;
7953 revision = inp(eisa_iop);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007954 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007955 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -06007956 return AscGetChipVerNo(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007957}
7958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007959static ASC_DCNT
7960AscLoadMicroCode(PortAddr iop_base,
7961 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007962{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007963 ASC_DCNT chksum;
7964 ushort mcode_word_size;
7965 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007967 /* Write the microcode buffer starting at LRAM address 0. */
7968 mcode_word_size = (ushort)(mcode_size >> 1);
7969 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
7970 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007972 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
7973 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
7974 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
7975 (ushort)ASC_CODE_SEC_BEG,
7976 (ushort)((mcode_size -
7977 s_addr - (ushort)
7978 ASC_CODE_SEC_BEG) /
7979 2));
7980 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
7981 (ulong)mcode_chksum);
7982 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
7983 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
7984 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007985}
7986
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007987static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007988{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007989 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007990
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007991 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
7992 iop_base, AscGetChipSignatureByte(iop_base));
7993 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
7994 ASC_DBG2(1,
7995 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
7996 iop_base, AscGetChipSignatureWord(iop_base));
7997 sig_word = AscGetChipSignatureWord(iop_base);
7998 if ((sig_word == (ushort)ASC_1000_ID0W) ||
7999 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
8000 return (1);
8001 }
8002 }
8003 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008004}
8005
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008006static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008007{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008008 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
8009 AscSetChipStatus(iop_base, 0);
8010 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008011}
8012
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008013static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008014{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008015 ushort cfg_lsw;
8016 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008018 if ((bus_type & ASC_IS_EISA) != 0) {
8019 cfg_lsw = AscGetEisaChipCfg(iop_base);
8020 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
8021 if ((chip_irq == 13) || (chip_irq > 15)) {
8022 return (0);
8023 }
8024 return (chip_irq);
8025 }
8026 if ((bus_type & ASC_IS_VL) != 0) {
8027 cfg_lsw = AscGetChipCfgLsw(iop_base);
8028 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
8029 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
8030 return (0);
8031 }
8032 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
8033 }
8034 cfg_lsw = AscGetChipCfgLsw(iop_base);
8035 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
8036 if (chip_irq == 3)
8037 chip_irq += (uchar)2;
8038 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008039}
8040
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008041static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008042AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008043{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008044 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008045
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008046 if ((bus_type & ASC_IS_VL) != 0) {
8047 if (irq_no != 0) {
8048 if ((irq_no < ASC_MIN_IRQ_NO)
8049 || (irq_no > ASC_MAX_IRQ_NO)) {
8050 irq_no = 0;
8051 } else {
8052 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
8053 }
8054 }
8055 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
8056 cfg_lsw |= (ushort)0x0010;
8057 AscSetChipCfgLsw(iop_base, cfg_lsw);
8058 AscToggleIRQAct(iop_base);
8059 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
8060 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
8061 AscSetChipCfgLsw(iop_base, cfg_lsw);
8062 AscToggleIRQAct(iop_base);
8063 return (AscGetChipIRQ(iop_base, bus_type));
8064 }
8065 if ((bus_type & (ASC_IS_ISA)) != 0) {
8066 if (irq_no == 15)
8067 irq_no -= (uchar)2;
8068 irq_no -= (uchar)ASC_MIN_IRQ_NO;
8069 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
8070 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
8071 AscSetChipCfgLsw(iop_base, cfg_lsw);
8072 return (AscGetChipIRQ(iop_base, bus_type));
8073 }
8074 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008075}
8076
8077#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008078static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008079{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008080 if (dma_channel < 4) {
8081 outp(0x000B, (ushort)(0xC0 | dma_channel));
8082 outp(0x000A, dma_channel);
8083 } else if (dma_channel < 8) {
8084 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
8085 outp(0x00D4, (ushort)(dma_channel - 4));
8086 }
8087 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008088}
8089#endif /* CONFIG_ISA */
8090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008091static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008092{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008093 EXT_MSG ext_msg;
8094 EXT_MSG out_msg;
8095 ushort halt_q_addr;
8096 int sdtr_accept;
8097 ushort int_halt_code;
8098 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8099 ASC_SCSI_BIT_ID_TYPE target_id;
8100 PortAddr iop_base;
8101 uchar tag_code;
8102 uchar q_status;
8103 uchar halt_qp;
8104 uchar sdtr_data;
8105 uchar target_ix;
8106 uchar q_cntl, tid_no;
8107 uchar cur_dvc_qng;
8108 uchar asyn_sdtr;
8109 uchar scsi_status;
8110 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008112 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
8113 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008115 iop_base = asc_dvc->iop_base;
8116 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008118 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8119 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8120 target_ix = AscReadLramByte(iop_base,
8121 (ushort)(halt_q_addr +
8122 (ushort)ASC_SCSIQ_B_TARGET_IX));
8123 q_cntl =
8124 AscReadLramByte(iop_base,
8125 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8126 tid_no = ASC_TIX_TO_TID(target_ix);
8127 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8128 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8129 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8130 } else {
8131 asyn_sdtr = 0;
8132 }
8133 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8134 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8135 AscSetChipSDTR(iop_base, 0, tid_no);
8136 boardp->sdtr_data[tid_no] = 0;
8137 }
8138 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8139 return (0);
8140 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8141 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8142 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8143 boardp->sdtr_data[tid_no] = asyn_sdtr;
8144 }
8145 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8146 return (0);
8147 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008149 AscMemWordCopyPtrFromLram(iop_base,
8150 ASCV_MSGIN_BEG,
8151 (uchar *)&ext_msg,
8152 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008153
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008154 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8155 ext_msg.msg_req == EXTENDED_SDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008156 ext_msg.msg_len == MS_SDTR_LEN) {
8157 sdtr_accept = TRUE;
8158 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008159
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008160 sdtr_accept = FALSE;
8161 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8162 }
8163 if ((ext_msg.xfer_period <
8164 asc_dvc->sdtr_period_tbl[asc_dvc->
8165 host_init_sdtr_index])
8166 || (ext_msg.xfer_period >
8167 asc_dvc->sdtr_period_tbl[asc_dvc->
8168 max_sdtr_index])) {
8169 sdtr_accept = FALSE;
8170 ext_msg.xfer_period =
8171 asc_dvc->sdtr_period_tbl[asc_dvc->
8172 host_init_sdtr_index];
8173 }
8174 if (sdtr_accept) {
8175 sdtr_data =
8176 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8177 ext_msg.req_ack_offset);
8178 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008180 q_cntl |= QC_MSG_OUT;
8181 asc_dvc->init_sdtr &= ~target_id;
8182 asc_dvc->sdtr_done &= ~target_id;
8183 AscSetChipSDTR(iop_base, asyn_sdtr,
8184 tid_no);
8185 boardp->sdtr_data[tid_no] = asyn_sdtr;
8186 }
8187 }
8188 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008189
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008190 q_cntl &= ~QC_MSG_OUT;
8191 asc_dvc->init_sdtr &= ~target_id;
8192 asc_dvc->sdtr_done &= ~target_id;
8193 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8194 } else {
8195 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008196
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008197 q_cntl &= ~QC_MSG_OUT;
8198 asc_dvc->sdtr_done |= target_id;
8199 asc_dvc->init_sdtr |= target_id;
8200 asc_dvc->pci_fix_asyn_xfer &=
8201 ~target_id;
8202 sdtr_data =
8203 AscCalSDTRData(asc_dvc,
8204 ext_msg.xfer_period,
8205 ext_msg.
8206 req_ack_offset);
8207 AscSetChipSDTR(iop_base, sdtr_data,
8208 tid_no);
8209 boardp->sdtr_data[tid_no] = sdtr_data;
8210 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008211
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008212 q_cntl |= QC_MSG_OUT;
8213 AscMsgOutSDTR(asc_dvc,
8214 ext_msg.xfer_period,
8215 ext_msg.req_ack_offset);
8216 asc_dvc->pci_fix_asyn_xfer &=
8217 ~target_id;
8218 sdtr_data =
8219 AscCalSDTRData(asc_dvc,
8220 ext_msg.xfer_period,
8221 ext_msg.
8222 req_ack_offset);
8223 AscSetChipSDTR(iop_base, sdtr_data,
8224 tid_no);
8225 boardp->sdtr_data[tid_no] = sdtr_data;
8226 asc_dvc->sdtr_done |= target_id;
8227 asc_dvc->init_sdtr |= target_id;
8228 }
8229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008231 AscWriteLramByte(iop_base,
8232 (ushort)(halt_q_addr +
8233 (ushort)ASC_SCSIQ_B_CNTL),
8234 q_cntl);
8235 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8236 return (0);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008237 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8238 ext_msg.msg_req == EXTENDED_WDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008239 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008240
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008241 ext_msg.wdtr_width = 0;
8242 AscMemWordCopyPtrToLram(iop_base,
8243 ASCV_MSGOUT_BEG,
8244 (uchar *)&ext_msg,
8245 sizeof(EXT_MSG) >> 1);
8246 q_cntl |= QC_MSG_OUT;
8247 AscWriteLramByte(iop_base,
8248 (ushort)(halt_q_addr +
8249 (ushort)ASC_SCSIQ_B_CNTL),
8250 q_cntl);
8251 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8252 return (0);
8253 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008254
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008255 ext_msg.msg_type = MESSAGE_REJECT;
8256 AscMemWordCopyPtrToLram(iop_base,
8257 ASCV_MSGOUT_BEG,
8258 (uchar *)&ext_msg,
8259 sizeof(EXT_MSG) >> 1);
8260 q_cntl |= QC_MSG_OUT;
8261 AscWriteLramByte(iop_base,
8262 (ushort)(halt_q_addr +
8263 (ushort)ASC_SCSIQ_B_CNTL),
8264 q_cntl);
8265 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8266 return (0);
8267 }
8268 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008270 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008272 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008274 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008276 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8277 q_cntl |= QC_MSG_OUT;
8278 AscMsgOutSDTR(asc_dvc,
8279 asc_dvc->
8280 sdtr_period_tbl[(sdtr_data >> 4) &
8281 (uchar)(asc_dvc->
8282 max_sdtr_index -
8283 1)],
8284 (uchar)(sdtr_data & (uchar)
8285 ASC_SYN_MAX_OFFSET));
8286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008288 AscWriteLramByte(iop_base,
8289 (ushort)(halt_q_addr +
8290 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008292 tag_code = AscReadLramByte(iop_base,
8293 (ushort)(halt_q_addr + (ushort)
8294 ASC_SCSIQ_B_TAG_CODE));
8295 tag_code &= 0xDC;
8296 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
8297 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
8298 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008299
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008300 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
8301 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008303 }
8304 AscWriteLramByte(iop_base,
8305 (ushort)(halt_q_addr +
8306 (ushort)ASC_SCSIQ_B_TAG_CODE),
8307 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008308
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008309 q_status = AscReadLramByte(iop_base,
8310 (ushort)(halt_q_addr + (ushort)
8311 ASC_SCSIQ_B_STATUS));
8312 q_status |= (QS_READY | QS_BUSY);
8313 AscWriteLramByte(iop_base,
8314 (ushort)(halt_q_addr +
8315 (ushort)ASC_SCSIQ_B_STATUS),
8316 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008318 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
8319 scsi_busy &= ~target_id;
8320 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008321
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008322 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8323 return (0);
8324 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008325
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008326 AscMemWordCopyPtrFromLram(iop_base,
8327 ASCV_MSGOUT_BEG,
8328 (uchar *)&out_msg,
8329 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008330
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008331 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008332 (out_msg.msg_len == MS_SDTR_LEN) &&
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008333 (out_msg.msg_req == EXTENDED_SDTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008334
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008335 asc_dvc->init_sdtr &= ~target_id;
8336 asc_dvc->sdtr_done &= ~target_id;
8337 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8338 boardp->sdtr_data[tid_no] = asyn_sdtr;
8339 }
8340 q_cntl &= ~QC_MSG_OUT;
8341 AscWriteLramByte(iop_base,
8342 (ushort)(halt_q_addr +
8343 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8344 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8345 return (0);
8346 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008348 scsi_status = AscReadLramByte(iop_base,
8349 (ushort)((ushort)halt_q_addr +
8350 (ushort)
8351 ASC_SCSIQ_SCSI_STATUS));
8352 cur_dvc_qng =
8353 AscReadLramByte(iop_base,
8354 (ushort)((ushort)ASC_QADR_BEG +
8355 (ushort)target_ix));
8356 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008358 scsi_busy = AscReadLramByte(iop_base,
8359 (ushort)ASCV_SCSIBUSY_B);
8360 scsi_busy |= target_id;
8361 AscWriteLramByte(iop_base,
8362 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8363 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008364
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008365 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
8366 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
8367 cur_dvc_qng -= 1;
8368 asc_dvc->max_dvc_qng[tid_no] =
8369 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008370
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008371 AscWriteLramByte(iop_base,
8372 (ushort)((ushort)
8373 ASCV_MAX_DVC_QNG_BEG
8374 + (ushort)
8375 tid_no),
8376 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008377
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008378 /*
8379 * Set the device queue depth to the number of
8380 * active requests when the QUEUE FULL condition
8381 * was encountered.
8382 */
8383 boardp->queue_full |= target_id;
8384 boardp->queue_full_cnt[tid_no] =
8385 cur_dvc_qng;
8386 }
8387 }
8388 }
8389 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8390 return (0);
8391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008392#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008393 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
8394 uchar q_no;
8395 ushort q_addr;
8396 uchar sg_wk_q_no;
8397 uchar first_sg_wk_q_no;
8398 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
8399 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
8400 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
8401 ushort sg_list_dwords;
8402 ushort sg_entry_cnt;
8403 uchar next_qp;
8404 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008406 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
8407 if (q_no == ASC_QLINK_END) {
8408 return (0);
8409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008411 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008413 /*
8414 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
8415 * structure pointer using a macro provided by the driver.
8416 * The ASC_SCSI_REQ pointer provides a pointer to the
8417 * host ASC_SG_HEAD structure.
8418 */
8419 /* Read request's SRB pointer. */
8420 scsiq = (ASC_SCSI_Q *)
8421 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
8422 (ushort)
8423 (q_addr +
8424 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008425
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008426 /*
8427 * Get request's first and working SG queue.
8428 */
8429 sg_wk_q_no = AscReadLramByte(iop_base,
8430 (ushort)(q_addr +
8431 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008432
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008433 first_sg_wk_q_no = AscReadLramByte(iop_base,
8434 (ushort)(q_addr +
8435 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008436
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008437 /*
8438 * Reset request's working SG queue back to the
8439 * first SG queue.
8440 */
8441 AscWriteLramByte(iop_base,
8442 (ushort)(q_addr +
8443 (ushort)ASC_SCSIQ_B_SG_WK_QP),
8444 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008446 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008448 /*
8449 * Set sg_entry_cnt to the number of SG elements
8450 * that will be completed on this interrupt.
8451 *
8452 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
8453 * SG elements. The data_cnt and data_addr fields which
8454 * add 1 to the SG element capacity are not used when
8455 * restarting SG handling after a halt.
8456 */
8457 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
8458 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008460 /*
8461 * Keep track of remaining number of SG elements that will
8462 * need to be handled on the next interrupt.
8463 */
8464 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
8465 } else {
8466 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
8467 scsiq->remain_sg_entry_cnt = 0;
8468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008469
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008470 /*
8471 * Copy SG elements into the list of allocated SG queues.
8472 *
8473 * Last index completed is saved in scsiq->next_sg_index.
8474 */
8475 next_qp = first_sg_wk_q_no;
8476 q_addr = ASC_QNO_TO_QADDR(next_qp);
8477 scsi_sg_q.sg_head_qp = q_no;
8478 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
8479 for (i = 0; i < sg_head->queue_cnt; i++) {
8480 scsi_sg_q.seq_no = i + 1;
8481 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
8482 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
8483 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8484 /*
8485 * After very first SG queue RISC FW uses next
8486 * SG queue first element then checks sg_list_cnt
8487 * against zero and then decrements, so set
8488 * sg_list_cnt 1 less than number of SG elements
8489 * in each SG queue.
8490 */
8491 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
8492 scsi_sg_q.sg_cur_list_cnt =
8493 ASC_SG_LIST_PER_Q - 1;
8494 } else {
8495 /*
8496 * This is the last SG queue in the list of
8497 * allocated SG queues. If there are more
8498 * SG elements than will fit in the allocated
8499 * queues, then set the QCSG_SG_XFER_MORE flag.
8500 */
8501 if (scsiq->remain_sg_entry_cnt != 0) {
8502 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8503 } else {
8504 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
8505 }
8506 /* equals sg_entry_cnt * 2 */
8507 sg_list_dwords = sg_entry_cnt << 1;
8508 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
8509 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
8510 sg_entry_cnt = 0;
8511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008512
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008513 scsi_sg_q.q_no = next_qp;
8514 AscMemWordCopyPtrToLram(iop_base,
8515 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8516 (uchar *)&scsi_sg_q,
8517 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008518
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008519 AscMemDWordCopyPtrToLram(iop_base,
8520 q_addr + ASC_SGQ_LIST_BEG,
8521 (uchar *)&sg_head->
8522 sg_list[scsiq->next_sg_index],
8523 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008524
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008525 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008526
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008527 /*
8528 * If the just completed SG queue contained the
8529 * last SG element, then no more SG queues need
8530 * to be written.
8531 */
8532 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
8533 break;
8534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008535
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008536 next_qp = AscReadLramByte(iop_base,
8537 (ushort)(q_addr +
8538 ASC_SCSIQ_B_FWD));
8539 q_addr = ASC_QNO_TO_QADDR(next_qp);
8540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008542 /*
8543 * Clear the halt condition so the RISC will be restarted
8544 * after the return.
8545 */
8546 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8547 return (0);
8548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008549#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008550 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008551}
8552
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008553static uchar
8554_AscCopyLramScsiDoneQ(PortAddr iop_base,
8555 ushort q_addr,
8556 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008557{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008558 ushort _val;
8559 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008560
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008561 DvcGetQinfo(iop_base,
8562 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
8563 (uchar *)scsiq,
8564 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008566 _val = AscReadLramWord(iop_base,
8567 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
8568 scsiq->q_status = (uchar)_val;
8569 scsiq->q_no = (uchar)(_val >> 8);
8570 _val = AscReadLramWord(iop_base,
8571 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8572 scsiq->cntl = (uchar)_val;
8573 sg_queue_cnt = (uchar)(_val >> 8);
8574 _val = AscReadLramWord(iop_base,
8575 (ushort)(q_addr +
8576 (ushort)ASC_SCSIQ_B_SENSE_LEN));
8577 scsiq->sense_len = (uchar)_val;
8578 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008580 /*
8581 * Read high word of remain bytes from alternate location.
8582 */
8583 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
8584 (ushort)(q_addr +
8585 (ushort)
8586 ASC_SCSIQ_W_ALT_DC1)))
8587 << 16);
8588 /*
8589 * Read low word of remain bytes from original location.
8590 */
8591 scsiq->remain_bytes += AscReadLramWord(iop_base,
8592 (ushort)(q_addr + (ushort)
8593 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008594
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008595 scsiq->remain_bytes &= max_dma_count;
8596 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008597}
8598
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008599static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008600{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008601 uchar next_qp;
8602 uchar n_q_used;
8603 uchar sg_list_qp;
8604 uchar sg_queue_cnt;
8605 uchar q_cnt;
8606 uchar done_q_tail;
8607 uchar tid_no;
8608 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8609 ASC_SCSI_BIT_ID_TYPE target_id;
8610 PortAddr iop_base;
8611 ushort q_addr;
8612 ushort sg_q_addr;
8613 uchar cur_target_qng;
8614 ASC_QDONE_INFO scsiq_buf;
8615 ASC_QDONE_INFO *scsiq;
8616 int false_overrun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008617
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008618 iop_base = asc_dvc->iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008619 n_q_used = 1;
8620 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
8621 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
8622 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
8623 next_qp = AscReadLramByte(iop_base,
8624 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
8625 if (next_qp != ASC_QLINK_END) {
8626 AscPutVarDoneQTail(iop_base, next_qp);
8627 q_addr = ASC_QNO_TO_QADDR(next_qp);
8628 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
8629 asc_dvc->max_dma_count);
8630 AscWriteLramByte(iop_base,
8631 (ushort)(q_addr +
8632 (ushort)ASC_SCSIQ_B_STATUS),
8633 (uchar)(scsiq->
8634 q_status & (uchar)~(QS_READY |
8635 QS_ABORTED)));
8636 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
8637 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
8638 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
8639 sg_q_addr = q_addr;
8640 sg_list_qp = next_qp;
8641 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
8642 sg_list_qp = AscReadLramByte(iop_base,
8643 (ushort)(sg_q_addr
8644 + (ushort)
8645 ASC_SCSIQ_B_FWD));
8646 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
8647 if (sg_list_qp == ASC_QLINK_END) {
8648 AscSetLibErrorCode(asc_dvc,
8649 ASCQ_ERR_SG_Q_LINKS);
8650 scsiq->d3.done_stat = QD_WITH_ERROR;
8651 scsiq->d3.host_stat =
8652 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
8653 goto FATAL_ERR_QDONE;
8654 }
8655 AscWriteLramByte(iop_base,
8656 (ushort)(sg_q_addr + (ushort)
8657 ASC_SCSIQ_B_STATUS),
8658 QS_FREE);
8659 }
8660 n_q_used = sg_queue_cnt + 1;
8661 AscPutVarDoneQTail(iop_base, sg_list_qp);
8662 }
8663 if (asc_dvc->queue_full_or_busy & target_id) {
8664 cur_target_qng = AscReadLramByte(iop_base,
8665 (ushort)((ushort)
8666 ASC_QADR_BEG
8667 + (ushort)
8668 scsiq->d2.
8669 target_ix));
8670 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
8671 scsi_busy = AscReadLramByte(iop_base, (ushort)
8672 ASCV_SCSIBUSY_B);
8673 scsi_busy &= ~target_id;
8674 AscWriteLramByte(iop_base,
8675 (ushort)ASCV_SCSIBUSY_B,
8676 scsi_busy);
8677 asc_dvc->queue_full_or_busy &= ~target_id;
8678 }
8679 }
8680 if (asc_dvc->cur_total_qng >= n_q_used) {
8681 asc_dvc->cur_total_qng -= n_q_used;
8682 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
8683 asc_dvc->cur_dvc_qng[tid_no]--;
8684 }
8685 } else {
8686 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
8687 scsiq->d3.done_stat = QD_WITH_ERROR;
8688 goto FATAL_ERR_QDONE;
8689 }
8690 if ((scsiq->d2.srb_ptr == 0UL) ||
8691 ((scsiq->q_status & QS_ABORTED) != 0)) {
8692 return (0x11);
8693 } else if (scsiq->q_status == QS_DONE) {
8694 false_overrun = FALSE;
8695 if (scsiq->extra_bytes != 0) {
8696 scsiq->remain_bytes +=
8697 (ADV_DCNT)scsiq->extra_bytes;
8698 }
8699 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
8700 if (scsiq->d3.host_stat ==
8701 QHSTA_M_DATA_OVER_RUN) {
8702 if ((scsiq->
8703 cntl & (QC_DATA_IN | QC_DATA_OUT))
8704 == 0) {
8705 scsiq->d3.done_stat =
8706 QD_NO_ERROR;
8707 scsiq->d3.host_stat =
8708 QHSTA_NO_ERROR;
8709 } else if (false_overrun) {
8710 scsiq->d3.done_stat =
8711 QD_NO_ERROR;
8712 scsiq->d3.host_stat =
8713 QHSTA_NO_ERROR;
8714 }
8715 } else if (scsiq->d3.host_stat ==
8716 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
8717 AscStopChip(iop_base);
8718 AscSetChipControl(iop_base,
8719 (uchar)(CC_SCSI_RESET
8720 | CC_HALT));
8721 DvcDelayNanoSecond(asc_dvc, 60000);
8722 AscSetChipControl(iop_base, CC_HALT);
8723 AscSetChipStatus(iop_base,
8724 CIW_CLR_SCSI_RESET_INT);
8725 AscSetChipStatus(iop_base, 0);
8726 AscSetChipControl(iop_base, 0);
8727 }
8728 }
8729 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04008730 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008731 } else {
8732 if ((AscReadLramByte(iop_base,
8733 (ushort)(q_addr + (ushort)
8734 ASC_SCSIQ_CDB_BEG))
8735 == START_STOP)) {
8736 asc_dvc->unit_not_ready &= ~target_id;
8737 if (scsiq->d3.done_stat != QD_NO_ERROR) {
8738 asc_dvc->start_motor &=
8739 ~target_id;
8740 }
8741 }
8742 }
8743 return (1);
8744 } else {
8745 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
8746 FATAL_ERR_QDONE:
8747 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04008748 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008749 }
8750 return (0x80);
8751 }
8752 }
8753 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008754}
8755
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008756static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008757{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008758 ASC_CS_TYPE chipstat;
8759 PortAddr iop_base;
8760 ushort saved_ram_addr;
8761 uchar ctrl_reg;
8762 uchar saved_ctrl_reg;
8763 int int_pending;
8764 int status;
8765 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008767 iop_base = asc_dvc->iop_base;
8768 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008770 if (AscIsIntPending(iop_base) == 0) {
8771 return int_pending;
8772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008773
Matthew Wilcox895d6b42007-07-26 11:57:06 -04008774 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008775 return (ERR);
8776 }
8777 if (asc_dvc->in_critical_cnt != 0) {
8778 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
8779 return (ERR);
8780 }
8781 if (asc_dvc->is_in_int) {
8782 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
8783 return (ERR);
8784 }
8785 asc_dvc->is_in_int = TRUE;
8786 ctrl_reg = AscGetChipControl(iop_base);
8787 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
8788 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
8789 chipstat = AscGetChipStatus(iop_base);
8790 if (chipstat & CSW_SCSI_RESET_LATCH) {
8791 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
8792 int i = 10;
8793 int_pending = TRUE;
8794 asc_dvc->sdtr_done = 0;
8795 saved_ctrl_reg &= (uchar)(~CC_HALT);
8796 while ((AscGetChipStatus(iop_base) &
8797 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
8798 DvcSleepMilliSecond(100);
8799 }
8800 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
8801 AscSetChipControl(iop_base, CC_HALT);
8802 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
8803 AscSetChipStatus(iop_base, 0);
8804 chipstat = AscGetChipStatus(iop_base);
8805 }
8806 }
8807 saved_ram_addr = AscGetChipLramAddr(iop_base);
8808 host_flag = AscReadLramByte(iop_base,
8809 ASCV_HOST_FLAG_B) &
8810 (uchar)(~ASC_HOST_FLAG_IN_ISR);
8811 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8812 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
8813 if ((chipstat & CSW_INT_PENDING)
8814 || (int_pending)
8815 ) {
8816 AscAckInterrupt(iop_base);
8817 int_pending = TRUE;
8818 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
8819 if (AscIsrChipHalted(asc_dvc) == ERR) {
8820 goto ISR_REPORT_QDONE_FATAL_ERROR;
8821 } else {
8822 saved_ctrl_reg &= (uchar)(~CC_HALT);
8823 }
8824 } else {
8825 ISR_REPORT_QDONE_FATAL_ERROR:
8826 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
8827 while (((status =
8828 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
8829 }
8830 } else {
8831 do {
8832 if ((status =
8833 AscIsrQDone(asc_dvc)) == 1) {
8834 break;
8835 }
8836 } while (status == 0x11);
8837 }
8838 if ((status & 0x80) != 0)
8839 int_pending = ERR;
8840 }
8841 }
8842 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8843 AscSetChipLramAddr(iop_base, saved_ram_addr);
8844 AscSetChipControl(iop_base, saved_ctrl_reg);
8845 asc_dvc->is_in_int = FALSE;
8846 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008847}
8848
8849/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008850static uchar _asc_mcode_buf[] = {
8851 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8852 0x00, 0x00, 0x00, 0x00,
8853 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
8854 0x00, 0x00, 0x00, 0x00,
8855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8856 0x00, 0x00, 0x00, 0x00,
8857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8858 0x00, 0x00, 0x00, 0x00,
8859 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00,
8860 0x00, 0xFF, 0x00, 0x00,
8861 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
8862 0x00, 0x00, 0x00, 0x00,
8863 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
8864 0x00, 0x00, 0x00, 0x00,
8865 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88,
8866 0x00, 0x00, 0x00, 0x00,
8867 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73,
8868 0x03, 0x23, 0x36, 0x40,
8869 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
8870 0xC2, 0x00, 0x92, 0x80,
8871 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60,
8872 0xB6, 0x00, 0x92, 0x80,
8873 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00,
8874 0x92, 0x80, 0x80, 0x62,
8875 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
8876 0xCD, 0x04, 0x4D, 0x00,
8877 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01,
8878 0xE6, 0x84, 0xD2, 0xC1,
8879 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97,
8880 0xC6, 0x81, 0xC2, 0x88,
8881 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
8882 0x84, 0x97, 0x07, 0xA6,
8883 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE,
8884 0xC2, 0x88, 0xCE, 0x00,
8885 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01,
8886 0x80, 0x63, 0x07, 0xA6,
8887 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
8888 0x34, 0x01, 0x00, 0x33,
8889 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23,
8890 0x68, 0x98, 0x4D, 0x04,
8891 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23,
8892 0xF8, 0x88, 0xFB, 0x23,
8893 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
8894 0x00, 0x33, 0x0A, 0x00,
8895 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00,
8896 0xC2, 0x88, 0xCD, 0x04,
8897 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81,
8898 0x06, 0xAB, 0x82, 0x01,
8899 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
8900 0x3C, 0x01, 0x00, 0x05,
8901 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01,
8902 0x15, 0x23, 0xA1, 0x01,
8903 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00,
8904 0x06, 0x61, 0x00, 0xA0,
8905 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
8906 0xC2, 0x88, 0x06, 0x23,
8907 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01,
8908 0x57, 0x60, 0x00, 0xA0,
8909 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73,
8910 0x4B, 0x00, 0x06, 0x61,
8911 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
8912 0x4F, 0x00, 0x84, 0x97,
8913 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97,
8914 0x48, 0x04, 0x84, 0x80,
8915 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00,
8916 0x81, 0x73, 0x06, 0x29,
8917 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
8918 0x04, 0x98, 0xF0, 0x80,
8919 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6,
8920 0x34, 0x02, 0x03, 0xA6,
8921 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96,
8922 0x46, 0x82, 0xFE, 0x95,
8923 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
8924 0x07, 0xA6, 0x5A, 0x02,
8925 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95,
8926 0x48, 0x82, 0x60, 0x96,
8927 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84,
8928 0x04, 0x01, 0x0C, 0xDC,
8929 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
8930 0x6F, 0x00, 0xA5, 0x01,
8931 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01,
8932 0x02, 0xA6, 0xAA, 0x02,
8933 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04,
8934 0x01, 0xA6, 0xB4, 0x02,
8935 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
8936 0x80, 0x63, 0x00, 0x43,
8937 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23,
8938 0x04, 0x61, 0x84, 0x01,
8939 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F,
8940 0x00, 0x00, 0xEA, 0x82,
8941 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
8942 0x00, 0x33, 0x1F, 0x00,
8943 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98,
8944 0xB6, 0x2D, 0x01, 0xA6,
8945 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6,
8946 0x10, 0x03, 0x03, 0xA6,
8947 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
8948 0x7C, 0x95, 0xEE, 0x82,
8949 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4,
8950 0x04, 0x01, 0x2D, 0xC8,
8951 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01,
8952 0x05, 0x05, 0x86, 0x98,
8953 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
8954 0x3C, 0x04, 0x06, 0xA6,
8955 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88,
8956 0x7C, 0x95, 0x32, 0x83,
8957 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05,
8958 0xEB, 0x04, 0x00, 0x33,
8959 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
8960 0xFF, 0xA2, 0x7A, 0x03,
8961 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01,
8962 0x00, 0xA2, 0x9A, 0x03,
8963 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
8964 0x01, 0xA6, 0x96, 0x03,
8965 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
8966 0xA4, 0x03, 0x00, 0xA6,
8967 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03,
8968 0x07, 0xA6, 0xB2, 0x03,
8969 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88,
8970 0xA8, 0x98, 0x80, 0x42,
8971 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
8972 0xC0, 0x83, 0x00, 0x33,
8973 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
8974 0xA0, 0x01, 0x12, 0x23,
8975 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B,
8976 0x80, 0x67, 0x05, 0x23,
8977 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
8978 0x06, 0xA6, 0x0A, 0x04,
8979 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96,
8980 0xF4, 0x83, 0x20, 0x84,
8981 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
8982 0x83, 0x03, 0x80, 0x63,
8983 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
8984 0x38, 0x04, 0x00, 0x33,
8985 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84,
8986 0x1D, 0x01, 0x06, 0xCC,
8987 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62,
8988 0xA2, 0x0D, 0x80, 0x63,
8989 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
8990 0x80, 0x63, 0xA3, 0x01,
8991 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0,
8992 0x76, 0x04, 0xE0, 0x00,
8993 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00,
8994 0x00, 0x33, 0x1E, 0x00,
8995 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
8996 0x08, 0x23, 0x22, 0xA3,
8997 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3,
8998 0xC4, 0x04, 0x42, 0x23,
8999 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23,
9000 0xF8, 0x88, 0x04, 0x98,
9001 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
9002 0x81, 0x62, 0xE8, 0x81,
9003 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98,
9004 0x00, 0x33, 0x00, 0x81,
9005 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23,
9006 0xF8, 0x88, 0x04, 0x23,
9007 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
9008 0xF4, 0x04, 0x00, 0x33,
9009 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01,
9010 0x04, 0x23, 0xA0, 0x01,
9011 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00,
9012 0x00, 0xA3, 0x22, 0x05,
9013 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
9014 0x46, 0x97, 0xCD, 0x04,
9015 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23,
9016 0x82, 0x01, 0x34, 0x85,
9017 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05,
9018 0x1D, 0x01, 0x04, 0xD6,
9019 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
9020 0x49, 0x00, 0x81, 0x01,
9021 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01,
9022 0x49, 0x04, 0x80, 0x01,
9023 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04,
9024 0x01, 0x23, 0xEA, 0x00,
9025 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
9026 0x07, 0xA4, 0xF8, 0x05,
9027 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00,
9028 0xC2, 0x88, 0x04, 0xA0,
9029 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61,
9030 0x00, 0xA2, 0xA4, 0x05,
9031 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
9032 0x62, 0x97, 0x04, 0x85,
9033 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05,
9034 0xF4, 0x85, 0x03, 0xA0,
9035 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63,
9036 0xCC, 0x86, 0x07, 0xA0,
9037 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
9038 0x80, 0x67, 0x80, 0x63,
9039 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23,
9040 0xF8, 0x88, 0x07, 0x23,
9041 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00,
9042 0x00, 0x63, 0x4A, 0x00,
9043 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
9044 0x07, 0x41, 0x83, 0x03,
9045 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88,
9046 0x1D, 0x01, 0x01, 0xD6,
9047 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00,
9048 0x07, 0xA6, 0x7C, 0x05,
9049 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
9050 0x52, 0x00, 0x06, 0x61,
9051 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41,
9052 0x00, 0x63, 0x1D, 0x01,
9053 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23,
9054 0x07, 0x41, 0x00, 0x63,
9055 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
9056 0xDF, 0x00, 0x06, 0xA6,
9057 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33,
9058 0x00, 0x40, 0xC0, 0x20,
9059 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63,
9060 0x06, 0xA6, 0x94, 0x06,
9061 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
9062 0x40, 0x0E, 0x80, 0x63,
9063 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E,
9064 0x80, 0x63, 0x00, 0x43,
9065 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05,
9066 0x80, 0x67, 0x40, 0x0E,
9067 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
9068 0x07, 0xA6, 0xD6, 0x06,
9069 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00,
9070 0x0A, 0x2B, 0x07, 0xA6,
9071 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2,
9072 0xF4, 0x06, 0xC0, 0x0E,
9073 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
9074 0x81, 0x62, 0x04, 0x01,
9075 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
9076 0x8C, 0x06, 0x00, 0x33,
9077 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03,
9078 0x80, 0x63, 0x06, 0xA6,
9079 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
9080 0x00, 0x00, 0x80, 0x67,
9081 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05,
9082 0xBF, 0x23, 0x04, 0x61,
9083 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00,
9084 0x00, 0x01, 0xF2, 0x00,
9085 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
9086 0x80, 0x05, 0x81, 0x05,
9087 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00,
9088 0x70, 0x00, 0x81, 0x01,
9089 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04,
9090 0x70, 0x00, 0x80, 0x01,
9091 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
9092 0xF1, 0x00, 0x70, 0x00,
9093 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01,
9094 0x71, 0x04, 0x70, 0x00,
9095 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05,
9096 0xA3, 0x01, 0xA2, 0x01,
9097 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
9098 0xC4, 0x07, 0x00, 0x33,
9099 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8,
9100 0x48, 0x00, 0xB0, 0x01,
9101 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43,
9102 0x00, 0xA2, 0xE4, 0x07,
9103 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
9104 0x05, 0x05, 0x00, 0x63,
9105 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43,
9106 0x76, 0x08, 0x80, 0x02,
9107 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
9108 0x00, 0x02, 0x00, 0xA0,
9109 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
9110 0x00, 0x63, 0xF3, 0x04,
9111 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40,
9112 0x00, 0xA2, 0x44, 0x08,
9113 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1,
9114 0x24, 0x08, 0x04, 0x98,
9115 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
9116 0x5A, 0x88, 0x02, 0x01,
9117 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00,
9118 0x00, 0xA3, 0x64, 0x08,
9119 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63,
9120 0x06, 0xA6, 0x76, 0x08,
9121 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
9122 0x00, 0x63, 0x38, 0x2B,
9123 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98,
9124 0x05, 0x05, 0xB2, 0x09,
9125 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63,
9126 0x80, 0x32, 0x80, 0x36,
9127 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
9128 0x40, 0x36, 0x40, 0x3A,
9129 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08,
9130 0x5D, 0x00, 0xFE, 0xC3,
9131 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73,
9132 0xFF, 0xFD, 0x80, 0x73,
9133 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
9134 0xA1, 0x23, 0xA1, 0x01,
9135 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2,
9136 0x80, 0x00, 0x03, 0xC2,
9137 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23,
9138 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009139};
9140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009141static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
9142static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009143
9144#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009145static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
9146 INQUIRY,
9147 REQUEST_SENSE,
9148 READ_CAPACITY,
9149 READ_TOC,
9150 MODE_SELECT,
9151 MODE_SENSE,
9152 MODE_SELECT_10,
9153 MODE_SENSE_10,
9154 0xFF,
9155 0xFF,
9156 0xFF,
9157 0xFF,
9158 0xFF,
9159 0xFF,
9160 0xFF,
9161 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07009162};
9163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009164static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009165{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009166 PortAddr iop_base;
9167 ulong last_int_level;
9168 int sta;
9169 int n_q_required;
9170 int disable_syn_offset_one_fix;
9171 int i;
9172 ASC_PADDR addr;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009173 ushort sg_entry_cnt = 0;
9174 ushort sg_entry_cnt_minus_one = 0;
9175 uchar target_ix;
9176 uchar tid_no;
9177 uchar sdtr_data;
9178 uchar extra_bytes;
9179 uchar scsi_cmd;
9180 uchar disable_cmd;
9181 ASC_SG_HEAD *sg_head;
9182 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009184 iop_base = asc_dvc->iop_base;
9185 sg_head = scsiq->sg_head;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009186 if (asc_dvc->err_code != 0)
9187 return (ERR);
9188 if (scsiq == (ASC_SCSI_Q *)0L) {
9189 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
9190 return (ERR);
9191 }
9192 scsiq->q1.q_no = 0;
9193 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
9194 scsiq->q1.extra_bytes = 0;
9195 }
9196 sta = 0;
9197 target_ix = scsiq->q2.target_ix;
9198 tid_no = ASC_TIX_TO_TID(target_ix);
9199 n_q_required = 1;
9200 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
9201 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
9202 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
9203 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9204 AscMsgOutSDTR(asc_dvc,
9205 asc_dvc->
9206 sdtr_period_tbl[(sdtr_data >> 4) &
9207 (uchar)(asc_dvc->
9208 max_sdtr_index -
9209 1)],
9210 (uchar)(sdtr_data & (uchar)
9211 ASC_SYN_MAX_OFFSET));
9212 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
9213 }
9214 }
9215 last_int_level = DvcEnterCritical();
9216 if (asc_dvc->in_critical_cnt != 0) {
9217 DvcLeaveCritical(last_int_level);
9218 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
9219 return (ERR);
9220 }
9221 asc_dvc->in_critical_cnt++;
9222 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
9223 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
9224 asc_dvc->in_critical_cnt--;
9225 DvcLeaveCritical(last_int_level);
9226 return (ERR);
9227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009228#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009229 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
9230 asc_dvc->in_critical_cnt--;
9231 DvcLeaveCritical(last_int_level);
9232 return (ERR);
9233 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009234#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009235 if (sg_entry_cnt == 1) {
9236 scsiq->q1.data_addr =
9237 (ADV_PADDR)sg_head->sg_list[0].addr;
9238 scsiq->q1.data_cnt =
9239 (ADV_DCNT)sg_head->sg_list[0].bytes;
9240 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
9241 }
9242 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
9243 }
9244 scsi_cmd = scsiq->cdbptr[0];
9245 disable_syn_offset_one_fix = FALSE;
9246 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
9247 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
9248 if (scsiq->q1.cntl & QC_SG_HEAD) {
9249 data_cnt = 0;
9250 for (i = 0; i < sg_entry_cnt; i++) {
9251 data_cnt +=
9252 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
9253 bytes);
9254 }
9255 } else {
9256 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
9257 }
9258 if (data_cnt != 0UL) {
9259 if (data_cnt < 512UL) {
9260 disable_syn_offset_one_fix = TRUE;
9261 } else {
9262 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
9263 i++) {
9264 disable_cmd =
9265 _syn_offset_one_disable_cmd[i];
9266 if (disable_cmd == 0xFF) {
9267 break;
9268 }
9269 if (scsi_cmd == disable_cmd) {
9270 disable_syn_offset_one_fix =
9271 TRUE;
9272 break;
9273 }
9274 }
9275 }
9276 }
9277 }
9278 if (disable_syn_offset_one_fix) {
9279 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
9280 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
9281 ASC_TAG_FLAG_DISABLE_DISCONNECT);
9282 } else {
9283 scsiq->q2.tag_code &= 0x27;
9284 }
9285 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
9286 if (asc_dvc->bug_fix_cntl) {
9287 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
9288 if ((scsi_cmd == READ_6) ||
9289 (scsi_cmd == READ_10)) {
9290 addr =
9291 (ADV_PADDR)le32_to_cpu(sg_head->
9292 sg_list
9293 [sg_entry_cnt_minus_one].
9294 addr) +
9295 (ADV_DCNT)le32_to_cpu(sg_head->
9296 sg_list
9297 [sg_entry_cnt_minus_one].
9298 bytes);
9299 extra_bytes =
9300 (uchar)((ushort)addr & 0x0003);
9301 if ((extra_bytes != 0)
9302 &&
9303 ((scsiq->q2.
9304 tag_code &
9305 ASC_TAG_FLAG_EXTRA_BYTES)
9306 == 0)) {
9307 scsiq->q2.tag_code |=
9308 ASC_TAG_FLAG_EXTRA_BYTES;
9309 scsiq->q1.extra_bytes =
9310 extra_bytes;
9311 data_cnt =
9312 le32_to_cpu(sg_head->
9313 sg_list
9314 [sg_entry_cnt_minus_one].
9315 bytes);
9316 data_cnt -=
9317 (ASC_DCNT) extra_bytes;
9318 sg_head->
9319 sg_list
9320 [sg_entry_cnt_minus_one].
9321 bytes =
9322 cpu_to_le32(data_cnt);
9323 }
9324 }
9325 }
9326 }
9327 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009328#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009329 /*
9330 * Set the sg_entry_cnt to the maximum possible. The rest of
9331 * the SG elements will be copied when the RISC completes the
9332 * SG elements that fit and halts.
9333 */
9334 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
9335 sg_entry_cnt = ASC_MAX_SG_LIST;
9336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009337#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009338 n_q_required = AscSgListToQueue(sg_entry_cnt);
9339 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
9340 (uint) n_q_required)
9341 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
9342 if ((sta =
9343 AscSendScsiQueue(asc_dvc, scsiq,
9344 n_q_required)) == 1) {
9345 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009346 DvcLeaveCritical(last_int_level);
9347 return (sta);
9348 }
9349 }
9350 } else {
9351 if (asc_dvc->bug_fix_cntl) {
9352 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
9353 if ((scsi_cmd == READ_6) ||
9354 (scsi_cmd == READ_10)) {
9355 addr =
9356 le32_to_cpu(scsiq->q1.data_addr) +
9357 le32_to_cpu(scsiq->q1.data_cnt);
9358 extra_bytes =
9359 (uchar)((ushort)addr & 0x0003);
9360 if ((extra_bytes != 0)
9361 &&
9362 ((scsiq->q2.
9363 tag_code &
9364 ASC_TAG_FLAG_EXTRA_BYTES)
9365 == 0)) {
9366 data_cnt =
9367 le32_to_cpu(scsiq->q1.
9368 data_cnt);
9369 if (((ushort)data_cnt & 0x01FF)
9370 == 0) {
9371 scsiq->q2.tag_code |=
9372 ASC_TAG_FLAG_EXTRA_BYTES;
9373 data_cnt -= (ASC_DCNT)
9374 extra_bytes;
9375 scsiq->q1.data_cnt =
9376 cpu_to_le32
9377 (data_cnt);
9378 scsiq->q1.extra_bytes =
9379 extra_bytes;
9380 }
9381 }
9382 }
9383 }
9384 }
9385 n_q_required = 1;
9386 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
9387 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
9388 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
9389 n_q_required)) == 1) {
9390 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009391 DvcLeaveCritical(last_int_level);
9392 return (sta);
9393 }
9394 }
9395 }
9396 asc_dvc->in_critical_cnt--;
9397 DvcLeaveCritical(last_int_level);
9398 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009399}
9400
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009401static int
9402AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009403{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009404 PortAddr iop_base;
9405 uchar free_q_head;
9406 uchar next_qp;
9407 uchar tid_no;
9408 uchar target_ix;
9409 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009411 iop_base = asc_dvc->iop_base;
9412 target_ix = scsiq->q2.target_ix;
9413 tid_no = ASC_TIX_TO_TID(target_ix);
9414 sta = 0;
9415 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
9416 if (n_q_required > 1) {
9417 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
9418 free_q_head, (uchar)
9419 (n_q_required)))
9420 != (uchar)ASC_QLINK_END) {
9421 asc_dvc->last_q_shortage = 0;
9422 scsiq->sg_head->queue_cnt = n_q_required - 1;
9423 scsiq->q1.q_no = free_q_head;
9424 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
9425 free_q_head)) == 1) {
9426 AscPutVarFreeQHead(iop_base, next_qp);
9427 asc_dvc->cur_total_qng += (uchar)(n_q_required);
9428 asc_dvc->cur_dvc_qng[tid_no]++;
9429 }
9430 return (sta);
9431 }
9432 } else if (n_q_required == 1) {
9433 if ((next_qp = AscAllocFreeQueue(iop_base,
9434 free_q_head)) !=
9435 ASC_QLINK_END) {
9436 scsiq->q1.q_no = free_q_head;
9437 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
9438 free_q_head)) == 1) {
9439 AscPutVarFreeQHead(iop_base, next_qp);
9440 asc_dvc->cur_total_qng++;
9441 asc_dvc->cur_dvc_qng[tid_no]++;
9442 }
9443 return (sta);
9444 }
9445 }
9446 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009447}
9448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009449static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009450{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009451 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009453 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
9454 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
9455 n_sg_list_qs++;
9456 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009457}
9458
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009459static uint
9460AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009461{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009462 uint cur_used_qs;
9463 uint cur_free_qs;
9464 ASC_SCSI_BIT_ID_TYPE target_id;
9465 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009467 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
9468 tid_no = ASC_TIX_TO_TID(target_ix);
9469 if ((asc_dvc->unit_not_ready & target_id) ||
9470 (asc_dvc->queue_full_or_busy & target_id)) {
9471 return (0);
9472 }
9473 if (n_qs == 1) {
9474 cur_used_qs = (uint) asc_dvc->cur_total_qng +
9475 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
9476 } else {
9477 cur_used_qs = (uint) asc_dvc->cur_total_qng +
9478 (uint) ASC_MIN_FREE_Q;
9479 }
9480 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
9481 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
9482 if (asc_dvc->cur_dvc_qng[tid_no] >=
9483 asc_dvc->max_dvc_qng[tid_no]) {
9484 return (0);
9485 }
9486 return (cur_free_qs);
9487 }
9488 if (n_qs > 1) {
9489 if ((n_qs > asc_dvc->last_q_shortage)
9490 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
9491 asc_dvc->last_q_shortage = n_qs;
9492 }
9493 }
9494 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009495}
9496
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009497static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009498{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009499 ushort q_addr;
9500 uchar tid_no;
9501 uchar sdtr_data;
9502 uchar syn_period_ix;
9503 uchar syn_offset;
9504 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009505
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009506 iop_base = asc_dvc->iop_base;
9507 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
9508 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
9509 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
9510 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9511 syn_period_ix =
9512 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
9513 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
9514 AscMsgOutSDTR(asc_dvc,
9515 asc_dvc->sdtr_period_tbl[syn_period_ix],
9516 syn_offset);
9517 scsiq->q1.cntl |= QC_MSG_OUT;
9518 }
9519 q_addr = ASC_QNO_TO_QADDR(q_no);
9520 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
9521 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
9522 }
9523 scsiq->q1.status = QS_FREE;
9524 AscMemWordCopyPtrToLram(iop_base,
9525 q_addr + ASC_SCSIQ_CDB_BEG,
9526 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009528 DvcPutScsiQ(iop_base,
9529 q_addr + ASC_SCSIQ_CPY_BEG,
9530 (uchar *)&scsiq->q1.cntl,
9531 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
9532 AscWriteLramWord(iop_base,
9533 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
9534 (ushort)(((ushort)scsiq->q1.
9535 q_no << 8) | (ushort)QS_READY));
9536 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009537}
9538
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009539static int
9540AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009541{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009542 int sta;
9543 int i;
9544 ASC_SG_HEAD *sg_head;
9545 ASC_SG_LIST_Q scsi_sg_q;
9546 ASC_DCNT saved_data_addr;
9547 ASC_DCNT saved_data_cnt;
9548 PortAddr iop_base;
9549 ushort sg_list_dwords;
9550 ushort sg_index;
9551 ushort sg_entry_cnt;
9552 ushort q_addr;
9553 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009554
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009555 iop_base = asc_dvc->iop_base;
9556 sg_head = scsiq->sg_head;
9557 saved_data_addr = scsiq->q1.data_addr;
9558 saved_data_cnt = scsiq->q1.data_cnt;
9559 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
9560 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009561#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009562 /*
9563 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
9564 * then not all SG elements will fit in the allocated queues.
9565 * The rest of the SG elements will be copied when the RISC
9566 * completes the SG elements that fit and halts.
9567 */
9568 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
9569 /*
9570 * Set sg_entry_cnt to be the number of SG elements that
9571 * will fit in the allocated SG queues. It is minus 1, because
9572 * the first SG element is handled above. ASC_MAX_SG_LIST is
9573 * already inflated by 1 to account for this. For example it
9574 * may be 50 which is 1 + 7 queues * 7 SG elements.
9575 */
9576 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009577
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009578 /*
9579 * Keep track of remaining number of SG elements that will
9580 * need to be handled from a_isr.c.
9581 */
9582 scsiq->remain_sg_entry_cnt =
9583 sg_head->entry_cnt - ASC_MAX_SG_LIST;
9584 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009585#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009586 /*
9587 * Set sg_entry_cnt to be the number of SG elements that
9588 * will fit in the allocated SG queues. It is minus 1, because
9589 * the first SG element is handled above.
9590 */
9591 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009592#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009594#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009595 if (sg_entry_cnt != 0) {
9596 scsiq->q1.cntl |= QC_SG_HEAD;
9597 q_addr = ASC_QNO_TO_QADDR(q_no);
9598 sg_index = 1;
9599 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
9600 scsi_sg_q.sg_head_qp = q_no;
9601 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9602 for (i = 0; i < sg_head->queue_cnt; i++) {
9603 scsi_sg_q.seq_no = i + 1;
9604 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9605 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9606 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9607 if (i == 0) {
9608 scsi_sg_q.sg_list_cnt =
9609 ASC_SG_LIST_PER_Q;
9610 scsi_sg_q.sg_cur_list_cnt =
9611 ASC_SG_LIST_PER_Q;
9612 } else {
9613 scsi_sg_q.sg_list_cnt =
9614 ASC_SG_LIST_PER_Q - 1;
9615 scsi_sg_q.sg_cur_list_cnt =
9616 ASC_SG_LIST_PER_Q - 1;
9617 }
9618 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009619#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009620 /*
9621 * This is the last SG queue in the list of
9622 * allocated SG queues. If there are more
9623 * SG elements than will fit in the allocated
9624 * queues, then set the QCSG_SG_XFER_MORE flag.
9625 */
9626 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
9627 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9628 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009629#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009630 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009631#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009633#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009634 sg_list_dwords = sg_entry_cnt << 1;
9635 if (i == 0) {
9636 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
9637 scsi_sg_q.sg_cur_list_cnt =
9638 sg_entry_cnt;
9639 } else {
9640 scsi_sg_q.sg_list_cnt =
9641 sg_entry_cnt - 1;
9642 scsi_sg_q.sg_cur_list_cnt =
9643 sg_entry_cnt - 1;
9644 }
9645 sg_entry_cnt = 0;
9646 }
9647 next_qp = AscReadLramByte(iop_base,
9648 (ushort)(q_addr +
9649 ASC_SCSIQ_B_FWD));
9650 scsi_sg_q.q_no = next_qp;
9651 q_addr = ASC_QNO_TO_QADDR(next_qp);
9652 AscMemWordCopyPtrToLram(iop_base,
9653 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9654 (uchar *)&scsi_sg_q,
9655 sizeof(ASC_SG_LIST_Q) >> 1);
9656 AscMemDWordCopyPtrToLram(iop_base,
9657 q_addr + ASC_SGQ_LIST_BEG,
9658 (uchar *)&sg_head->
9659 sg_list[sg_index],
9660 sg_list_dwords);
9661 sg_index += ASC_SG_LIST_PER_Q;
9662 scsiq->next_sg_index = sg_index;
9663 }
9664 } else {
9665 scsiq->q1.cntl &= ~QC_SG_HEAD;
9666 }
9667 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
9668 scsiq->q1.data_addr = saved_data_addr;
9669 scsiq->q1.data_cnt = saved_data_cnt;
9670 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009671}
9672
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009673static int
9674AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009675{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009676 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009677
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009678 if (AscHostReqRiscHalt(iop_base)) {
9679 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9680 AscStartChip(iop_base);
9681 return (sta);
9682 }
9683 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009684}
9685
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009686static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009687{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009688 ASC_SCSI_BIT_ID_TYPE org_id;
9689 int i;
9690 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009692 AscSetBank(iop_base, 1);
9693 org_id = AscReadChipDvcID(iop_base);
9694 for (i = 0; i <= ASC_MAX_TID; i++) {
9695 if (org_id == (0x01 << i))
9696 break;
9697 }
9698 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
9699 AscWriteChipDvcID(iop_base, id);
9700 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
9701 AscSetBank(iop_base, 0);
9702 AscSetChipSyn(iop_base, sdtr_data);
9703 if (AscGetChipSyn(iop_base) != sdtr_data) {
9704 sta = FALSE;
9705 }
9706 } else {
9707 sta = FALSE;
9708 }
9709 AscSetBank(iop_base, 1);
9710 AscWriteChipDvcID(iop_base, org_id);
9711 AscSetBank(iop_base, 0);
9712 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009713}
9714
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009715static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009716{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009717 uchar i;
9718 ushort s_addr;
9719 PortAddr iop_base;
9720 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009721
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009722 iop_base = asc_dvc->iop_base;
9723 warn_code = 0;
9724 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
9725 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
9726 64) >> 1)
9727 );
9728 i = ASC_MIN_ACTIVE_QNO;
9729 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
9730 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
9731 (uchar)(i + 1));
9732 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
9733 (uchar)(asc_dvc->max_total_qng));
9734 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
9735 (uchar)i);
9736 i++;
9737 s_addr += ASC_QBLK_SIZE;
9738 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
9739 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
9740 (uchar)(i + 1));
9741 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
9742 (uchar)(i - 1));
9743 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
9744 (uchar)i);
9745 }
9746 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
9747 (uchar)ASC_QLINK_END);
9748 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
9749 (uchar)(asc_dvc->max_total_qng - 1));
9750 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
9751 (uchar)asc_dvc->max_total_qng);
9752 i++;
9753 s_addr += ASC_QBLK_SIZE;
9754 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
9755 i++, s_addr += ASC_QBLK_SIZE) {
9756 AscWriteLramByte(iop_base,
9757 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
9758 AscWriteLramByte(iop_base,
9759 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
9760 AscWriteLramByte(iop_base,
9761 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
9762 }
9763 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009764}
9765
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009766static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009767{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009768 PortAddr iop_base;
9769 int i;
9770 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009771
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009772 iop_base = asc_dvc->iop_base;
9773 AscPutRiscVarFreeQHead(iop_base, 1);
9774 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
9775 AscPutVarFreeQHead(iop_base, 1);
9776 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
9777 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
9778 (uchar)((int)asc_dvc->max_total_qng + 1));
9779 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
9780 (uchar)((int)asc_dvc->max_total_qng + 2));
9781 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
9782 asc_dvc->max_total_qng);
9783 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
9784 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9785 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
9786 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
9787 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
9788 AscPutQDoneInProgress(iop_base, 0);
9789 lram_addr = ASC_QADR_BEG;
9790 for (i = 0; i < 32; i++, lram_addr += 2) {
9791 AscWriteLramWord(iop_base, lram_addr, 0);
9792 }
9793 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009794}
9795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009796static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009797{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009798 if (asc_dvc->err_code == 0) {
9799 asc_dvc->err_code = err_code;
9800 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
9801 err_code);
9802 }
9803 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009804}
9805
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009806static uchar
9807AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009808{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009809 EXT_MSG sdtr_buf;
9810 uchar sdtr_period_index;
9811 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009813 iop_base = asc_dvc->iop_base;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009814 sdtr_buf.msg_type = EXTENDED_MESSAGE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009815 sdtr_buf.msg_len = MS_SDTR_LEN;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009816 sdtr_buf.msg_req = EXTENDED_SDTR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009817 sdtr_buf.xfer_period = sdtr_period;
9818 sdtr_offset &= ASC_SYN_MAX_OFFSET;
9819 sdtr_buf.req_ack_offset = sdtr_offset;
9820 if ((sdtr_period_index =
9821 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
9822 asc_dvc->max_sdtr_index) {
9823 AscMemWordCopyPtrToLram(iop_base,
9824 ASCV_MSGOUT_BEG,
9825 (uchar *)&sdtr_buf,
9826 sizeof(EXT_MSG) >> 1);
9827 return ((sdtr_period_index << 4) | sdtr_offset);
9828 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009829
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009830 sdtr_buf.req_ack_offset = 0;
9831 AscMemWordCopyPtrToLram(iop_base,
9832 ASCV_MSGOUT_BEG,
9833 (uchar *)&sdtr_buf,
9834 sizeof(EXT_MSG) >> 1);
9835 return (0);
9836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009837}
9838
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009839static uchar
9840AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009841{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009842 uchar byte;
9843 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009844
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009845 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
9846 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
9847 ) {
9848 return (0xFF);
9849 }
9850 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
9851 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009852}
9853
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009854static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009855{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009856 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9857 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
9858 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009859}
9860
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009861static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009862{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009863 uchar *period_table;
9864 int max_index;
9865 int min_index;
9866 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009868 period_table = asc_dvc->sdtr_period_tbl;
9869 max_index = (int)asc_dvc->max_sdtr_index;
9870 min_index = (int)asc_dvc->host_init_sdtr_index;
9871 if ((syn_time <= period_table[max_index])) {
9872 for (i = min_index; i < (max_index - 1); i++) {
9873 if (syn_time <= period_table[i]) {
9874 return ((uchar)i);
9875 }
9876 }
9877 return ((uchar)max_index);
9878 } else {
9879 return ((uchar)(max_index + 1));
9880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009881}
9882
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009883static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009884{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009885 ushort q_addr;
9886 uchar next_qp;
9887 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009889 q_addr = ASC_QNO_TO_QADDR(free_q_head);
9890 q_status = (uchar)AscReadLramByte(iop_base,
9891 (ushort)(q_addr +
9892 ASC_SCSIQ_B_STATUS));
9893 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
9894 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
9895 return (next_qp);
9896 }
9897 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009898}
9899
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009900static uchar
9901AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009902{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009903 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009904
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009905 for (i = 0; i < n_free_q; i++) {
9906 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
9907 == ASC_QLINK_END) {
9908 return (ASC_QLINK_END);
9909 }
9910 }
9911 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009912}
9913
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009914static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009915{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009916 int count = 0;
9917 int sta = 0;
9918 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009920 if (AscIsChipHalted(iop_base))
9921 return (1);
9922 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
9923 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9924 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
9925 do {
9926 if (AscIsChipHalted(iop_base)) {
9927 sta = 1;
9928 break;
9929 }
9930 DvcSleepMilliSecond(100);
9931 } while (count++ < 20);
9932 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
9933 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009934}
9935
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009936static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009937{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009938 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009940 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
9941 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9942 ASC_STOP_REQ_RISC_STOP);
9943 do {
9944 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
9945 ASC_STOP_ACK_RISC_STOP) {
9946 return (1);
9947 }
9948 DvcSleepMilliSecond(100);
9949 } while (count++ < 20);
9950 }
9951 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009952}
9953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009954static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009955{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009956 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009957}
9958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009959static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009960{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009961 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009962}
9963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009964static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009965{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009966 AscSetChipControl(iop_base, 0);
9967 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
9968 return (0);
9969 }
9970 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009971}
9972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009973static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009974{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009975 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009977 cc_val =
9978 AscGetChipControl(iop_base) &
9979 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
9980 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
9981 AscSetChipIH(iop_base, INS_HALT);
9982 AscSetChipIH(iop_base, INS_RFLAG_WTM);
9983 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
9984 return (0);
9985 }
9986 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009987}
9988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009989static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009990{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009991 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
9992 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
9993 return (1);
9994 }
9995 }
9996 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009997}
9998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009999static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010000{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010001 AscSetBank(iop_base, 1);
10002 AscWriteChipIH(iop_base, ins_code);
10003 AscSetBank(iop_base, 0);
10004 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010005}
10006
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010007static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010008{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010009 uchar host_flag;
10010 uchar risc_flag;
10011 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010012
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010013 loop = 0;
10014 do {
10015 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
10016 if (loop++ > 0x7FFF) {
10017 break;
10018 }
10019 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
10020 host_flag =
10021 AscReadLramByte(iop_base,
10022 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
10023 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
10024 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
10025 AscSetChipStatus(iop_base, CIW_INT_ACK);
10026 loop = 0;
10027 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
10028 AscSetChipStatus(iop_base, CIW_INT_ACK);
10029 if (loop++ > 3) {
10030 break;
10031 }
10032 }
10033 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
10034 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010035}
10036
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010037static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010038{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010039 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010040
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010041 cfg = AscGetChipCfgLsw(iop_base);
10042 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
10043 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010044}
10045
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010046static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010047{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010048 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010049
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010050 cfg = AscGetChipCfgLsw(iop_base);
10051 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
10052 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010053}
10054
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010055static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010056{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010057 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010058
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010059 val = AscGetChipControl(iop_base) &
10060 (~
10061 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
10062 CC_CHIP_RESET));
10063 if (bank == 1) {
10064 val |= CC_BANK_ONE;
10065 } else if (bank == 2) {
10066 val |= CC_DIAG | CC_BANK_ONE;
10067 } else {
10068 val &= ~CC_BANK_ONE;
10069 }
10070 AscSetChipControl(iop_base, val);
10071 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010072}
10073
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010074static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010075{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010076 PortAddr iop_base;
10077 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010078
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010079 iop_base = asc_dvc->iop_base;
10080 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
10081 && (i-- > 0)) {
10082 DvcSleepMilliSecond(100);
10083 }
10084 AscStopChip(iop_base);
10085 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
10086 DvcDelayNanoSecond(asc_dvc, 60000);
10087 AscSetChipIH(iop_base, INS_RFLAG_WTM);
10088 AscSetChipIH(iop_base, INS_HALT);
10089 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
10090 AscSetChipControl(iop_base, CC_HALT);
10091 DvcSleepMilliSecond(200);
10092 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
10093 AscSetChipStatus(iop_base, 0);
10094 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010095}
10096
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010097static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010098{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010099 if (bus_type & ASC_IS_ISA)
10100 return (ASC_MAX_ISA_DMA_COUNT);
10101 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
10102 return (ASC_MAX_VL_DMA_COUNT);
10103 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010104}
10105
10106#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010107static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010108{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010109 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010111 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
10112 if (channel == 0x03)
10113 return (0);
10114 else if (channel == 0x00)
10115 return (7);
10116 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010117}
10118
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010119static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010120{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010121 ushort cfg_lsw;
10122 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010123
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010124 if ((dma_channel >= 5) && (dma_channel <= 7)) {
10125 if (dma_channel == 7)
10126 value = 0x00;
10127 else
10128 value = dma_channel - 4;
10129 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
10130 cfg_lsw |= value;
10131 AscSetChipCfgLsw(iop_base, cfg_lsw);
10132 return (AscGetIsaDmaChannel(iop_base));
10133 }
10134 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010135}
10136
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010137static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010138{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010139 speed_value &= 0x07;
10140 AscSetBank(iop_base, 1);
10141 AscWriteChipDmaSpeed(iop_base, speed_value);
10142 AscSetBank(iop_base, 0);
10143 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010144}
10145
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010146static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010147{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010148 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010149
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010150 AscSetBank(iop_base, 1);
10151 speed_value = AscReadChipDmaSpeed(iop_base);
10152 speed_value &= 0x07;
10153 AscSetBank(iop_base, 0);
10154 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010155}
10156#endif /* CONFIG_ISA */
10157
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010158static ushort __devinit AscInitGetConfig(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010159{
Matthew Wilcox9649af32007-07-26 21:51:47 -060010160 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010161
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010162 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
Matthew Wilcox9649af32007-07-26 21:51:47 -060010163 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010164 return (UW_ERR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010165
Matthew Wilcox9649af32007-07-26 21:51:47 -060010166 if (AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010167 warn_code |= AscInitAscDvcVar(asc_dvc);
10168 warn_code |= AscInitFromEEP(asc_dvc);
10169 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
Matthew Wilcoxecec1942007-07-30 08:08:22 -060010170 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010171 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010172 } else {
10173 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10174 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -060010175 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010176}
10177
Matthew Wilcox394dbf32007-07-26 11:56:40 -040010178static unsigned short __devinit
10179AscInitSetConfig(struct pci_dev *pdev, ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010180{
Matthew Wilcox394dbf32007-07-26 11:56:40 -040010181 PortAddr iop_base = asc_dvc->iop_base;
10182 unsigned short cfg_msw;
10183 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010184
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010185 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
10186 if (asc_dvc->err_code != 0)
Matthew Wilcox394dbf32007-07-26 11:56:40 -040010187 return UW_ERR;
10188 if (!AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010189 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
Matthew Wilcox394dbf32007-07-26 11:56:40 -040010190 return 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010192
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010193 cfg_msw = AscGetChipCfgMsw(iop_base);
10194 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
10195 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
10196 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
10197 AscSetChipCfgMsw(iop_base, cfg_msw);
10198 }
10199 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
10200 asc_dvc->cfg->cmd_qng_enabled) {
10201 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
10202 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
10203 }
10204 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
10205 warn_code |= ASC_WARN_AUTO_CONFIG;
10206 }
10207 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
10208 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
10209 != asc_dvc->irq_no) {
10210 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
10211 }
10212 }
Matthew Wilcox9649af32007-07-26 21:51:47 -060010213#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010214 if (asc_dvc->bus_type & ASC_IS_PCI) {
10215 cfg_msw &= 0xFFC0;
10216 AscSetChipCfgMsw(iop_base, cfg_msw);
10217 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
10218 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060010219 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
10220 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010221 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
10222 asc_dvc->bug_fix_cntl |=
10223 ASC_BUG_FIX_ASYN_USE_SYN;
10224 }
10225 }
Matthew Wilcox9649af32007-07-26 21:51:47 -060010226 } else
10227#endif /* CONFIG_PCI */
10228 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010229 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
10230 == ASC_CHIP_VER_ASYN_BUG) {
10231 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
10232 }
10233 }
10234 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
10235 asc_dvc->cfg->chip_scsi_id) {
10236 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
10237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010238#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010239 if (asc_dvc->bus_type & ASC_IS_ISA) {
10240 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
10241 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
10242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010243#endif /* CONFIG_ISA */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040010244
10245 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
10246 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010247}
10248
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010249static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010250{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010251 ushort warn_code;
10252 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010254 iop_base = asc_dvc->iop_base;
10255 warn_code = 0;
10256 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
10257 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
10258 AscResetChipAndScsiBus(asc_dvc);
10259 DvcSleepMilliSecond((ASC_DCNT)
10260 ((ushort)asc_dvc->scsi_reset_wait * 1000));
10261 }
10262 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
10263 if (asc_dvc->err_code != 0)
10264 return (UW_ERR);
10265 if (!AscFindSignature(asc_dvc->iop_base)) {
10266 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10267 return (warn_code);
10268 }
10269 AscDisableInterrupt(iop_base);
10270 warn_code |= AscInitLram(asc_dvc);
10271 if (asc_dvc->err_code != 0)
10272 return (UW_ERR);
10273 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
10274 (ulong)_asc_mcode_chksum);
10275 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
10276 _asc_mcode_size) != _asc_mcode_chksum) {
10277 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
10278 return (warn_code);
10279 }
10280 warn_code |= AscInitMicroCodeVar(asc_dvc);
10281 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
10282 AscEnableInterrupt(iop_base);
10283 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010284}
10285
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010286static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010287{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010288 int i;
10289 PortAddr iop_base;
10290 ushort warn_code;
10291 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010292
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010293 iop_base = asc_dvc->iop_base;
10294 warn_code = 0;
10295 asc_dvc->err_code = 0;
10296 if ((asc_dvc->bus_type &
10297 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
10298 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
10299 }
10300 AscSetChipControl(iop_base, CC_HALT);
10301 AscSetChipStatus(iop_base, 0);
10302 asc_dvc->bug_fix_cntl = 0;
10303 asc_dvc->pci_fix_asyn_xfer = 0;
10304 asc_dvc->pci_fix_asyn_xfer_always = 0;
10305 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
10306 asc_dvc->sdtr_done = 0;
10307 asc_dvc->cur_total_qng = 0;
10308 asc_dvc->is_in_int = 0;
10309 asc_dvc->in_critical_cnt = 0;
10310 asc_dvc->last_q_shortage = 0;
10311 asc_dvc->use_tagged_qng = 0;
10312 asc_dvc->no_scam = 0;
10313 asc_dvc->unit_not_ready = 0;
10314 asc_dvc->queue_full_or_busy = 0;
10315 asc_dvc->redo_scam = 0;
10316 asc_dvc->res2 = 0;
10317 asc_dvc->host_init_sdtr_index = 0;
10318 asc_dvc->cfg->can_tagged_qng = 0;
10319 asc_dvc->cfg->cmd_qng_enabled = 0;
10320 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
10321 asc_dvc->init_sdtr = 0;
10322 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
10323 asc_dvc->scsi_reset_wait = 3;
10324 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
10325 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
10326 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
10327 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
10328 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
10329 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
10330 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
10331 ASC_LIB_VERSION_MINOR;
10332 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
10333 asc_dvc->cfg->chip_version = chip_version;
10334 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
10335 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
10336 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
10337 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
10338 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
10339 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
10340 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
10341 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
10342 asc_dvc->max_sdtr_index = 7;
10343 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
10344 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
10345 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
10346 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
10347 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
10348 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
10349 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
10350 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
10351 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
10352 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
10353 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
10354 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
10355 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
10356 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
10357 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
10358 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
10359 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
10360 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
10361 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
10362 asc_dvc->max_sdtr_index = 15;
10363 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
10364 AscSetExtraControl(iop_base,
10365 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
10366 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
10367 AscSetExtraControl(iop_base,
10368 (SEC_ACTIVE_NEGATE |
10369 SEC_ENABLE_FILTER));
10370 }
10371 }
10372 if (asc_dvc->bus_type == ASC_IS_PCI) {
10373 AscSetExtraControl(iop_base,
10374 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
10375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010376
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010377 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010378#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010379 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
Matthew Wilcox59fcf842007-07-26 11:54:15 -040010380 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
10381 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
10382 asc_dvc->bus_type = ASC_IS_ISAPNP;
10383 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010384 asc_dvc->cfg->isa_dma_channel =
10385 (uchar)AscGetIsaDmaChannel(iop_base);
10386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010387#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010388 for (i = 0; i <= ASC_MAX_TID; i++) {
10389 asc_dvc->cur_dvc_qng[i] = 0;
10390 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
10391 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
10392 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
10393 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
10394 }
10395 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010396}
10397
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010398static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010399{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010400 ASCEEP_CONFIG eep_config_buf;
10401 ASCEEP_CONFIG *eep_config;
10402 PortAddr iop_base;
10403 ushort chksum;
10404 ushort warn_code;
10405 ushort cfg_msw, cfg_lsw;
10406 int i;
10407 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010408
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010409 iop_base = asc_dvc->iop_base;
10410 warn_code = 0;
10411 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
10412 AscStopQueueExe(iop_base);
10413 if ((AscStopChip(iop_base) == FALSE) ||
10414 (AscGetChipScsiCtrl(iop_base) != 0)) {
10415 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
10416 AscResetChipAndScsiBus(asc_dvc);
10417 DvcSleepMilliSecond((ASC_DCNT)
10418 ((ushort)asc_dvc->scsi_reset_wait * 1000));
10419 }
10420 if (AscIsChipHalted(iop_base) == FALSE) {
10421 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
10422 return (warn_code);
10423 }
10424 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
10425 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
10426 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
10427 return (warn_code);
10428 }
10429 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
10430 cfg_msw = AscGetChipCfgMsw(iop_base);
10431 cfg_lsw = AscGetChipCfgLsw(iop_base);
10432 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
10433 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
10434 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
10435 AscSetChipCfgMsw(iop_base, cfg_msw);
10436 }
10437 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
10438 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
10439 if (chksum == 0) {
10440 chksum = 0xaa55;
10441 }
10442 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
10443 warn_code |= ASC_WARN_AUTO_CONFIG;
10444 if (asc_dvc->cfg->chip_version == 3) {
10445 if (eep_config->cfg_lsw != cfg_lsw) {
10446 warn_code |= ASC_WARN_EEPROM_RECOVER;
10447 eep_config->cfg_lsw =
10448 AscGetChipCfgLsw(iop_base);
10449 }
10450 if (eep_config->cfg_msw != cfg_msw) {
10451 warn_code |= ASC_WARN_EEPROM_RECOVER;
10452 eep_config->cfg_msw =
10453 AscGetChipCfgMsw(iop_base);
10454 }
10455 }
10456 }
10457 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
10458 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
10459 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
10460 eep_config->chksum);
10461 if (chksum != eep_config->chksum) {
10462 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
10463 ASC_CHIP_VER_PCI_ULTRA_3050) {
10464 ASC_DBG(1,
10465 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
10466 eep_config->init_sdtr = 0xFF;
10467 eep_config->disc_enable = 0xFF;
10468 eep_config->start_motor = 0xFF;
10469 eep_config->use_cmd_qng = 0;
10470 eep_config->max_total_qng = 0xF0;
10471 eep_config->max_tag_qng = 0x20;
10472 eep_config->cntl = 0xBFFF;
10473 ASC_EEP_SET_CHIP_ID(eep_config, 7);
10474 eep_config->no_scam = 0;
10475 eep_config->adapter_info[0] = 0;
10476 eep_config->adapter_info[1] = 0;
10477 eep_config->adapter_info[2] = 0;
10478 eep_config->adapter_info[3] = 0;
10479 eep_config->adapter_info[4] = 0;
10480 /* Indicate EEPROM-less board. */
10481 eep_config->adapter_info[5] = 0xBB;
10482 } else {
10483 ASC_PRINT
10484 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
10485 write_eep = 1;
10486 warn_code |= ASC_WARN_EEPROM_CHKSUM;
10487 }
10488 }
10489 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
10490 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
10491 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
10492 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
10493 asc_dvc->start_motor = eep_config->start_motor;
10494 asc_dvc->dvc_cntl = eep_config->cntl;
10495 asc_dvc->no_scam = eep_config->no_scam;
10496 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
10497 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
10498 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
10499 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
10500 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
10501 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
10502 if (!AscTestExternalLram(asc_dvc)) {
10503 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
10504 ASC_IS_PCI_ULTRA)) {
10505 eep_config->max_total_qng =
10506 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
10507 eep_config->max_tag_qng =
10508 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
10509 } else {
10510 eep_config->cfg_msw |= 0x0800;
10511 cfg_msw |= 0x0800;
10512 AscSetChipCfgMsw(iop_base, cfg_msw);
10513 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
10514 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
10515 }
10516 } else {
10517 }
10518 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
10519 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
10520 }
10521 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
10522 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
10523 }
10524 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
10525 eep_config->max_tag_qng = eep_config->max_total_qng;
10526 }
10527 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
10528 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
10529 }
10530 asc_dvc->max_total_qng = eep_config->max_total_qng;
10531 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
10532 eep_config->use_cmd_qng) {
10533 eep_config->disc_enable = eep_config->use_cmd_qng;
10534 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
10535 }
10536 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
10537 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
10538 }
10539 ASC_EEP_SET_CHIP_ID(eep_config,
10540 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
10541 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
10542 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
10543 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
10544 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
10545 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010546
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010547 for (i = 0; i <= ASC_MAX_TID; i++) {
10548 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
10549 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
10550 asc_dvc->cfg->sdtr_period_offset[i] =
10551 (uchar)(ASC_DEF_SDTR_OFFSET |
10552 (asc_dvc->host_init_sdtr_index << 4));
10553 }
10554 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
10555 if (write_eep) {
10556 if ((i =
10557 AscSetEEPConfig(iop_base, eep_config,
10558 asc_dvc->bus_type)) != 0) {
10559 ASC_PRINT1
10560 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
10561 i);
10562 } else {
10563 ASC_PRINT
10564 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
10565 }
10566 }
10567 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010568}
10569
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010570static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010571{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010572 int i;
10573 ushort warn_code;
10574 PortAddr iop_base;
10575 ASC_PADDR phy_addr;
10576 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010577
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010578 iop_base = asc_dvc->iop_base;
10579 warn_code = 0;
10580 for (i = 0; i <= ASC_MAX_TID; i++) {
10581 AscPutMCodeInitSDTRAtID(iop_base, i,
10582 asc_dvc->cfg->sdtr_period_offset[i]
10583 );
10584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010585
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010586 AscInitQLinkVar(asc_dvc);
10587 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
10588 asc_dvc->cfg->disc_enable);
10589 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
10590 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010591
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010592 /* Align overrun buffer on an 8 byte boundary. */
10593 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
10594 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
10595 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
10596 (uchar *)&phy_addr, 1);
10597 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
10598 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
10599 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010601 asc_dvc->cfg->mcode_date =
10602 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
10603 asc_dvc->cfg->mcode_version =
10604 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010605
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010606 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
10607 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
10608 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
10609 return (warn_code);
10610 }
10611 if (AscStartChip(iop_base) != 1) {
10612 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
10613 return (warn_code);
10614 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010615
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010616 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010617}
10618
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010619static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010620{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010621 PortAddr iop_base;
10622 ushort q_addr;
10623 ushort saved_word;
10624 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010625
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010626 iop_base = asc_dvc->iop_base;
10627 sta = 0;
10628 q_addr = ASC_QNO_TO_QADDR(241);
10629 saved_word = AscReadLramWord(iop_base, q_addr);
10630 AscSetChipLramAddr(iop_base, q_addr);
10631 AscSetChipLramData(iop_base, 0x55AA);
10632 DvcSleepMilliSecond(10);
10633 AscSetChipLramAddr(iop_base, q_addr);
10634 if (AscGetChipLramData(iop_base) == 0x55AA) {
10635 sta = 1;
10636 AscWriteLramWord(iop_base, q_addr, saved_word);
10637 }
10638 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010639}
10640
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010641static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010642{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010643 uchar read_back;
10644 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010645
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010646 retry = 0;
10647 while (TRUE) {
10648 AscSetChipEEPCmd(iop_base, cmd_reg);
10649 DvcSleepMilliSecond(1);
10650 read_back = AscGetChipEEPCmd(iop_base);
10651 if (read_back == cmd_reg) {
10652 return (1);
10653 }
10654 if (retry++ > ASC_EEP_MAX_RETRY) {
10655 return (0);
10656 }
10657 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010658}
10659
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010660static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010661{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010662 ushort read_back;
10663 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010664
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010665 retry = 0;
10666 while (TRUE) {
10667 AscSetChipEEPData(iop_base, data_reg);
10668 DvcSleepMilliSecond(1);
10669 read_back = AscGetChipEEPData(iop_base);
10670 if (read_back == data_reg) {
10671 return (1);
10672 }
10673 if (retry++ > ASC_EEP_MAX_RETRY) {
10674 return (0);
10675 }
10676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010677}
10678
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010679static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010680{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010681 DvcSleepMilliSecond(1);
10682 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010683}
10684
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010685static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010686{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010687 DvcSleepMilliSecond(20);
10688 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010689}
10690
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010691static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010692{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010693 ushort read_wval;
10694 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010695
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010696 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
10697 AscWaitEEPRead();
10698 cmd_reg = addr | ASC_EEP_CMD_READ;
10699 AscWriteEEPCmdReg(iop_base, cmd_reg);
10700 AscWaitEEPRead();
10701 read_wval = AscGetChipEEPData(iop_base);
10702 AscWaitEEPRead();
10703 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010704}
10705
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010706static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010707AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010708{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010709 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010710
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010711 read_wval = AscReadEEPWord(iop_base, addr);
10712 if (read_wval != word_val) {
10713 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
10714 AscWaitEEPRead();
10715 AscWriteEEPDataReg(iop_base, word_val);
10716 AscWaitEEPRead();
10717 AscWriteEEPCmdReg(iop_base,
10718 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
10719 AscWaitEEPWrite();
10720 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
10721 AscWaitEEPRead();
10722 return (AscReadEEPWord(iop_base, addr));
10723 }
10724 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010725}
10726
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010727static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010728AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010729{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010730 ushort wval;
10731 ushort sum;
10732 ushort *wbuf;
10733 int cfg_beg;
10734 int cfg_end;
10735 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
10736 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010737
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010738 wbuf = (ushort *)cfg_buf;
10739 sum = 0;
10740 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
10741 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
10742 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
10743 sum += *wbuf;
10744 }
10745 if (bus_type & ASC_IS_VL) {
10746 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
10747 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
10748 } else {
10749 cfg_beg = ASC_EEP_DVC_CFG_BEG;
10750 cfg_end = ASC_EEP_MAX_DVC_ADDR;
10751 }
10752 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
10753 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
10754 if (s_addr <= uchar_end_in_config) {
10755 /*
10756 * Swap all char fields - must unswap bytes already swapped
10757 * by AscReadEEPWord().
10758 */
10759 *wbuf = le16_to_cpu(wval);
10760 } else {
10761 /* Don't swap word field at the end - cntl field. */
10762 *wbuf = wval;
10763 }
10764 sum += wval; /* Checksum treats all EEPROM data as words. */
10765 }
10766 /*
10767 * Read the checksum word which will be compared against 'sum'
10768 * by the caller. Word field already swapped.
10769 */
10770 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
10771 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010772}
10773
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010774static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010775AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010776{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010777 int n_error;
10778 ushort *wbuf;
10779 ushort word;
10780 ushort sum;
10781 int s_addr;
10782 int cfg_beg;
10783 int cfg_end;
10784 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010785
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010786 wbuf = (ushort *)cfg_buf;
10787 n_error = 0;
10788 sum = 0;
10789 /* Write two config words; AscWriteEEPWord() will swap bytes. */
10790 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
10791 sum += *wbuf;
10792 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
10793 n_error++;
10794 }
10795 }
10796 if (bus_type & ASC_IS_VL) {
10797 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
10798 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
10799 } else {
10800 cfg_beg = ASC_EEP_DVC_CFG_BEG;
10801 cfg_end = ASC_EEP_MAX_DVC_ADDR;
10802 }
10803 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
10804 if (s_addr <= uchar_end_in_config) {
10805 /*
10806 * This is a char field. Swap char fields before they are
10807 * swapped again by AscWriteEEPWord().
10808 */
10809 word = cpu_to_le16(*wbuf);
10810 if (word !=
10811 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
10812 n_error++;
10813 }
10814 } else {
10815 /* Don't swap word field at the end - cntl field. */
10816 if (*wbuf !=
10817 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
10818 n_error++;
10819 }
10820 }
10821 sum += *wbuf; /* Checksum calculated from word values. */
10822 }
10823 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
10824 *wbuf = sum;
10825 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
10826 n_error++;
10827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010828
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010829 /* Read EEPROM back again. */
10830 wbuf = (ushort *)cfg_buf;
10831 /*
10832 * Read two config words; Byte-swapping done by AscReadEEPWord().
10833 */
10834 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
10835 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
10836 n_error++;
10837 }
10838 }
10839 if (bus_type & ASC_IS_VL) {
10840 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
10841 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
10842 } else {
10843 cfg_beg = ASC_EEP_DVC_CFG_BEG;
10844 cfg_end = ASC_EEP_MAX_DVC_ADDR;
10845 }
10846 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
10847 if (s_addr <= uchar_end_in_config) {
10848 /*
10849 * Swap all char fields. Must unswap bytes already swapped
10850 * by AscReadEEPWord().
10851 */
10852 word =
10853 le16_to_cpu(AscReadEEPWord
10854 (iop_base, (uchar)s_addr));
10855 } else {
10856 /* Don't swap word field at the end - cntl field. */
10857 word = AscReadEEPWord(iop_base, (uchar)s_addr);
10858 }
10859 if (*wbuf != word) {
10860 n_error++;
10861 }
10862 }
10863 /* Read checksum; Byte swapping not needed. */
10864 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
10865 n_error++;
10866 }
10867 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010868}
10869
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010870static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010871AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010872{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010873 int retry;
10874 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010875
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010876 retry = 0;
10877 while (TRUE) {
10878 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
10879 bus_type)) == 0) {
10880 break;
10881 }
10882 if (++retry > ASC_EEP_MAX_RETRY) {
10883 break;
10884 }
10885 }
10886 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010887}
10888
Matthew Wilcox47d853c2007-07-26 11:41:33 -040010889static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010890{
Matthew Wilcox47d853c2007-07-26 11:41:33 -040010891 char type = sdev->type;
10892 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010893
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010894 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
10895 if (!(asc_dvc->init_sdtr & tid_bits)) {
Matthew Wilcox47d853c2007-07-26 11:41:33 -040010896 if ((type == TYPE_ROM) &&
10897 (strncmp(sdev->vendor, "HP ", 3) == 0)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010898 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
10899 }
10900 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
Matthew Wilcox47d853c2007-07-26 11:41:33 -040010901 if ((type == TYPE_PROCESSOR) ||
10902 (type == TYPE_SCANNER) || (type == TYPE_ROM) ||
10903 (type == TYPE_TAPE)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010904 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
10905 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010906
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010907 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
10908 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
Matthew Wilcox47d853c2007-07-26 11:41:33 -040010909 sdev->id,
10910 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010911 }
10912 }
10913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010914}
10915
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010916static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010917{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010918 uchar byte_data;
10919 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010920
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010921 if (isodd_word(addr)) {
10922 AscSetChipLramAddr(iop_base, addr - 1);
10923 word_data = AscGetChipLramData(iop_base);
10924 byte_data = (uchar)((word_data >> 8) & 0xFF);
10925 } else {
10926 AscSetChipLramAddr(iop_base, addr);
10927 word_data = AscGetChipLramData(iop_base);
10928 byte_data = (uchar)(word_data & 0xFF);
10929 }
10930 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010931}
Linus Torvalds1da177e2005-04-16 15:20:36 -070010932
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010933static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
10934{
10935 ushort word_data;
10936
10937 AscSetChipLramAddr(iop_base, addr);
10938 word_data = AscGetChipLramData(iop_base);
10939 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010940}
10941
10942#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010943static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010944{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010945 ushort val_low, val_high;
10946 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010947
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010948 AscSetChipLramAddr(iop_base, addr);
10949 val_low = AscGetChipLramData(iop_base);
10950 val_high = AscGetChipLramData(iop_base);
10951 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
10952 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010953}
10954#endif /* CC_VERY_LONG_SG_LIST */
10955
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010956static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010957{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010958 AscSetChipLramAddr(iop_base, addr);
10959 AscSetChipLramData(iop_base, word_val);
10960 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010961}
10962
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010963static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010964{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010965 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010966
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010967 if (isodd_word(addr)) {
10968 addr--;
10969 word_data = AscReadLramWord(iop_base, addr);
10970 word_data &= 0x00FF;
10971 word_data |= (((ushort)byte_val << 8) & 0xFF00);
10972 } else {
10973 word_data = AscReadLramWord(iop_base, addr);
10974 word_data &= 0xFF00;
10975 word_data |= ((ushort)byte_val & 0x00FF);
10976 }
10977 AscWriteLramWord(iop_base, addr, word_data);
10978 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010979}
10980
10981/*
10982 * Copy 2 bytes to LRAM.
10983 *
10984 * The source data is assumed to be in little-endian order in memory
10985 * and is maintained in little-endian order when written to LRAM.
10986 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010987static void
10988AscMemWordCopyPtrToLram(PortAddr iop_base,
10989 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010990{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010991 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010992
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010993 AscSetChipLramAddr(iop_base, s_addr);
10994 for (i = 0; i < 2 * words; i += 2) {
10995 /*
10996 * On a little-endian system the second argument below
10997 * produces a little-endian ushort which is written to
10998 * LRAM in little-endian order. On a big-endian system
10999 * the second argument produces a big-endian ushort which
11000 * is "transparently" byte-swapped by outpw() and written
11001 * in little-endian order to LRAM.
11002 */
11003 outpw(iop_base + IOP_RAM_DATA,
11004 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
11005 }
11006 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011007}
11008
11009/*
11010 * Copy 4 bytes to LRAM.
11011 *
11012 * The source data is assumed to be in little-endian order in memory
11013 * and is maintained in little-endian order when writen to LRAM.
11014 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011015static void
11016AscMemDWordCopyPtrToLram(PortAddr iop_base,
11017 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011018{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011019 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011020
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011021 AscSetChipLramAddr(iop_base, s_addr);
11022 for (i = 0; i < 4 * dwords; i += 4) {
11023 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
11024 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
11025 }
11026 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011027}
11028
11029/*
11030 * Copy 2 bytes from LRAM.
11031 *
11032 * The source data is assumed to be in little-endian order in LRAM
11033 * and is maintained in little-endian order when written to memory.
11034 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011035static void
11036AscMemWordCopyPtrFromLram(PortAddr iop_base,
11037 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011038{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011039 int i;
11040 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011041
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011042 AscSetChipLramAddr(iop_base, s_addr);
11043 for (i = 0; i < 2 * words; i += 2) {
11044 word = inpw(iop_base + IOP_RAM_DATA);
11045 d_buffer[i] = word & 0xff;
11046 d_buffer[i + 1] = (word >> 8) & 0xff;
11047 }
11048 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011049}
11050
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011051static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011052{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011053 ASC_DCNT sum;
11054 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011055
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011056 sum = 0L;
11057 for (i = 0; i < words; i++, s_addr += 2) {
11058 sum += AscReadLramWord(iop_base, s_addr);
11059 }
11060 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011061}
11062
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011063static void
11064AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011065{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011066 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011067
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011068 AscSetChipLramAddr(iop_base, s_addr);
11069 for (i = 0; i < words; i++) {
11070 AscSetChipLramData(iop_base, set_wval);
11071 }
11072 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011073}
11074
Linus Torvalds1da177e2005-04-16 15:20:36 -070011075/*
11076 * --- Adv Library Functions
11077 */
11078
11079/* a_mcode.h */
11080
11081/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011082static unsigned char _adv_asc3550_buf[] = {
11083 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
11084 0x01, 0x00, 0x48, 0xe4,
11085 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff,
11086 0x28, 0x0e, 0x9e, 0xe7,
11087 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7,
11088 0x55, 0xf0, 0x01, 0xf6,
11089 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
11090 0x00, 0xec, 0x85, 0xf0,
11091 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0,
11092 0x86, 0xf0, 0xb4, 0x00,
11093 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00,
11094 0xaa, 0x18, 0x02, 0x80,
11095 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
11096 0x00, 0x57, 0x01, 0xea,
11097 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80,
11098 0x03, 0xe6, 0xb6, 0x00,
11099 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12,
11100 0x02, 0x4a, 0xb9, 0x54,
11101 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
11102 0x3e, 0x00, 0x80, 0x00,
11103 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
11104 0x74, 0x01, 0x76, 0x01,
11105 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13,
11106 0x4c, 0x1c, 0xbb, 0x55,
11107 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
11108 0x03, 0xf7, 0x06, 0xf7,
11109 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08,
11110 0x30, 0x13, 0x64, 0x15,
11111 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c,
11112 0x04, 0xea, 0x5d, 0xf0,
11113 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
11114 0xcc, 0x00, 0x20, 0x01,
11115 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13,
11116 0x40, 0x13, 0x30, 0x1c,
11117 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
11118 0x59, 0xf0, 0xa7, 0xf0,
11119 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
11120 0xa4, 0x00, 0xb5, 0x00,
11121 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a,
11122 0x14, 0x0e, 0x02, 0x10,
11123 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13,
11124 0x10, 0x15, 0x14, 0x15,
11125 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
11126 0x91, 0x44, 0x0a, 0x45,
11127 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58,
11128 0x83, 0x59, 0x05, 0xe6,
11129 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8,
11130 0x02, 0xfa, 0x03, 0xfa,
11131 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
11132 0x9e, 0x00, 0xa8, 0x00,
11133 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01,
11134 0x7a, 0x01, 0xc0, 0x01,
11135 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08,
11136 0x69, 0x08, 0xba, 0x08,
11137 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
11138 0xf1, 0x10, 0x06, 0x12,
11139 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14,
11140 0x8a, 0x15, 0xc6, 0x17,
11141 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
11142 0x0e, 0x47, 0x48, 0x47,
11143 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
11144 0x14, 0x56, 0x77, 0x57,
11145 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c,
11146 0xf0, 0x29, 0x02, 0xfe,
11147 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf,
11148 0xfe, 0x80, 0x01, 0xff,
11149 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
11150 0x00, 0xfe, 0x57, 0x24,
11151 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09,
11152 0x00, 0x00, 0xff, 0x08,
11153 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
11154 0xff, 0xff, 0xff, 0x0f,
11155 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
11156 0xfe, 0x04, 0xf7, 0xcf,
11157 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67,
11158 0x0b, 0x3c, 0x2a, 0xfe,
11159 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0,
11160 0xfe, 0xf0, 0x01, 0xfe,
11161 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
11162 0x02, 0xfe, 0xd4, 0x0c,
11163 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
11164 0x1c, 0x05, 0xfe, 0xa6,
11165 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48,
11166 0xf0, 0xfe, 0x86, 0x02,
11167 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
11168 0xfe, 0x46, 0xf0, 0xfe,
11169 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
11170 0x44, 0x02, 0xfe, 0x44,
11171 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b,
11172 0xa0, 0x17, 0x06, 0x18,
11173 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
11174 0x1e, 0x1c, 0xfe, 0xe9,
11175 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7,
11176 0x0a, 0x6b, 0x01, 0x9e,
11177 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b,
11178 0x01, 0x82, 0xfe, 0xbd,
11179 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
11180 0x58, 0x1c, 0x17, 0x06,
11181 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21,
11182 0xfe, 0x94, 0x02, 0xfe,
11183 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97,
11184 0x01, 0xfe, 0x54, 0x0f,
11185 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
11186 0x69, 0x10, 0x17, 0x06,
11187 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05,
11188 0xf6, 0xc7, 0x01, 0xfe,
11189 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6,
11190 0x02, 0x29, 0x0a, 0x40,
11191 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
11192 0x58, 0x0a, 0x99, 0x01,
11193 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29,
11194 0x2a, 0x46, 0xfe, 0x02,
11195 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc,
11196 0x01, 0xfe, 0x07, 0x4b,
11197 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
11198 0xfe, 0x56, 0x03, 0xfe,
11199 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10,
11200 0xfe, 0x9f, 0xf0, 0xfe,
11201 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48,
11202 0x1c, 0xeb, 0x09, 0x04,
11203 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
11204 0x01, 0x0e, 0xac, 0x75,
11205 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2,
11206 0xfe, 0x82, 0xf0, 0xfe,
11207 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25,
11208 0x32, 0x1f, 0xfe, 0xb4,
11209 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
11210 0x0a, 0xf0, 0xfe, 0x7a,
11211 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c,
11212 0x01, 0x33, 0x8f, 0xfe,
11213 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8,
11214 0xf7, 0xfe, 0x48, 0x1c,
11215 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
11216 0x0a, 0xca, 0x01, 0x0e,
11217 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14,
11218 0x2c, 0x01, 0x33, 0x8f,
11219 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65,
11220 0xfe, 0x3c, 0x04, 0x1f,
11221 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
11222 0x12, 0x2b, 0xff, 0x02,
11223 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f,
11224 0x22, 0x30, 0x2e, 0xd5,
11225 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c,
11226 0xfe, 0x4c, 0x54, 0x64,
11227 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
11228 0xfe, 0x2a, 0x13, 0x2f,
11229 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
11230 0xd3, 0xfa, 0xef, 0x86,
11231 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04,
11232 0x1d, 0xfe, 0x1c, 0x12,
11233 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
11234 0x70, 0x0c, 0x02, 0x22,
11235 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92,
11236 0x01, 0x33, 0x02, 0x29,
11237 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87,
11238 0x80, 0xfe, 0x31, 0xe4,
11239 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
11240 0xfe, 0x70, 0x12, 0x49,
11241 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe,
11242 0x80, 0x05, 0xfe, 0x31,
11243 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00,
11244 0x28, 0xfe, 0x42, 0x12,
11245 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
11246 0x11, 0xfe, 0xe3, 0x00,
11247 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
11248 0x64, 0x05, 0x83, 0x24,
11249 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe,
11250 0x09, 0x48, 0x01, 0x08,
11251 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
11252 0x86, 0x24, 0x06, 0x12,
11253 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47,
11254 0x01, 0xa7, 0x14, 0x92,
11255 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c,
11256 0x02, 0x22, 0x05, 0xfe,
11257 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
11258 0x47, 0x01, 0xa7, 0x26,
11259 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f,
11260 0x01, 0xfe, 0xaa, 0x14,
11261 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00,
11262 0x05, 0x50, 0xb4, 0x0c,
11263 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
11264 0x13, 0x01, 0xfe, 0x14,
11265 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c,
11266 0xff, 0x02, 0x00, 0x57,
11267 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe,
11268 0x72, 0x06, 0x49, 0x04,
11269 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
11270 0x06, 0x11, 0x9a, 0x01,
11271 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06,
11272 0x01, 0xa7, 0xec, 0x72,
11273 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32,
11274 0xfe, 0x0a, 0xf0, 0xfe,
11275 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
11276 0x8d, 0x81, 0x02, 0x22,
11277 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00,
11278 0x01, 0x08, 0x15, 0x00,
11279 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15,
11280 0x00, 0x02, 0xfe, 0x32,
11281 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
11282 0xfe, 0x1b, 0x00, 0x01,
11283 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
11284 0x08, 0x15, 0x06, 0x01,
11285 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe,
11286 0x9a, 0x81, 0x4b, 0x1d,
11287 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
11288 0x45, 0xfe, 0x32, 0x12,
11289 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0,
11290 0xfe, 0x32, 0x07, 0x8d,
11291 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a,
11292 0x06, 0x15, 0x19, 0x02,
11293 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
11294 0x90, 0x77, 0xfe, 0xca,
11295 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07,
11296 0x10, 0xfe, 0x0e, 0x12,
11297 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe,
11298 0x83, 0xe7, 0xc4, 0xa1,
11299 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
11300 0x40, 0x12, 0x58, 0x01,
11301 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6,
11302 0x51, 0x83, 0xfb, 0xfe,
11303 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90,
11304 0xfe, 0x40, 0x50, 0xfe,
11305 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
11306 0xfe, 0x2a, 0x12, 0xfe,
11307 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f,
11308 0x85, 0x01, 0xa8, 0xfe,
11309 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56,
11310 0x18, 0x57, 0xfb, 0xfe,
11311 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
11312 0x0c, 0x39, 0x18, 0x3a,
11313 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e,
11314 0x11, 0x65, 0xfe, 0x48,
11315 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73,
11316 0xdd, 0xb8, 0xfe, 0x80,
11317 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
11318 0xfe, 0x7a, 0x08, 0x8d,
11319 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9,
11320 0x10, 0x61, 0x04, 0x06,
11321 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68,
11322 0x12, 0xfe, 0x2e, 0x1c,
11323 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
11324 0x52, 0x12, 0xfe, 0x2c,
11325 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe,
11326 0x08, 0xfe, 0x8a, 0x10,
11327 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe,
11328 0x24, 0x0a, 0xab, 0xfe,
11329 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
11330 0x1c, 0x12, 0xb5, 0xfe,
11331 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb,
11332 0x1c, 0x06, 0x16, 0x9d,
11333 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b,
11334 0x14, 0x92, 0x01, 0x33,
11335 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
11336 0xfe, 0x74, 0x18, 0x1c,
11337 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b,
11338 0x01, 0xe6, 0x1e, 0x27,
11339 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a,
11340 0x09, 0x04, 0x6a, 0xfe,
11341 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
11342 0xfe, 0x83, 0x80, 0xfe,
11343 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63,
11344 0x27, 0xfe, 0x40, 0x59,
11345 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18,
11346 0x7c, 0xbe, 0x54, 0xbf,
11347 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
11348 0x79, 0x56, 0x68, 0x57,
11349 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5,
11350 0xa2, 0x23, 0x0c, 0x7b,
11351 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19,
11352 0x16, 0xd7, 0x79, 0x39,
11353 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
11354 0xfe, 0x10, 0x58, 0xfe,
11355 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04,
11356 0x19, 0x16, 0xd7, 0x09,
11357 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f,
11358 0xfe, 0x10, 0x90, 0xfe,
11359 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
11360 0x11, 0x9b, 0x09, 0x04,
11361 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08,
11362 0xfe, 0x0c, 0x58, 0xfe,
11363 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04,
11364 0x0b, 0xfe, 0x1a, 0x12,
11365 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
11366 0x14, 0x7a, 0x01, 0x33,
11367 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39,
11368 0xfe, 0xed, 0x19, 0xbf,
11369 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff,
11370 0x34, 0xfe, 0x74, 0x10,
11371 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
11372 0x84, 0x05, 0xcb, 0x1c,
11373 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1,
11374 0xf0, 0xfe, 0xc4, 0x0a,
11375 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe,
11376 0xce, 0xf0, 0xfe, 0xca,
11377 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
11378 0x22, 0x00, 0x02, 0x5a,
11379 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a,
11380 0xfe, 0xd0, 0xf0, 0xfe,
11381 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f,
11382 0x4c, 0xfe, 0x10, 0x10,
11383 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
11384 0x2a, 0x13, 0xfe, 0x4e,
11385 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1,
11386 0x16, 0x32, 0x2a, 0x73,
11387 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25,
11388 0x32, 0x8c, 0xfe, 0x48,
11389 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
11390 0xdb, 0x10, 0x11, 0xfe,
11391 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0,
11392 0x22, 0x30, 0x2e, 0xd8,
11393 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1,
11394 0x45, 0x0f, 0xfe, 0x42,
11395 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
11396 0x09, 0x04, 0x0b, 0xfe,
11397 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28,
11398 0x00, 0x21, 0xfe, 0xa6,
11399 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00,
11400 0xfe, 0xe2, 0x10, 0x01,
11401 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
11402 0x01, 0x6f, 0x02, 0x29,
11403 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10,
11404 0x01, 0x86, 0x3e, 0x0b,
11405 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3,
11406 0x3e, 0x0b, 0x0f, 0xfe,
11407 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
11408 0xe8, 0x59, 0x11, 0x2d,
11409 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09,
11410 0x04, 0x0b, 0x84, 0x3e,
11411 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12,
11412 0x09, 0x04, 0x1b, 0xfe,
11413 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
11414 0x1c, 0x1c, 0xfe, 0x9d,
11415 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f,
11416 0xfe, 0x15, 0x00, 0xfe,
11417 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10,
11418 0x0f, 0xfe, 0x47, 0x00,
11419 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
11420 0xab, 0x70, 0x05, 0x6b,
11421 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe,
11422 0x1c, 0x42, 0x59, 0x01,
11423 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31,
11424 0x00, 0x37, 0x97, 0x01,
11425 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
11426 0x1d, 0xfe, 0xce, 0x45,
11427 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75,
11428 0x57, 0x05, 0x51, 0xfe,
11429 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48,
11430 0x46, 0x09, 0x04, 0x1d,
11431 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
11432 0x99, 0x01, 0x0e, 0xfe,
11433 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51,
11434 0xfe, 0xee, 0x14, 0xee,
11435 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad,
11436 0x13, 0x02, 0x29, 0x1e,
11437 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
11438 0xce, 0x1e, 0x2d, 0x47,
11439 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06,
11440 0x12, 0x4d, 0x01, 0xfe,
11441 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe,
11442 0xf0, 0x0d, 0xfe, 0x02,
11443 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
11444 0xf6, 0xfe, 0x34, 0x01,
11445 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13,
11446 0xaf, 0xfe, 0x02, 0xea,
11447 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c,
11448 0x05, 0xfe, 0x38, 0x01,
11449 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
11450 0x0c, 0xfe, 0x62, 0x01,
11451 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06,
11452 0x03, 0x23, 0x03, 0x1e,
11453 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe,
11454 0x71, 0x13, 0xfe, 0x24,
11455 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
11456 0xdc, 0xfe, 0x73, 0x57,
11457 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe,
11458 0x80, 0x5d, 0x03, 0xfe,
11459 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6,
11460 0x75, 0x03, 0x09, 0x04,
11461 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
11462 0xfe, 0x1e, 0x80, 0xe1,
11463 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e,
11464 0x90, 0xa3, 0xfe, 0x3c,
11465 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82,
11466 0x16, 0x2f, 0x07, 0x2d,
11467 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
11468 0xe8, 0x11, 0xfe, 0xe9,
11469 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe,
11470 0x1e, 0x1c, 0xfe, 0x14,
11471 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01,
11472 0x09, 0x04, 0x4f, 0xfe,
11473 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
11474 0x40, 0x12, 0x20, 0x63,
11475 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08,
11476 0x1c, 0x05, 0xfe, 0xac,
11477 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05,
11478 0xfe, 0xb0, 0x00, 0xfe,
11479 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
11480 0x24, 0x69, 0x12, 0xc9,
11481 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe,
11482 0x90, 0x4d, 0xfe, 0x91,
11483 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c,
11484 0xfe, 0x90, 0x4d, 0xfe,
11485 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
11486 0x46, 0x1e, 0x20, 0xed,
11487 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea,
11488 0x70, 0xfe, 0x14, 0x1c,
11489 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee,
11490 0xfe, 0x07, 0xe6, 0x1d,
11491 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
11492 0xfa, 0xef, 0xfe, 0x42,
11493 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0,
11494 0xfe, 0x36, 0x12, 0xf0,
11495 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
11496 0x3d, 0x75, 0x07, 0x10,
11497 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
11498 0x10, 0x07, 0x7e, 0x45,
11499 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74,
11500 0xfe, 0x01, 0xec, 0x97,
11501 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76,
11502 0x27, 0x01, 0xda, 0xfe,
11503 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
11504 0xfe, 0x48, 0x12, 0x07,
11505 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16,
11506 0xfe, 0x3e, 0x11, 0x07,
11507 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8,
11508 0x11, 0x07, 0x19, 0xfe,
11509 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
11510 0x01, 0x08, 0x8c, 0x43,
11511 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11,
11512 0x7e, 0x02, 0x29, 0x2b,
11513 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe,
11514 0xfc, 0x10, 0x09, 0x04,
11515 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
11516 0xc6, 0x10, 0x1e, 0x58,
11517 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c,
11518 0x54, 0x18, 0x55, 0x23,
11519 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01,
11520 0xa5, 0xc0, 0x38, 0xc1,
11521 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
11522 0x05, 0xfa, 0x4e, 0xfe,
11523 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56,
11524 0x0c, 0x56, 0x18, 0x57,
11525 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe,
11526 0x00, 0x56, 0xfe, 0xa1,
11527 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
11528 0x58, 0xfe, 0x1f, 0x40,
11529 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56,
11530 0x31, 0x57, 0xfe, 0x44,
11531 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe,
11532 0x8a, 0x50, 0x05, 0x39,
11533 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
11534 0x12, 0xcd, 0x02, 0x5b,
11535 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44,
11536 0x2f, 0x07, 0x9b, 0x21,
11537 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79,
11538 0x39, 0x68, 0x3a, 0xfe,
11539 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
11540 0x51, 0xfe, 0x8e, 0x51,
11541 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b,
11542 0x01, 0x08, 0x25, 0x32,
11543 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b,
11544 0x3b, 0x02, 0x44, 0x01,
11545 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
11546 0x01, 0x08, 0x1f, 0xa2,
11547 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c,
11548 0x00, 0x28, 0x84, 0x49,
11549 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06,
11550 0x78, 0x3d, 0xfe, 0xda,
11551 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
11552 0x05, 0xc6, 0x28, 0x84,
11553 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8,
11554 0x14, 0xfe, 0x03, 0x17,
11555 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01,
11556 0xfe, 0xaa, 0x14, 0x02,
11557 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
11558 0x21, 0x44, 0x01, 0xfe,
11559 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87,
11560 0xfe, 0x4a, 0xf4, 0x0b,
11561 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a,
11562 0x85, 0x02, 0x5b, 0x05,
11563 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
11564 0xd8, 0x14, 0x02, 0x5c,
11565 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1,
11566 0x01, 0x08, 0x23, 0x72,
11567 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca,
11568 0x12, 0x5e, 0x2b, 0x01,
11569 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
11570 0x1c, 0xfe, 0xff, 0x7f,
11571 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00,
11572 0x57, 0x48, 0x8b, 0x1c,
11573 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02,
11574 0x00, 0x57, 0x48, 0x8b,
11575 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
11576 0x03, 0x0a, 0x50, 0x01,
11577 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00,
11578 0x54, 0xfe, 0x00, 0xf4,
11579 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe,
11580 0x03, 0x7c, 0x63, 0x27,
11581 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
11582 0xfe, 0x82, 0x4a, 0xfe,
11583 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe,
11584 0x42, 0x48, 0x5f, 0x60,
11585 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08,
11586 0x1f, 0xfe, 0xa2, 0x14,
11587 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
11588 0xcc, 0x12, 0x49, 0x04,
11589 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe,
11590 0xe8, 0x13, 0x3b, 0x13,
11591 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55,
11592 0xa1, 0xff, 0x02, 0x83,
11593 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
11594 0x13, 0x06, 0xfe, 0x56,
11595 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe,
11596 0x64, 0x00, 0x17, 0x93,
11597 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe,
11598 0xc8, 0x00, 0x8e, 0xe4,
11599 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
11600 0x01, 0xba, 0xfe, 0x4e,
11601 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0,
11602 0xfe, 0x60, 0x14, 0xfe,
11603 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01,
11604 0xfe, 0x22, 0x13, 0x1c,
11605 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
11606 0xfe, 0x9c, 0x14, 0xb7,
11607 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba,
11608 0xfe, 0x9c, 0x14, 0xb7,
11609 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06,
11610 0xfe, 0xb4, 0x56, 0xfe,
11611 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
11612 0xe5, 0x15, 0x0b, 0x01,
11613 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89,
11614 0x49, 0x01, 0x08, 0x03,
11615 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6,
11616 0x15, 0x06, 0x01, 0x08,
11617 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
11618 0x4a, 0x01, 0x08, 0x03,
11619 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc,
11620 0xfe, 0x49, 0xf4, 0x00,
11621 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01,
11622 0x08, 0x2f, 0x07, 0xfe,
11623 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
11624 0x01, 0x43, 0x1e, 0xcd,
11625 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e,
11626 0xed, 0x88, 0x07, 0x10,
11627 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a,
11628 0x80, 0x01, 0x0e, 0x88,
11629 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
11630 0x88, 0x03, 0x0a, 0x42,
11631 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e,
11632 0xfe, 0x80, 0x80, 0xf2,
11633 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51,
11634 0x01, 0x82, 0x03, 0x17,
11635 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
11636 0xfe, 0x24, 0x1c, 0xfe,
11637 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0,
11638 0x91, 0x1d, 0x66, 0xfe,
11639 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe,
11640 0xda, 0x10, 0x17, 0x10,
11641 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
11642 0x05, 0xfe, 0x66, 0x01,
11643 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06,
11644 0xfe, 0x3c, 0x50, 0x66,
11645 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe,
11646 0x40, 0x16, 0xfe, 0xb6,
11647 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
11648 0x10, 0x71, 0xfe, 0x83,
11649 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90,
11650 0xfe, 0x62, 0x16, 0xfe,
11651 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19,
11652 0xfe, 0x98, 0xe7, 0x00,
11653 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
11654 0xfe, 0x30, 0xbc, 0xfe,
11655 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
11656 0xc5, 0x90, 0xfe, 0x9a,
11657 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe,
11658 0x42, 0x10, 0xfe, 0x02,
11659 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
11660 0xfe, 0x1d, 0xf7, 0x4f,
11661 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f,
11662 0x47, 0xfe, 0x83, 0x58,
11663 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11,
11664 0xfe, 0xdd, 0x00, 0x63,
11665 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
11666 0x06, 0x37, 0x95, 0xa9,
11667 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e,
11668 0x18, 0x1c, 0x1a, 0x5d,
11669 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe,
11670 0xe1, 0x10, 0x78, 0x2c,
11671 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
11672 0x13, 0x3c, 0x8a, 0x0a,
11673 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
11674 0xe3, 0xfe, 0x00, 0xcc,
11675 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01,
11676 0x0e, 0xf2, 0x01, 0x6f,
11677 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
11678 0xf6, 0xfe, 0xd6, 0xf0,
11679 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe,
11680 0x15, 0x00, 0x59, 0x76,
11681 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35,
11682 0x11, 0x2d, 0x01, 0x6f,
11683 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
11684 0xc8, 0xfe, 0x48, 0x55,
11685 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a,
11686 0x99, 0x01, 0x0e, 0xf0,
11687 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73,
11688 0x75, 0x03, 0x0a, 0x42,
11689 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
11690 0x0e, 0x73, 0x75, 0x03,
11691 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00,
11692 0xfe, 0x3a, 0x45, 0x5b,
11693 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00,
11694 0xfe, 0x02, 0xe6, 0x1b,
11695 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
11696 0xfe, 0x94, 0x00, 0xfe,
11697 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02,
11698 0xe6, 0x2c, 0xfe, 0x4e,
11699 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69,
11700 0x03, 0x07, 0x7a, 0xfe,
11701 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
11702 0x07, 0x1b, 0xfe, 0x5a,
11703 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d,
11704 0x24, 0x2c, 0xdc, 0x07,
11705 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d,
11706 0x9f, 0xad, 0x03, 0x14,
11707 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
11708 0x03, 0x25, 0xfe, 0xca,
11709 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a,
11710 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070011711};
11712
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011713static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
11714static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011715
11716/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011717static unsigned char _adv_asc38C0800_buf[] = {
11718 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
11719 0x01, 0x00, 0x48, 0xe4,
11720 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff,
11721 0x1c, 0x0f, 0x00, 0xf6,
11722 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6,
11723 0x09, 0xe7, 0x55, 0xf0,
11724 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
11725 0x18, 0xf4, 0x08, 0x00,
11726 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6,
11727 0x86, 0xf0, 0xb1, 0xf0,
11728 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c,
11729 0x3c, 0x00, 0xbb, 0x00,
11730 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
11731 0xba, 0x13, 0x18, 0x40,
11732 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01,
11733 0x6e, 0x01, 0x74, 0x01,
11734 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00,
11735 0xc0, 0x00, 0x01, 0x01,
11736 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
11737 0x08, 0x12, 0x02, 0x4a,
11738 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4,
11739 0x5d, 0xf0, 0x02, 0xfa,
11740 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01,
11741 0x68, 0x01, 0x6a, 0x01,
11742 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
11743 0x06, 0x13, 0x4c, 0x1c,
11744 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00,
11745 0x0f, 0x00, 0x47, 0x00,
11746 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c,
11747 0x4e, 0x1c, 0x10, 0x44,
11748 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
11749 0x05, 0x00, 0x34, 0x00,
11750 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b,
11751 0x42, 0x0c, 0x12, 0x0f,
11752 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48,
11753 0x00, 0x4e, 0x42, 0x54,
11754 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
11755 0x59, 0xf0, 0xb8, 0xf0,
11756 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00,
11757 0x19, 0x00, 0x33, 0x00,
11758 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00,
11759 0xe7, 0x00, 0xe2, 0x03,
11760 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
11761 0x12, 0x13, 0x24, 0x14,
11762 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c,
11763 0x36, 0x1c, 0x08, 0x44,
11764 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54,
11765 0x3a, 0x55, 0x83, 0x55,
11766 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
11767 0x0c, 0xf0, 0x04, 0xf8,
11768 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00,
11769 0xa8, 0x00, 0xaa, 0x00,
11770 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01,
11771 0xc4, 0x01, 0xc6, 0x01,
11772 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
11773 0x68, 0x08, 0x69, 0x08,
11774 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10,
11775 0xed, 0x10, 0xf1, 0x10,
11776 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13,
11777 0x1e, 0x13, 0x46, 0x14,
11778 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
11779 0xca, 0x18, 0xe6, 0x19,
11780 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c,
11781 0xf0, 0x2b, 0x02, 0xfe,
11782 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6,
11783 0xfe, 0x84, 0x01, 0xff,
11784 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
11785 0x00, 0xfe, 0x57, 0x24,
11786 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09,
11787 0x00, 0x00, 0xff, 0x08,
11788 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
11789 0xff, 0xff, 0xff, 0x11,
11790 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
11791 0xfe, 0x04, 0xf7, 0xd6,
11792 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99,
11793 0x0a, 0x42, 0x2c, 0xfe,
11794 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0,
11795 0xfe, 0xf4, 0x01, 0xfe,
11796 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
11797 0x02, 0xfe, 0xc8, 0x0d,
11798 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
11799 0x1c, 0x03, 0xfe, 0xa6,
11800 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48,
11801 0xf0, 0xfe, 0x8a, 0x02,
11802 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
11803 0xfe, 0x46, 0xf0, 0xfe,
11804 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
11805 0x48, 0x02, 0xfe, 0x44,
11806 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a,
11807 0xaa, 0x18, 0x06, 0x14,
11808 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
11809 0x1e, 0x1c, 0xfe, 0xe9,
11810 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce,
11811 0x09, 0x70, 0x01, 0xa8,
11812 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70,
11813 0x01, 0x87, 0xfe, 0xbd,
11814 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
11815 0x58, 0x1c, 0x18, 0x06,
11816 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23,
11817 0xfe, 0x98, 0x02, 0xfe,
11818 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2,
11819 0x01, 0xfe, 0x48, 0x10,
11820 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
11821 0x69, 0x10, 0x18, 0x06,
11822 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05,
11823 0xf6, 0xce, 0x01, 0xfe,
11824 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe,
11825 0x82, 0x16, 0x02, 0x2b,
11826 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
11827 0xfe, 0x41, 0x58, 0x09,
11828 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe,
11829 0x82, 0x16, 0x02, 0x2b,
11830 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43,
11831 0xfe, 0x77, 0x57, 0xfe,
11832 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
11833 0xfe, 0x40, 0x1c, 0x1c,
11834 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48,
11835 0x03, 0xfe, 0x11, 0xf0,
11836 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10,
11837 0xfe, 0x11, 0x00, 0x02,
11838 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
11839 0x21, 0x22, 0xa3, 0xb7,
11840 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16,
11841 0x12, 0xd1, 0x1c, 0xd9,
11842 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12,
11843 0xfe, 0xe4, 0x00, 0x27,
11844 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
11845 0x06, 0xf0, 0xfe, 0xc8,
11846 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03,
11847 0x70, 0x28, 0x17, 0xfe,
11848 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8,
11849 0xf9, 0x2c, 0x99, 0x19,
11850 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
11851 0x74, 0x01, 0xaf, 0x8c,
11852 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e,
11853 0x8d, 0x51, 0x64, 0x79,
11854 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b,
11855 0xfe, 0x6a, 0x02, 0x02,
11856 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
11857 0xfe, 0x3c, 0x04, 0x3b,
11858 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02,
11859 0x00, 0x10, 0x01, 0x0b,
11860 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde,
11861 0xfe, 0x4c, 0x44, 0xfe,
11862 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
11863 0xda, 0x4f, 0x79, 0x2a,
11864 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b,
11865 0xfe, 0x2a, 0x13, 0x32,
11866 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c,
11867 0x54, 0x6b, 0xda, 0xfe,
11868 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
11869 0x08, 0x13, 0x32, 0x07,
11870 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d,
11871 0x08, 0x05, 0x06, 0x4d,
11872 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24,
11873 0x2d, 0x12, 0xfe, 0xe6,
11874 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
11875 0x02, 0x2b, 0xfe, 0x42,
11876 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
11877 0xfe, 0x87, 0x80, 0xfe,
11878 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80,
11879 0x07, 0x19, 0xfe, 0x7c,
11880 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
11881 0x17, 0xfe, 0x90, 0x05,
11882 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe,
11883 0xa0, 0x00, 0x28, 0xfe,
11884 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c,
11885 0x34, 0xfe, 0x89, 0x48,
11886 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
11887 0x12, 0xfe, 0xe3, 0x00,
11888 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
11889 0x70, 0x05, 0x88, 0x25,
11890 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe,
11891 0x09, 0x48, 0xff, 0x02,
11892 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
11893 0x08, 0x53, 0x05, 0xcb,
11894 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08,
11895 0x05, 0x1b, 0xfe, 0x22,
11896 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe,
11897 0x0d, 0x00, 0x01, 0x36,
11898 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
11899 0x03, 0x5c, 0x28, 0xfe,
11900 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53,
11901 0x05, 0x1f, 0xfe, 0x02,
11902 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5,
11903 0x01, 0x4b, 0x12, 0xfe,
11904 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
11905 0x12, 0x03, 0x45, 0x28,
11906 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe,
11907 0x43, 0x48, 0xc4, 0xcc,
11908 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4,
11909 0x6e, 0x41, 0x01, 0xb2,
11910 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
11911 0xfe, 0xcc, 0x15, 0x1d,
11912 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03,
11913 0x45, 0xc1, 0x0c, 0x45,
11914 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe,
11915 0xe2, 0x00, 0x27, 0xdb,
11916 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
11917 0xfe, 0x06, 0xf0, 0xfe,
11918 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12,
11919 0x16, 0x19, 0x01, 0x0b,
11920 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
11921 0xfe, 0x99, 0xa4, 0x01,
11922 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
11923 0x12, 0x08, 0x05, 0x1a,
11924 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
11925 0x0b, 0x16, 0x00, 0x01,
11926 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02,
11927 0xe2, 0x6c, 0x58, 0xbe,
11928 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
11929 0xfe, 0x09, 0x6f, 0xba,
11930 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27,
11931 0xfe, 0x54, 0x07, 0x1c,
11932 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c,
11933 0x07, 0x02, 0x24, 0x01,
11934 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
11935 0x2c, 0x90, 0xfe, 0xae,
11936 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a,
11937 0x37, 0x22, 0x20, 0x07,
11938 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a,
11939 0xfe, 0x06, 0x10, 0xfe,
11940 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
11941 0x37, 0x01, 0xb3, 0xb8,
11942 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a,
11943 0x50, 0xfe, 0x44, 0x51,
11944 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e,
11945 0x14, 0x5f, 0xfe, 0x0c,
11946 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
11947 0x14, 0x3e, 0xfe, 0x4a,
11948 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
11949 0x90, 0x0c, 0x60, 0x14,
11950 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62,
11951 0xfe, 0x44, 0x90, 0xfe,
11952 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
11953 0x0c, 0x5e, 0x14, 0x5f,
11954 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e,
11955 0x14, 0x3c, 0x21, 0x0c,
11956 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11,
11957 0x27, 0xdd, 0xfe, 0x9e,
11958 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
11959 0x9a, 0x08, 0xc6, 0xfe,
11960 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08,
11961 0x95, 0x86, 0x02, 0x24,
11962 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05,
11963 0x06, 0xfe, 0x10, 0x12,
11964 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
11965 0x1c, 0x02, 0xfe, 0x18,
11966 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe,
11967 0x2c, 0x1c, 0xfe, 0xaa,
11968 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe,
11969 0xde, 0x09, 0xfe, 0xb7,
11970 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
11971 0xfe, 0xf1, 0x18, 0xfe,
11972 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe,
11973 0x14, 0x59, 0xfe, 0x95,
11974 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0,
11975 0xfe, 0xf0, 0x08, 0xb5,
11976 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
11977 0x0b, 0xb6, 0xfe, 0xbf,
11978 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c,
11979 0x12, 0xc2, 0xfe, 0xd2,
11980 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e,
11981 0x06, 0x17, 0x85, 0xc5,
11982 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
11983 0x9d, 0x01, 0x36, 0x10,
11984 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe,
11985 0x98, 0x80, 0xfe, 0x19,
11986 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18,
11987 0xfe, 0x44, 0x54, 0xbe,
11988 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
11989 0x02, 0x4a, 0x08, 0x05,
11990 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e,
11991 0x9c, 0x3c, 0xfe, 0x6c,
11992 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f,
11993 0x3b, 0x40, 0x03, 0x49,
11994 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
11995 0x8f, 0xfe, 0xe3, 0x54,
11996 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe,
11997 0xda, 0x09, 0xfe, 0x8b,
11998 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa,
11999 0x0a, 0x3a, 0x49, 0x3b,
12000 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
12001 0xad, 0xfe, 0x01, 0x59,
12002 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a,
12003 0x49, 0x8f, 0xfe, 0xe3,
12004 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02,
12005 0x4a, 0x3a, 0x49, 0x3b,
12006 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
12007 0x02, 0x4a, 0x08, 0x05,
12008 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62,
12009 0xb7, 0xfe, 0x03, 0xa1,
12010 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
12011 0xfe, 0x86, 0x91, 0x6a,
12012 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
12013 0x61, 0x0c, 0x7f, 0x14,
12014 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62,
12015 0x9b, 0x2e, 0x9c, 0x3c,
12016 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05,
12017 0xfa, 0x3c, 0x01, 0xef,
12018 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
12019 0xe4, 0x08, 0x05, 0x1f,
12020 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37,
12021 0x03, 0x5e, 0x29, 0x5f,
12022 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe,
12023 0xf4, 0x09, 0x08, 0x05,
12024 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
12025 0x81, 0x50, 0xfe, 0x10,
12026 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe,
12027 0x08, 0x09, 0x12, 0xa6,
12028 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe,
12029 0x08, 0x09, 0xfe, 0x0c,
12030 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
12031 0x08, 0x05, 0x0a, 0xfe,
12032 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1,
12033 0xf0, 0xe2, 0x15, 0x7e,
12034 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19,
12035 0x57, 0x3d, 0xfe, 0xed,
12036 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
12037 0x00, 0xff, 0x35, 0xfe,
12038 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18,
12039 0x1e, 0x19, 0x8a, 0x03,
12040 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65,
12041 0xfe, 0xd1, 0xf0, 0xfe,
12042 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
12043 0x10, 0xfe, 0xce, 0xf0,
12044 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b,
12045 0x10, 0xfe, 0x22, 0x00,
12046 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00,
12047 0x02, 0x65, 0xfe, 0xd0,
12048 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
12049 0x0b, 0x10, 0x58, 0xfe,
12050 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe,
12051 0x12, 0x00, 0x2c, 0x0f,
12052 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14,
12053 0x0c, 0xbc, 0x17, 0x34,
12054 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
12055 0x0c, 0x1c, 0x34, 0x94,
12056 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01,
12057 0x4b, 0xfe, 0xdb, 0x10,
12058 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe,
12059 0x89, 0xf0, 0x24, 0x33,
12060 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
12061 0x33, 0x31, 0xdf, 0xbc,
12062 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49,
12063 0x17, 0xfe, 0x2c, 0x0d,
12064 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54,
12065 0x12, 0x55, 0xfe, 0x28,
12066 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
12067 0x44, 0xfe, 0x28, 0x00,
12068 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26,
12069 0x0f, 0x64, 0x12, 0x2f,
12070 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44,
12071 0x0a, 0xfe, 0xb4, 0x10,
12072 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
12073 0xfe, 0x34, 0x46, 0xac,
12074 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a,
12075 0x37, 0x01, 0xf5, 0x01,
12076 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02,
12077 0xfe, 0x2e, 0x03, 0x08,
12078 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
12079 0x1a, 0xfe, 0x58, 0x12,
12080 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
12081 0xfe, 0x50, 0x0d, 0xfe,
12082 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37,
12083 0xfe, 0xa9, 0x10, 0x10,
12084 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
12085 0xfe, 0x13, 0x00, 0xfe,
12086 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe,
12087 0x24, 0x00, 0x8c, 0xb5,
12088 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a,
12089 0xfe, 0x9d, 0x41, 0xfe,
12090 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
12091 0xb4, 0x15, 0xfe, 0x31,
12092 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06,
12093 0xec, 0xd0, 0xfc, 0x44,
12094 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47,
12095 0x4b, 0x91, 0xfe, 0x75,
12096 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
12097 0x0e, 0xfe, 0x44, 0x48,
12098 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41,
12099 0xfe, 0x41, 0x58, 0x09,
12100 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe,
12101 0x2e, 0x03, 0x09, 0x5d,
12102 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
12103 0xce, 0x47, 0xfe, 0xad,
12104 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13,
12105 0x59, 0x13, 0x9f, 0x13,
12106 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe,
12107 0xe0, 0x0e, 0x0f, 0x06,
12108 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
12109 0x3a, 0x01, 0x56, 0xfe,
12110 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec,
12111 0x20, 0x4f, 0xfe, 0x05,
12112 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe,
12113 0x48, 0xf4, 0x0d, 0xfe,
12114 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
12115 0x15, 0x1a, 0x39, 0xa0,
12116 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff,
12117 0x0c, 0xfe, 0x60, 0x01,
12118 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25,
12119 0x06, 0x13, 0x2f, 0x12,
12120 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
12121 0x22, 0x9f, 0xb7, 0x13,
12122 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39,
12123 0xa0, 0xb4, 0xfe, 0xd9,
12124 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04,
12125 0xc3, 0xfe, 0x03, 0xdc,
12126 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
12127 0xfe, 0x00, 0xcc, 0x04,
12128 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13,
12129 0xfe, 0x1c, 0x80, 0x07,
12130 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae,
12131 0xfe, 0x0c, 0x90, 0xfe,
12132 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
12133 0x0a, 0xfe, 0x3c, 0x50,
12134 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4,
12135 0x16, 0x08, 0x05, 0x1b,
12136 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58,
12137 0xfe, 0x2c, 0x13, 0x01,
12138 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
12139 0x0c, 0xfe, 0x64, 0x01,
12140 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03,
12141 0x80, 0x8d, 0xfe, 0x01,
12142 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64,
12143 0x22, 0x20, 0xfb, 0x79,
12144 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
12145 0x03, 0xfe, 0xae, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012146
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012147 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe,
12148 0xb2, 0x00, 0xfe, 0x09,
12149 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c,
12150 0x45, 0x0f, 0x46, 0x52,
12151 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
12152 0x0f, 0x44, 0x11, 0x0f,
12153 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4,
12154 0x25, 0x11, 0x13, 0x20,
12155 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14,
12156 0x56, 0xfe, 0xd6, 0xf0,
12157 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
12158 0x18, 0x1c, 0x04, 0x42,
12159 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe,
12160 0xf5, 0x13, 0x04, 0x01,
12161 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
12162 0x13, 0x32, 0x07, 0x2f,
12163 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
12164 0x41, 0x48, 0xfe, 0x45,
12165 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78,
12166 0x07, 0x11, 0xac, 0x09,
12167 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07,
12168 0x82, 0x4e, 0xfe, 0x14,
12169 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
12170 0xfe, 0x01, 0xec, 0xa2,
12171 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79,
12172 0x2a, 0x01, 0xe3, 0xfe,
12173 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a,
12174 0xfe, 0x48, 0x12, 0x07,
12175 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
12176 0xfe, 0x32, 0x12, 0x07,
12177 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07,
12178 0x1f, 0xfe, 0x12, 0x12,
12179 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b,
12180 0x94, 0x4b, 0x04, 0x2d,
12181 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
12182 0x32, 0x07, 0xa6, 0xfe,
12183 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05,
12184 0x5a, 0xfe, 0x72, 0x12,
12185 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62,
12186 0xfe, 0x26, 0x13, 0x03,
12187 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
12188 0x0c, 0x7f, 0x0c, 0x80,
12189 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c,
12190 0x3c, 0xfe, 0x04, 0x55,
12191 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe,
12192 0x91, 0x10, 0x03, 0x3f,
12193 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
12194 0x88, 0x9b, 0x2e, 0x9c,
12195 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
12196 0x56, 0x0c, 0x5e, 0x14,
12197 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40,
12198 0x03, 0x60, 0x29, 0x61,
12199 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
12200 0x50, 0xfe, 0xc6, 0x50,
12201 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d,
12202 0x29, 0x3e, 0xfe, 0x40,
12203 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72,
12204 0x2d, 0x01, 0x0b, 0x1d,
12205 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
12206 0x72, 0x01, 0xaf, 0x1e,
12207 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe,
12208 0x0a, 0x55, 0x35, 0xfe,
12209 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51,
12210 0x02, 0x72, 0xfe, 0x19,
12211 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
12212 0x1d, 0xe8, 0x33, 0x31,
12213 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01,
12214 0x0b, 0x1c, 0x34, 0x1d,
12215 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8,
12216 0x33, 0x31, 0xfe, 0xe8,
12217 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
12218 0x05, 0x1f, 0x35, 0xa9,
12219 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda,
12220 0x14, 0x01, 0xaf, 0x8c,
12221 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a,
12222 0x03, 0x45, 0x28, 0x35,
12223 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
12224 0x03, 0x5c, 0xc1, 0x0c,
12225 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02,
12226 0x89, 0x01, 0x0b, 0x1c,
12227 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1,
12228 0xfe, 0x42, 0x58, 0xf1,
12229 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
12230 0xf4, 0x06, 0xea, 0x32,
12231 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d,
12232 0x01, 0x0b, 0x26, 0x89,
12233 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13,
12234 0x26, 0xfe, 0xd4, 0x13,
12235 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
12236 0x13, 0x1c, 0xfe, 0xd0,
12237 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10,
12238 0x0f, 0x71, 0xff, 0x02,
12239 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe,
12240 0x00, 0x5c, 0x04, 0x0f,
12241 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
12242 0xfe, 0x00, 0x5c, 0x04,
12243 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff,
12244 0x02, 0x00, 0x57, 0x52,
12245 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01,
12246 0x87, 0x04, 0xfe, 0x03,
12247 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
12248 0xfe, 0x00, 0x7d, 0xfe,
12249 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e,
12250 0x14, 0x5f, 0x57, 0x3f,
12251 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83,
12252 0x5a, 0x8d, 0x04, 0x01,
12253 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
12254 0xfe, 0x96, 0x15, 0x33,
12255 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8,
12256 0x0a, 0xfe, 0xc1, 0x59,
12257 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13,
12258 0x21, 0x69, 0x1a, 0xee,
12259 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
12260 0x30, 0xfe, 0x78, 0x10,
12261 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae,
12262 0x98, 0xfe, 0x30, 0x00,
12263 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed,
12264 0x98, 0xfe, 0x64, 0x00,
12265 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
12266 0x10, 0x69, 0x06, 0xfe,
12267 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00,
12268 0x18, 0x59, 0x0f, 0x06,
12269 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe,
12270 0x43, 0xf4, 0x9f, 0xfe,
12271 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
12272 0x9e, 0xfe, 0xf3, 0x10,
12273 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00,
12274 0x17, 0xfe, 0x4d, 0xe4,
12275 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00,
12276 0x17, 0xfe, 0x4d, 0xe4,
12277 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
12278 0xf4, 0x00, 0xe9, 0x91,
12279 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a,
12280 0x04, 0x16, 0x06, 0x01,
12281 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01,
12282 0x0b, 0x26, 0xf3, 0x76,
12283 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
12284 0x16, 0x19, 0x01, 0x0b,
12285 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01,
12286 0x0b, 0x26, 0xb1, 0x76,
12287 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06,
12288 0xfe, 0x48, 0x13, 0xb8,
12289 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
12290 0xec, 0xfe, 0x27, 0x01,
12291 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32,
12292 0x07, 0xfe, 0xe3, 0x00,
12293 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b,
12294 0x22, 0xd4, 0x07, 0x06,
12295 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
12296 0x07, 0x11, 0xae, 0x09,
12297 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01,
12298 0x0e, 0x8e, 0xfe, 0x80,
12299 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04,
12300 0x09, 0x48, 0x01, 0x0e,
12301 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
12302 0x80, 0xfe, 0x80, 0x4c,
12303 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c,
12304 0x09, 0x5d, 0x01, 0x87,
12305 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe,
12306 0x19, 0xde, 0xfe, 0x24,
12307 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
12308 0x17, 0xad, 0x9a, 0x1b,
12309 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde,
12310 0x16, 0xfe, 0xda, 0x10,
12311 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe,
12312 0x18, 0x58, 0x03, 0xfe,
12313 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
12314 0xf4, 0x06, 0xfe, 0x3c,
12315 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f,
12316 0x97, 0xfe, 0x38, 0x17,
12317 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c,
12318 0x10, 0x18, 0x11, 0x75,
12319 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
12320 0x2e, 0x97, 0xfe, 0x5a,
12321 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19,
12322 0xfe, 0x98, 0xe7, 0x00,
12323 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75,
12324 0xfe, 0x30, 0xbc, 0xfe,
12325 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
12326 0xcb, 0x97, 0xfe, 0x92,
12327 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe,
12328 0x42, 0x10, 0xfe, 0x02,
12329 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe,
12330 0x03, 0xa1, 0xfe, 0x1d,
12331 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
12332 0x9a, 0x5b, 0x41, 0xfe,
12333 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7,
12334 0x11, 0x12, 0xfe, 0xdd,
12335 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8,
12336 0x17, 0x15, 0x06, 0x39,
12337 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
12338 0xfe, 0x7e, 0x18, 0x1e,
12339 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef,
12340 0x12, 0xfe, 0xe1, 0x10,
12341 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42,
12342 0x13, 0x42, 0x92, 0x09,
12343 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
12344 0xf0, 0xfe, 0x00, 0xcc,
12345 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01,
12346 0x0e, 0xfe, 0x80, 0x4c,
12347 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe,
12348 0x24, 0x12, 0xfe, 0x14,
12349 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
12350 0xe7, 0x0a, 0x10, 0xfe,
12351 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92,
12352 0x08, 0x54, 0x1b, 0x37,
12353 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba,
12354 0x90, 0x3a, 0xce, 0x3b,
12355 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
12356 0x13, 0xa3, 0x04, 0x09,
12357 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49,
12358 0x44, 0x17, 0xfe, 0xe8,
12359 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09,
12360 0x5d, 0x01, 0xa8, 0x09,
12361 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
12362 0x1c, 0x19, 0x03, 0xfe,
12363 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9,
12364 0x6b, 0xfe, 0x2e, 0x19,
12365 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4,
12366 0xfe, 0x0b, 0x00, 0x6b,
12367 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
12368 0x08, 0x10, 0x03, 0xfe,
12369 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff,
12370 0x04, 0x68, 0x54, 0xe7,
12371 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe,
12372 0x1a, 0xf4, 0xfe, 0x00,
12373 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
12374 0x04, 0x07, 0x7e, 0xfe,
12375 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
12376 0x07, 0x1a, 0xfe, 0x5a,
12377 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66,
12378 0x25, 0x6d, 0xe5, 0x07,
12379 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
12380 0xa9, 0xb8, 0x04, 0x15,
12381 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe,
12382 0x40, 0x5c, 0x04, 0x1c,
12383 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b,
12384 0xf7, 0xfe, 0x82, 0xf0,
12385 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012386};
12387
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012388static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
12389static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012390
12391/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012392static unsigned char _adv_asc38C1600_buf[] = {
12393 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
12394 0x18, 0xe4, 0x01, 0x00,
12395 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00,
12396 0x07, 0x17, 0xc0, 0x5f,
12397 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7,
12398 0x85, 0xf0, 0x86, 0xf0,
12399 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
12400 0x98, 0x57, 0x01, 0xe6,
12401 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d,
12402 0x38, 0x54, 0x32, 0xf0,
12403 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4,
12404 0x00, 0xe6, 0xb1, 0xf0,
12405 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
12406 0x06, 0x13, 0x0c, 0x1c,
12407 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12,
12408 0xb9, 0x54, 0x00, 0x80,
12409 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56,
12410 0x03, 0xe6, 0x01, 0xea,
12411 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
12412 0x04, 0x13, 0xbb, 0x55,
12413 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00,
12414 0xbb, 0x00, 0xc0, 0x00,
12415 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12,
12416 0x4c, 0x1c, 0x4e, 0x1c,
12417 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
12418 0x24, 0x01, 0x3c, 0x01,
12419 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01,
12420 0x78, 0x01, 0x7c, 0x01,
12421 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c,
12422 0x6e, 0x1e, 0x02, 0x48,
12423 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
12424 0x03, 0xfc, 0x06, 0x00,
12425 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a,
12426 0x30, 0x1c, 0x38, 0x1c,
12427 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea,
12428 0x5d, 0xf0, 0xa7, 0xf0,
12429 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
12430 0x33, 0x00, 0x34, 0x00,
12431 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01,
12432 0x79, 0x01, 0x3c, 0x09,
12433 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13,
12434 0x40, 0x16, 0x50, 0x16,
12435 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
12436 0x05, 0xf0, 0x09, 0xf0,
12437 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00,
12438 0x9c, 0x00, 0xa4, 0x00,
12439 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08,
12440 0xe9, 0x09, 0x5c, 0x0c,
12441 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
12442 0x42, 0x1d, 0x08, 0x44,
12443 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54,
12444 0x83, 0x55, 0x83, 0x59,
12445 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0,
12446 0x4b, 0xf4, 0x04, 0xf8,
12447 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
12448 0xa8, 0x00, 0xaa, 0x00,
12449 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01,
12450 0x7a, 0x01, 0x82, 0x01,
12451 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07,
12452 0x68, 0x08, 0x10, 0x0d,
12453 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
12454 0xf3, 0x10, 0x06, 0x12,
12455 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c,
12456 0xf0, 0x35, 0x05, 0xfe,
12457 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8,
12458 0xfe, 0x88, 0x01, 0xff,
12459 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
12460 0x00, 0xfe, 0x57, 0x24,
12461 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09,
12462 0x00, 0x00, 0xff, 0x08,
12463 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
12464 0xff, 0xff, 0xff, 0x13,
12465 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
12466 0xfe, 0x04, 0xf7, 0xe8,
12467 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d,
12468 0x0d, 0x51, 0x37, 0xfe,
12469 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0,
12470 0xfe, 0xf8, 0x01, 0xfe,
12471 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
12472 0x05, 0xfe, 0x08, 0x0f,
12473 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe,
12474 0x28, 0x1c, 0x03, 0xfe,
12475 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe,
12476 0x48, 0xf0, 0xfe, 0x90,
12477 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
12478 0x02, 0xfe, 0x46, 0xf0,
12479 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0,
12480 0xfe, 0x4e, 0x02, 0xfe,
12481 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c,
12482 0x0d, 0xa2, 0x1c, 0x07,
12483 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
12484 0x1c, 0xf5, 0xfe, 0x1e,
12485 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc,
12486 0xde, 0x0a, 0x81, 0x01,
12487 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a,
12488 0x81, 0x01, 0x5c, 0xfe,
12489 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
12490 0xfe, 0x58, 0x1c, 0x1c,
12491 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02,
12492 0x2b, 0xfe, 0x9e, 0x02,
12493 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30,
12494 0x00, 0x47, 0xb8, 0x01,
12495 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
12496 0x1a, 0x31, 0xfe, 0x69,
12497 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe,
12498 0x1e, 0x1e, 0x20, 0x2c,
12499 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a,
12500 0x44, 0x15, 0x56, 0x51,
12501 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
12502 0x01, 0x18, 0x09, 0x00,
12503 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01,
12504 0x18, 0xfe, 0xc8, 0x54,
12505 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60,
12506 0xfe, 0x02, 0xe8, 0x30,
12507 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
12508 0xfe, 0xe4, 0x01, 0xfe,
12509 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe,
12510 0x26, 0xf0, 0xfe, 0x66,
12511 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe,
12512 0xef, 0x10, 0xfe, 0x9f,
12513 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
12514 0x70, 0x37, 0xfe, 0x48,
12515 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26,
12516 0x21, 0xb9, 0xc7, 0x20,
12517 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15,
12518 0xe1, 0x2a, 0xeb, 0xfe,
12519 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
12520 0x15, 0xfe, 0xe4, 0x00,
12521 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41,
12522 0xfe, 0x06, 0xf0, 0xfe,
12523 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29,
12524 0x03, 0x81, 0x1e, 0x1b,
12525 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
12526 0xea, 0xfe, 0x46, 0x1c,
12527 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
12528 0xfe, 0x48, 0x1c, 0x75,
12529 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a,
12530 0xe1, 0x01, 0x18, 0x77,
12531 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
12532 0x8f, 0xfe, 0x70, 0x02,
12533 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04,
12534 0x16, 0xfe, 0x4a, 0x04,
12535 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff,
12536 0x02, 0x00, 0x10, 0x01,
12537 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
12538 0xee, 0xfe, 0x4c, 0x44,
12539 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54,
12540 0x7b, 0xec, 0x60, 0x8d,
12541 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01,
12542 0x0c, 0x06, 0x28, 0xfe,
12543 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
12544 0x13, 0x34, 0xfe, 0x4c,
12545 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54,
12546 0x13, 0x01, 0x0c, 0x06,
12547 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06,
12548 0x28, 0xf9, 0x1f, 0x7f,
12549 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
12550 0xfe, 0xa4, 0x0e, 0x05,
12551 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe,
12552 0x9c, 0x93, 0x3a, 0x0b,
12553 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b,
12554 0x7d, 0x1d, 0xfe, 0x46,
12555 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
12556 0xfe, 0x87, 0x83, 0xfe,
12557 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98,
12558 0x13, 0x0f, 0xfe, 0x20,
12559 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84,
12560 0x12, 0x01, 0x38, 0x06,
12561 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
12562 0x05, 0xd0, 0x54, 0x01,
12563 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe,
12564 0x50, 0x12, 0x5e, 0xff,
12565 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02,
12566 0x00, 0x10, 0x2f, 0xfe,
12567 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
12568 0x38, 0xfe, 0x4a, 0xf0,
12569 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe,
12570 0x21, 0x00, 0xf1, 0x2e,
12571 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00,
12572 0x10, 0x2f, 0xfe, 0xd0,
12573 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
12574 0x1c, 0x00, 0x4d, 0x01,
12575 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06,
12576 0x28, 0xfe, 0x24, 0x12,
12577 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe,
12578 0x0d, 0x00, 0x01, 0x42,
12579 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
12580 0x03, 0xb6, 0x1e, 0xfe,
12581 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17,
12582 0xfe, 0x72, 0x06, 0x0a,
12583 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56,
12584 0x19, 0x16, 0xfe, 0x68,
12585 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
12586 0x03, 0x9a, 0x1e, 0xfe,
12587 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12,
12588 0x48, 0xfe, 0x92, 0x06,
12589 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13,
12590 0x58, 0xff, 0x02, 0x00,
12591 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
12592 0xfe, 0xea, 0x06, 0x01,
12593 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16,
12594 0xfe, 0xe0, 0x06, 0x15,
12595 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07,
12596 0x01, 0x84, 0xfe, 0xae,
12597 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
12598 0x1e, 0xfe, 0x1a, 0x12,
12599 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
12600 0x43, 0x48, 0x62, 0x80,
12601 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24,
12602 0x36, 0xfe, 0x02, 0xf6,
12603 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
12604 0xd0, 0x0d, 0x17, 0xfe,
12605 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20,
12606 0x9e, 0x15, 0x82, 0x01,
12607 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58,
12608 0x57, 0x10, 0xe6, 0x05,
12609 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
12610 0xfe, 0x9c, 0x32, 0x5f,
12611 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c,
12612 0xfe, 0x0a, 0xf0, 0xfe,
12613 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08,
12614 0xaf, 0xa0, 0x05, 0x29,
12615 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
12616 0x00, 0x01, 0x08, 0x14,
12617 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08,
12618 0x14, 0x00, 0x05, 0xfe,
12619 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06,
12620 0x12, 0xfe, 0x30, 0x13,
12621 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
12622 0x01, 0x08, 0x14, 0x00,
12623 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a,
12624 0x78, 0x4f, 0x0f, 0xfe,
12625 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d,
12626 0x28, 0x48, 0xfe, 0x6c,
12627 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
12628 0x12, 0x53, 0x63, 0x4e,
12629 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe,
12630 0x6c, 0x08, 0xaf, 0xa0,
12631 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24,
12632 0x05, 0xed, 0xfe, 0x9c,
12633 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
12634 0x1e, 0xfe, 0x99, 0x58,
12635 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a,
12636 0x22, 0x6b, 0x01, 0x0c,
12637 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e,
12638 0x1e, 0x47, 0x2c, 0x7a,
12639 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
12640 0x01, 0x0c, 0x61, 0x65,
12641 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a,
12642 0x16, 0xfe, 0x08, 0x50,
12643 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10,
12644 0x01, 0xfe, 0xce, 0x1e,
12645 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
12646 0x01, 0xfe, 0xfe, 0x1e,
12647 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a,
12648 0x10, 0x01, 0x0c, 0x06,
12649 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e,
12650 0x10, 0x6a, 0x22, 0x6b,
12651 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
12652 0xfe, 0x9f, 0x83, 0x33,
12653 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93,
12654 0x3a, 0x0b, 0xfe, 0xc6,
12655 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d,
12656 0x01, 0xfe, 0xce, 0x1e,
12657 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
12658 0x04, 0xfe, 0xc0, 0x93,
12659 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e,
12660 0x10, 0x4b, 0x22, 0x4c,
12661 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe,
12662 0x4e, 0x11, 0x2f, 0xfe,
12663 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
12664 0x3c, 0x37, 0x88, 0xf5,
12665 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a,
12666 0xd3, 0xfe, 0x42, 0x0a,
12667 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0,
12668 0x05, 0x29, 0x01, 0x41,
12669 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
12670 0xfe, 0x14, 0x12, 0x01,
12671 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe,
12672 0x2e, 0x1c, 0x05, 0xfe,
12673 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41,
12674 0xfe, 0x2c, 0x1c, 0xfe,
12675 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
12676 0x92, 0x10, 0xc4, 0xf6,
12677 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe,
12678 0xe7, 0x10, 0xfe, 0x2b,
12679 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12,
12680 0xac, 0xfe, 0xd2, 0xf0,
12681 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
12682 0x1b, 0xbf, 0xd4, 0x5b,
12683 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75,
12684 0x5e, 0x32, 0x1f, 0x7f,
12685 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98,
12686 0x05, 0x70, 0xfe, 0x74,
12687 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
12688 0x0f, 0x4d, 0x01, 0xfe,
12689 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06,
12690 0x0d, 0x2b, 0xfe, 0xe2,
12691 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24,
12692 0xfe, 0x88, 0x13, 0x21,
12693 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
12694 0x83, 0x83, 0xfe, 0xc9,
12695 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04,
12696 0x91, 0x04, 0xfe, 0x84,
12697 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93,
12698 0xfe, 0xcb, 0x57, 0x0b,
12699 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
12700 0x6a, 0x3b, 0x6b, 0x10,
12701 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30,
12702 0x20, 0x6e, 0xdb, 0x64,
12703 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55,
12704 0xfe, 0x04, 0xfa, 0x64,
12705 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
12706 0x10, 0x98, 0x91, 0x6c,
12707 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91,
12708 0x4b, 0x7e, 0x4c, 0x01,
12709 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10,
12710 0x58, 0xfe, 0x91, 0x58,
12711 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
12712 0x1b, 0x40, 0x01, 0x0c,
12713 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f,
12714 0xfe, 0x10, 0x90, 0x04,
12715 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93,
12716 0x79, 0x0b, 0x0e, 0xfe,
12717 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
12718 0x01, 0x0c, 0x06, 0x0d,
12719 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe,
12720 0x0c, 0x58, 0xfe, 0x8d,
12721 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99,
12722 0x83, 0x33, 0x0b, 0x0e,
12723 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
12724 0x19, 0xfe, 0x19, 0x41,
12725 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42,
12726 0x19, 0xfe, 0x44, 0x00,
12727 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda,
12728 0x4c, 0xfe, 0x0c, 0x51,
12729 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
12730 0x76, 0x10, 0xac, 0xfe,
12731 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03,
12732 0xe3, 0x23, 0x07, 0xfe,
12733 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe,
12734 0xcc, 0x0c, 0x1f, 0x92,
12735 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
12736 0x0c, 0xfe, 0x3e, 0x10,
12737 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70,
12738 0xfe, 0xcb, 0xf0, 0xfe,
12739 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe,
12740 0xf4, 0x0c, 0x19, 0x94,
12741 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
12742 0xfe, 0xcc, 0xf0, 0xef,
12743 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe,
12744 0x4e, 0x11, 0x2f, 0xfe,
12745 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b,
12746 0x3c, 0x37, 0x88, 0xf5,
12747 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
12748 0x2f, 0xfe, 0x3e, 0x0d,
12749 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f,
12750 0xd2, 0x9f, 0xd3, 0x9f,
12751 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4,
12752 0xc5, 0x75, 0xd7, 0x99,
12753 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
12754 0x9c, 0x2f, 0xfe, 0x8c,
12755 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe,
12756 0x42, 0x00, 0x05, 0x70,
12757 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06,
12758 0x0d, 0xfe, 0x44, 0x13,
12759 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
12760 0xfe, 0xda, 0x0e, 0x0a,
12761 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa,
12762 0x10, 0x01, 0xfe, 0xf4,
12763 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40,
12764 0x15, 0x56, 0x01, 0x85,
12765 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
12766 0xcc, 0x10, 0x01, 0xa7,
12767 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04,
12768 0xfe, 0x99, 0x83, 0xfe,
12769 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe,
12770 0x43, 0x00, 0xfe, 0xa2,
12771 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
12772 0x00, 0x1d, 0x40, 0x15,
12773 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05,
12774 0xfe, 0x3a, 0x03, 0x01,
12775 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01,
12776 0x76, 0x06, 0x12, 0xfe,
12777 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
12778 0xfe, 0x9d, 0xf0, 0xfe,
12779 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01,
12780 0x0c, 0x61, 0x12, 0x44,
12781 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f,
12782 0xfe, 0x2e, 0x10, 0x19,
12783 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
12784 0xfe, 0x41, 0x00, 0xa2,
12785 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b,
12786 0xea, 0x4f, 0xfe, 0x04,
12787 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05,
12788 0x35, 0xfe, 0x12, 0x1c,
12789 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
12790 0xfe, 0xd4, 0x11, 0x05,
12791 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe,
12792 0xce, 0x45, 0x31, 0x51,
12793 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03,
12794 0x67, 0xfe, 0x98, 0x56,
12795 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
12796 0x0c, 0x06, 0x28, 0xfe,
12797 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba,
12798 0xfe, 0xfa, 0x14, 0xfe,
12799 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67,
12800 0xfe, 0xe0, 0x14, 0xfe,
12801 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
12802 0xfe, 0xad, 0x13, 0x05,
12803 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20,
12804 0xe7, 0xfe, 0x08, 0x1c,
12805 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe,
12806 0x48, 0x55, 0xa5, 0x3b,
12807 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
12808 0xf0, 0x1a, 0x03, 0xfe,
12809 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02,
12810 0xec, 0xe7, 0x53, 0x00,
12811 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
12812 0x01, 0xfe, 0x62, 0x1b,
12813 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
12814 0xea, 0xe7, 0x53, 0x92,
12815 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03,
12816 0xfe, 0x38, 0x01, 0x23,
12817 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62,
12818 0x01, 0x01, 0xfe, 0x1e,
12819 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
12820 0x26, 0x02, 0x21, 0x96,
12821 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5,
12822 0xc3, 0xfe, 0xe1, 0x10,
12823 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf,
12824 0xfe, 0x03, 0xdc, 0xfe,
12825 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
12826 0x00, 0xcc, 0x02, 0xfe,
12827 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13,
12828 0x0f, 0xfe, 0x1c, 0x80,
12829 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13,
12830 0x0f, 0xfe, 0x1e, 0x80,
12831 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
12832 0x1d, 0x80, 0x04, 0xfe,
12833 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee,
12834 0x1e, 0xac, 0xfe, 0x14,
12835 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e,
12836 0x1f, 0xfe, 0x30, 0xf4,
12837 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
12838 0x56, 0xfb, 0x01, 0xfe,
12839 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01,
12840 0xfe, 0x00, 0x1d, 0x15,
12841 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe,
12842 0x22, 0x1b, 0xfe, 0x1e,
12843 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
12844 0x96, 0x90, 0x04, 0xfe,
12845 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66,
12846 0x01, 0x01, 0x0c, 0x06,
12847 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b,
12848 0x0e, 0x77, 0xfe, 0x01,
12849 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
12850 0x21, 0x2c, 0xfe, 0x00,
12851 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe,
12852 0x06, 0x58, 0x03, 0xfe,
12853 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58,
12854 0x03, 0xfe, 0xb2, 0x00,
12855 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
12856 0x66, 0x10, 0x55, 0x10,
12857 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91,
12858 0x54, 0x2b, 0xfe, 0x88,
12859 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe,
12860 0x91, 0x54, 0x2b, 0xfe,
12861 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
12862 0x00, 0x40, 0x8d, 0x2c,
12863 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe,
12864 0x12, 0x1c, 0x75, 0xfe,
12865 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c,
12866 0x14, 0xfe, 0x0e, 0x47,
12867 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
12868 0xa7, 0x90, 0x34, 0x60,
12869 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80,
12870 0x09, 0x56, 0xfe, 0x34,
12871 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48,
12872 0xfe, 0x45, 0x48, 0x01,
12873 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
12874 0x09, 0x1a, 0xa5, 0x0a,
12875 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4,
12876 0xfe, 0x14, 0x56, 0xfe,
12877 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01,
12878 0xec, 0xb8, 0xfe, 0x9e,
12879 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
12880 0xf4, 0xfe, 0xdd, 0x10,
12881 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48,
12882 0x12, 0x09, 0x0d, 0xfe,
12883 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4,
12884 0x13, 0x09, 0xfe, 0x23,
12885 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
12886 0x24, 0xfe, 0x12, 0x12,
12887 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08,
12888 0xae, 0x41, 0x02, 0x32,
12889 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05,
12890 0x35, 0x32, 0x01, 0x43,
12891 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
12892 0x13, 0x01, 0x0c, 0x06,
12893 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe,
12894 0xe5, 0x55, 0xb0, 0xfe,
12895 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e,
12896 0xfe, 0xb6, 0x0e, 0x10,
12897 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
12898 0x88, 0x20, 0x6e, 0x01,
12899 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5,
12900 0x55, 0xfe, 0x04, 0xfa,
12901 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d,
12902 0xfe, 0x40, 0x56, 0xfe,
12903 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
12904 0x44, 0x55, 0xfe, 0xe5,
12905 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10,
12906 0x68, 0x22, 0x69, 0x01,
12907 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b,
12908 0x6b, 0xfe, 0x2c, 0x50,
12909 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
12910 0x50, 0x03, 0x68, 0x3b,
12911 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe,
12912 0x40, 0x50, 0xfe, 0xc2,
12913 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08,
12914 0x16, 0x3d, 0x27, 0x25,
12915 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
12916 0xa6, 0x23, 0x3f, 0x1b,
12917 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c,
12918 0xfe, 0x0a, 0x55, 0x31,
12919 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e,
12920 0x51, 0x05, 0x72, 0x01,
12921 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
12922 0x2a, 0x3c, 0x16, 0xc0,
12923 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b,
12924 0xfe, 0x66, 0x15, 0x05,
12925 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d,
12926 0x2b, 0x3d, 0x01, 0x08,
12927 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
12928 0xb6, 0x1e, 0x83, 0x01,
12929 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46,
12930 0x07, 0x90, 0x3f, 0x01,
12931 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13,
12932 0x01, 0x43, 0x09, 0x82,
12933 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
12934 0x05, 0x72, 0xfe, 0xc0,
12935 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e,
12936 0x32, 0x01, 0x08, 0x17,
12937 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16,
12938 0x3d, 0x27, 0x25, 0xbd,
12939 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
12940 0xe8, 0x14, 0x01, 0xa6,
12941 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe,
12942 0x0e, 0x12, 0x01, 0x43,
12943 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32,
12944 0x01, 0x08, 0x17, 0x73,
12945 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
12946 0x27, 0x25, 0xbd, 0x09,
12947 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe,
12948 0xb6, 0x14, 0x86, 0xa8,
12949 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09,
12950 0x82, 0x4e, 0x05, 0x72,
12951 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
12952 0xfe, 0xc0, 0x19, 0x05,
12953 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f,
12954 0xcc, 0x01, 0x08, 0x26,
12955 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe,
12956 0xcc, 0x15, 0x5e, 0x32,
12957 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
12958 0xad, 0x23, 0xfe, 0xff,
12959 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02,
12960 0x00, 0x57, 0x52, 0xad,
12961 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff,
12962 0x02, 0x00, 0x57, 0x52,
12963 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
12964 0x02, 0x13, 0x58, 0xff,
12965 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01,
12966 0x5c, 0x0a, 0x55, 0x01,
12967 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a,
12968 0xff, 0x03, 0x00, 0x54,
12969 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
12970 0x7c, 0x3a, 0x0b, 0x0e,
12971 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19,
12972 0xfe, 0x1a, 0xf7, 0x00,
12973 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c,
12974 0xda, 0x6d, 0x02, 0xfe,
12975 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
12976 0x02, 0x01, 0xc6, 0xfe,
12977 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27,
12978 0x25, 0xbe, 0x01, 0x08,
12979 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59,
12980 0x03, 0x9a, 0x1e, 0xfe,
12981 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
12982 0x48, 0xfe, 0x08, 0x17,
12983 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26,
12984 0x17, 0x4d, 0x13, 0x07,
12985 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1,
12986 0xff, 0x02, 0x83, 0x55,
12987 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
12988 0x17, 0x1c, 0x63, 0x13,
12989 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64,
12990 0x00, 0xb0, 0xfe, 0x80,
12991 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10,
12992 0x53, 0x07, 0xfe, 0x60,
12993 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
12994 0x00, 0x1c, 0x95, 0x13,
12995 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3,
12996 0xfe, 0x43, 0xf4, 0x96,
12997 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43,
12998 0xf4, 0x94, 0xf6, 0x8b,
12999 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
13000 0xda, 0x17, 0x62, 0x49,
13001 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80,
13002 0x71, 0x50, 0x26, 0xfe,
13003 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3,
13004 0x58, 0x02, 0x50, 0x13,
13005 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
13006 0x25, 0xbe, 0xfe, 0x03,
13007 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9,
13008 0x0a, 0x01, 0x08, 0x16,
13009 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01,
13010 0x01, 0x08, 0x16, 0xa9,
13011 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
13012 0x08, 0x16, 0xa9, 0x27,
13013 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83,
13014 0x01, 0x38, 0x06, 0x24,
13015 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1,
13016 0x78, 0x03, 0x9a, 0x1e,
13017 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
13018 0xfe, 0x40, 0x5a, 0x23,
13019 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c,
13020 0x80, 0x48, 0xfe, 0xaa,
13021 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01,
13022 0xfe, 0xac, 0x1d, 0xfe,
13023 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
13024 0x43, 0x48, 0x2d, 0x93,
13025 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4,
13026 0x36, 0xfe, 0x34, 0xf4,
13027 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe,
13028 0x28, 0x10, 0xfe, 0xc0,
13029 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
13030 0x18, 0x45, 0xfe, 0x1c,
13031 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c,
13032 0x19, 0xfe, 0x04, 0xf4,
13033 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d,
13034 0x21, 0xfe, 0x7f, 0x01,
13035 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
13036 0x7e, 0x01, 0xfe, 0xc8,
13037 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa,
13038 0x21, 0xfe, 0x81, 0x01,
13039 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50,
13040 0x13, 0x0d, 0x02, 0x14,
13041 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
13042 0xfe, 0x82, 0x19, 0x14,
13043 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01,
13044 0x08, 0x02, 0x14, 0x07,
13045 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07,
13046 0x01, 0x08, 0x17, 0xc1,
13047 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
13048 0x08, 0x02, 0x50, 0x02,
13049 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74,
13050 0x14, 0x12, 0x01, 0x08,
13051 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01,
13052 0x08, 0x17, 0x74, 0xfe,
13053 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
13054 0x74, 0x5f, 0xcc, 0x01,
13055 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4,
13056 0xfe, 0x49, 0xf4, 0x00,
13057 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff,
13058 0x02, 0x00, 0x10, 0x2f,
13059 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
13060 0x16, 0xfe, 0x64, 0x1a,
13061 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c,
13062 0x61, 0x07, 0x44, 0x02,
13063 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12,
13064 0x13, 0x0a, 0x9d, 0x01,
13065 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
13066 0xfe, 0x80, 0xe7, 0x1a,
13067 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02,
13068 0x0a, 0x5a, 0x01, 0x18,
13069 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe,
13070 0x7e, 0x1e, 0xfe, 0x80,
13071 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
13072 0xfe, 0x80, 0x4c, 0x0a,
13073 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf,
13074 0xfe, 0x19, 0xde, 0xfe,
13075 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe,
13076 0x2a, 0x1c, 0xfa, 0xb3,
13077 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
13078 0xf4, 0x1a, 0xfe, 0xfa,
13079 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24,
13080 0xfe, 0x18, 0x58, 0x03,
13081 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f,
13082 0xfe, 0x30, 0xf4, 0x07,
13083 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
13084 0xf7, 0x24, 0xb1, 0xfe,
13085 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b,
13086 0xfe, 0xba, 0x10, 0x1c,
13087 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
13088 0x1d, 0xf7, 0x54, 0xb1,
13089 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
13090 0xaf, 0x19, 0xfe, 0x98,
13091 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c,
13092 0x1a, 0x87, 0x8b, 0x0f,
13093 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58,
13094 0xfe, 0x32, 0x90, 0x04,
13095 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
13096 0x7c, 0x12, 0xfe, 0x0f,
13097 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14,
13098 0x31, 0x02, 0xc9, 0x2b,
13099 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe,
13100 0x6a, 0xfe, 0x19, 0xfe,
13101 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
13102 0x1b, 0xfe, 0x36, 0x14,
13103 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19,
13104 0xfe, 0x80, 0xe7, 0x1a,
13105 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a,
13106 0x30, 0xfe, 0x12, 0x45,
13107 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
13108 0x39, 0xf0, 0x75, 0x26,
13109 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03,
13110 0xe3, 0x23, 0x07, 0xfe,
13111 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09,
13112 0x56, 0xfe, 0x3c, 0x13,
13113 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
13114 0x01, 0x18, 0xcb, 0xfe,
13115 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16,
13116 0xfe, 0x00, 0xcc, 0xcb,
13117 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18,
13118 0xfe, 0x80, 0x4c, 0x01,
13119 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
13120 0x12, 0xfe, 0x14, 0x56,
13121 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7,
13122 0x0d, 0x19, 0xfe, 0x15,
13123 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06,
13124 0x83, 0xfe, 0x18, 0x80,
13125 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
13126 0x90, 0xfe, 0xba, 0x90,
13127 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02,
13128 0x21, 0xb9, 0x88, 0x20,
13129 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01,
13130 0x18, 0xfe, 0x49, 0x44,
13131 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
13132 0x1a, 0xa4, 0x0a, 0x67,
13133 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4,
13134 0x1d, 0x7b, 0xfe, 0x52,
13135 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe,
13136 0x4e, 0xe4, 0xdd, 0x7b,
13137 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
13138 0xfe, 0x4e, 0xe4, 0xfe,
13139 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24,
13140 0xfe, 0x08, 0x10, 0x03,
13141 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04,
13142 0x68, 0x54, 0xfe, 0xf1,
13143 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
13144 0xfe, 0x1a, 0xf4, 0xfe,
13145 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02,
13146 0x09, 0x92, 0xfe, 0x5a,
13147 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe,
13148 0x5a, 0xf0, 0xfe, 0xc8,
13149 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
13150 0x1a, 0x10, 0x09, 0x0d,
13151 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02,
13152 0x1f, 0x93, 0x01, 0x42,
13153 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e,
13154 0xfe, 0x14, 0xf0, 0x08,
13155 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
13156 0xfe, 0x82, 0xf0, 0xfe,
13157 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e,
13158 0x02, 0x0f, 0xfe, 0x18,
13159 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02,
13160 0x80, 0x04, 0xfe, 0x82,
13161 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
13162 0x83, 0x33, 0x0b, 0x0e,
13163 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e,
13164 0x02, 0x0f, 0xfe, 0x04,
13165 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80,
13166 0x80, 0x04, 0xfe, 0x80,
13167 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
13168 0xfe, 0x99, 0x83, 0xfe,
13169 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86,
13170 0x83, 0xfe, 0xce, 0x47,
13171 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a,
13172 0x0b, 0x0e, 0x02, 0x0f,
13173 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
13174 0xfe, 0x08, 0x90, 0x04,
13175 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04,
13176 0xfe, 0x8a, 0x93, 0x79,
13177 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a,
13178 0x0b, 0x0e, 0x02, 0x0f,
13179 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
13180 0xfe, 0x3c, 0x90, 0x04,
13181 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80,
13182 0x04, 0xfe, 0x83, 0x83,
13183 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070013184};
13185
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013186static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
13187static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013188
13189/* a_init.c */
13190/*
13191 * EEPROM Configuration.
13192 *
13193 * All drivers should use this structure to set the default EEPROM
13194 * configuration. The BIOS now uses this structure when it is built.
13195 * Additional structure information can be found in a_condor.h where
13196 * the structure is defined.
13197 *
13198 * The *_Field_IsChar structs are needed to correct for endianness.
13199 * These values are read from the board 16 bits at a time directly
13200 * into the structs. Because some fields are char, the values will be
13201 * in the wrong order. The *_Field_IsChar tells when to flip the
13202 * bytes. Data read and written to PCI memory is automatically swapped
13203 * on big-endian platforms so char fields read as words are actually being
13204 * unswapped on big-endian platforms.
13205 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013206static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013207 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
13208 0x0000, /* cfg_msw */
13209 0xFFFF, /* disc_enable */
13210 0xFFFF, /* wdtr_able */
13211 0xFFFF, /* sdtr_able */
13212 0xFFFF, /* start_motor */
13213 0xFFFF, /* tagqng_able */
13214 0xFFFF, /* bios_scan */
13215 0, /* scam_tolerant */
13216 7, /* adapter_scsi_id */
13217 0, /* bios_boot_delay */
13218 3, /* scsi_reset_delay */
13219 0, /* bios_id_lun */
13220 0, /* termination */
13221 0, /* reserved1 */
13222 0xFFE7, /* bios_ctrl */
13223 0xFFFF, /* ultra_able */
13224 0, /* reserved2 */
13225 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
13226 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13227 0, /* dvc_cntl */
13228 0, /* bug_fix */
13229 0, /* serial_number_word1 */
13230 0, /* serial_number_word2 */
13231 0, /* serial_number_word3 */
13232 0, /* check_sum */
13233 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13234 , /* oem_name[16] */
13235 0, /* dvc_err_code */
13236 0, /* adv_err_code */
13237 0, /* adv_err_addr */
13238 0, /* saved_dvc_err_code */
13239 0, /* saved_adv_err_code */
13240 0, /* saved_adv_err_addr */
13241 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013242};
13243
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013244static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013245 0, /* cfg_lsw */
13246 0, /* cfg_msw */
13247 0, /* -disc_enable */
13248 0, /* wdtr_able */
13249 0, /* sdtr_able */
13250 0, /* start_motor */
13251 0, /* tagqng_able */
13252 0, /* bios_scan */
13253 0, /* scam_tolerant */
13254 1, /* adapter_scsi_id */
13255 1, /* bios_boot_delay */
13256 1, /* scsi_reset_delay */
13257 1, /* bios_id_lun */
13258 1, /* termination */
13259 1, /* reserved1 */
13260 0, /* bios_ctrl */
13261 0, /* ultra_able */
13262 0, /* reserved2 */
13263 1, /* max_host_qng */
13264 1, /* max_dvc_qng */
13265 0, /* dvc_cntl */
13266 0, /* bug_fix */
13267 0, /* serial_number_word1 */
13268 0, /* serial_number_word2 */
13269 0, /* serial_number_word3 */
13270 0, /* check_sum */
13271 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13272 , /* oem_name[16] */
13273 0, /* dvc_err_code */
13274 0, /* adv_err_code */
13275 0, /* adv_err_addr */
13276 0, /* saved_dvc_err_code */
13277 0, /* saved_adv_err_code */
13278 0, /* saved_adv_err_addr */
13279 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013280};
13281
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013282static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013283 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
13284 0x0000, /* 01 cfg_msw */
13285 0xFFFF, /* 02 disc_enable */
13286 0xFFFF, /* 03 wdtr_able */
13287 0x4444, /* 04 sdtr_speed1 */
13288 0xFFFF, /* 05 start_motor */
13289 0xFFFF, /* 06 tagqng_able */
13290 0xFFFF, /* 07 bios_scan */
13291 0, /* 08 scam_tolerant */
13292 7, /* 09 adapter_scsi_id */
13293 0, /* bios_boot_delay */
13294 3, /* 10 scsi_reset_delay */
13295 0, /* bios_id_lun */
13296 0, /* 11 termination_se */
13297 0, /* termination_lvd */
13298 0xFFE7, /* 12 bios_ctrl */
13299 0x4444, /* 13 sdtr_speed2 */
13300 0x4444, /* 14 sdtr_speed3 */
13301 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
13302 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13303 0, /* 16 dvc_cntl */
13304 0x4444, /* 17 sdtr_speed4 */
13305 0, /* 18 serial_number_word1 */
13306 0, /* 19 serial_number_word2 */
13307 0, /* 20 serial_number_word3 */
13308 0, /* 21 check_sum */
13309 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13310 , /* 22-29 oem_name[16] */
13311 0, /* 30 dvc_err_code */
13312 0, /* 31 adv_err_code */
13313 0, /* 32 adv_err_addr */
13314 0, /* 33 saved_dvc_err_code */
13315 0, /* 34 saved_adv_err_code */
13316 0, /* 35 saved_adv_err_addr */
13317 0, /* 36 reserved */
13318 0, /* 37 reserved */
13319 0, /* 38 reserved */
13320 0, /* 39 reserved */
13321 0, /* 40 reserved */
13322 0, /* 41 reserved */
13323 0, /* 42 reserved */
13324 0, /* 43 reserved */
13325 0, /* 44 reserved */
13326 0, /* 45 reserved */
13327 0, /* 46 reserved */
13328 0, /* 47 reserved */
13329 0, /* 48 reserved */
13330 0, /* 49 reserved */
13331 0, /* 50 reserved */
13332 0, /* 51 reserved */
13333 0, /* 52 reserved */
13334 0, /* 53 reserved */
13335 0, /* 54 reserved */
13336 0, /* 55 reserved */
13337 0, /* 56 cisptr_lsw */
13338 0, /* 57 cisprt_msw */
13339 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
13340 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
13341 0, /* 60 reserved */
13342 0, /* 61 reserved */
13343 0, /* 62 reserved */
13344 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013345};
13346
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013347static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013348 0, /* 00 cfg_lsw */
13349 0, /* 01 cfg_msw */
13350 0, /* 02 disc_enable */
13351 0, /* 03 wdtr_able */
13352 0, /* 04 sdtr_speed1 */
13353 0, /* 05 start_motor */
13354 0, /* 06 tagqng_able */
13355 0, /* 07 bios_scan */
13356 0, /* 08 scam_tolerant */
13357 1, /* 09 adapter_scsi_id */
13358 1, /* bios_boot_delay */
13359 1, /* 10 scsi_reset_delay */
13360 1, /* bios_id_lun */
13361 1, /* 11 termination_se */
13362 1, /* termination_lvd */
13363 0, /* 12 bios_ctrl */
13364 0, /* 13 sdtr_speed2 */
13365 0, /* 14 sdtr_speed3 */
13366 1, /* 15 max_host_qng */
13367 1, /* max_dvc_qng */
13368 0, /* 16 dvc_cntl */
13369 0, /* 17 sdtr_speed4 */
13370 0, /* 18 serial_number_word1 */
13371 0, /* 19 serial_number_word2 */
13372 0, /* 20 serial_number_word3 */
13373 0, /* 21 check_sum */
13374 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13375 , /* 22-29 oem_name[16] */
13376 0, /* 30 dvc_err_code */
13377 0, /* 31 adv_err_code */
13378 0, /* 32 adv_err_addr */
13379 0, /* 33 saved_dvc_err_code */
13380 0, /* 34 saved_adv_err_code */
13381 0, /* 35 saved_adv_err_addr */
13382 0, /* 36 reserved */
13383 0, /* 37 reserved */
13384 0, /* 38 reserved */
13385 0, /* 39 reserved */
13386 0, /* 40 reserved */
13387 0, /* 41 reserved */
13388 0, /* 42 reserved */
13389 0, /* 43 reserved */
13390 0, /* 44 reserved */
13391 0, /* 45 reserved */
13392 0, /* 46 reserved */
13393 0, /* 47 reserved */
13394 0, /* 48 reserved */
13395 0, /* 49 reserved */
13396 0, /* 50 reserved */
13397 0, /* 51 reserved */
13398 0, /* 52 reserved */
13399 0, /* 53 reserved */
13400 0, /* 54 reserved */
13401 0, /* 55 reserved */
13402 0, /* 56 cisptr_lsw */
13403 0, /* 57 cisprt_msw */
13404 0, /* 58 subsysvid */
13405 0, /* 59 subsysid */
13406 0, /* 60 reserved */
13407 0, /* 61 reserved */
13408 0, /* 62 reserved */
13409 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013410};
13411
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013412static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013413 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
13414 0x0000, /* 01 cfg_msw */
13415 0xFFFF, /* 02 disc_enable */
13416 0xFFFF, /* 03 wdtr_able */
13417 0x5555, /* 04 sdtr_speed1 */
13418 0xFFFF, /* 05 start_motor */
13419 0xFFFF, /* 06 tagqng_able */
13420 0xFFFF, /* 07 bios_scan */
13421 0, /* 08 scam_tolerant */
13422 7, /* 09 adapter_scsi_id */
13423 0, /* bios_boot_delay */
13424 3, /* 10 scsi_reset_delay */
13425 0, /* bios_id_lun */
13426 0, /* 11 termination_se */
13427 0, /* termination_lvd */
13428 0xFFE7, /* 12 bios_ctrl */
13429 0x5555, /* 13 sdtr_speed2 */
13430 0x5555, /* 14 sdtr_speed3 */
13431 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
13432 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13433 0, /* 16 dvc_cntl */
13434 0x5555, /* 17 sdtr_speed4 */
13435 0, /* 18 serial_number_word1 */
13436 0, /* 19 serial_number_word2 */
13437 0, /* 20 serial_number_word3 */
13438 0, /* 21 check_sum */
13439 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13440 , /* 22-29 oem_name[16] */
13441 0, /* 30 dvc_err_code */
13442 0, /* 31 adv_err_code */
13443 0, /* 32 adv_err_addr */
13444 0, /* 33 saved_dvc_err_code */
13445 0, /* 34 saved_adv_err_code */
13446 0, /* 35 saved_adv_err_addr */
13447 0, /* 36 reserved */
13448 0, /* 37 reserved */
13449 0, /* 38 reserved */
13450 0, /* 39 reserved */
13451 0, /* 40 reserved */
13452 0, /* 41 reserved */
13453 0, /* 42 reserved */
13454 0, /* 43 reserved */
13455 0, /* 44 reserved */
13456 0, /* 45 reserved */
13457 0, /* 46 reserved */
13458 0, /* 47 reserved */
13459 0, /* 48 reserved */
13460 0, /* 49 reserved */
13461 0, /* 50 reserved */
13462 0, /* 51 reserved */
13463 0, /* 52 reserved */
13464 0, /* 53 reserved */
13465 0, /* 54 reserved */
13466 0, /* 55 reserved */
13467 0, /* 56 cisptr_lsw */
13468 0, /* 57 cisprt_msw */
13469 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
13470 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
13471 0, /* 60 reserved */
13472 0, /* 61 reserved */
13473 0, /* 62 reserved */
13474 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013475};
13476
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013477static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013478 0, /* 00 cfg_lsw */
13479 0, /* 01 cfg_msw */
13480 0, /* 02 disc_enable */
13481 0, /* 03 wdtr_able */
13482 0, /* 04 sdtr_speed1 */
13483 0, /* 05 start_motor */
13484 0, /* 06 tagqng_able */
13485 0, /* 07 bios_scan */
13486 0, /* 08 scam_tolerant */
13487 1, /* 09 adapter_scsi_id */
13488 1, /* bios_boot_delay */
13489 1, /* 10 scsi_reset_delay */
13490 1, /* bios_id_lun */
13491 1, /* 11 termination_se */
13492 1, /* termination_lvd */
13493 0, /* 12 bios_ctrl */
13494 0, /* 13 sdtr_speed2 */
13495 0, /* 14 sdtr_speed3 */
13496 1, /* 15 max_host_qng */
13497 1, /* max_dvc_qng */
13498 0, /* 16 dvc_cntl */
13499 0, /* 17 sdtr_speed4 */
13500 0, /* 18 serial_number_word1 */
13501 0, /* 19 serial_number_word2 */
13502 0, /* 20 serial_number_word3 */
13503 0, /* 21 check_sum */
13504 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13505 , /* 22-29 oem_name[16] */
13506 0, /* 30 dvc_err_code */
13507 0, /* 31 adv_err_code */
13508 0, /* 32 adv_err_addr */
13509 0, /* 33 saved_dvc_err_code */
13510 0, /* 34 saved_adv_err_code */
13511 0, /* 35 saved_adv_err_addr */
13512 0, /* 36 reserved */
13513 0, /* 37 reserved */
13514 0, /* 38 reserved */
13515 0, /* 39 reserved */
13516 0, /* 40 reserved */
13517 0, /* 41 reserved */
13518 0, /* 42 reserved */
13519 0, /* 43 reserved */
13520 0, /* 44 reserved */
13521 0, /* 45 reserved */
13522 0, /* 46 reserved */
13523 0, /* 47 reserved */
13524 0, /* 48 reserved */
13525 0, /* 49 reserved */
13526 0, /* 50 reserved */
13527 0, /* 51 reserved */
13528 0, /* 52 reserved */
13529 0, /* 53 reserved */
13530 0, /* 54 reserved */
13531 0, /* 55 reserved */
13532 0, /* 56 cisptr_lsw */
13533 0, /* 57 cisprt_msw */
13534 0, /* 58 subsysvid */
13535 0, /* 59 subsysid */
13536 0, /* 60 reserved */
13537 0, /* 61 reserved */
13538 0, /* 62 reserved */
13539 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013540};
13541
13542/*
13543 * Initialize the ADV_DVC_VAR structure.
13544 *
13545 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13546 *
13547 * For a non-fatal error return a warning code. If there are no warnings
13548 * then 0 is returned.
13549 */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040013550static int __devinit
13551AdvInitGetConfig(struct pci_dev *pdev, ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013552{
Matthew Wilcox9649af32007-07-26 21:51:47 -060013553 unsigned short warn_code = 0;
13554 AdvPortAddr iop_base = asc_dvc->iop_base;
Matthew Wilcox9649af32007-07-26 21:51:47 -060013555 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013556 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013557
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013558 asc_dvc->err_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013559
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013560 /*
13561 * Save the state of the PCI Configuration Command Register
13562 * "Parity Error Response Control" Bit. If the bit is clear (0),
13563 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13564 * DMA parity errors.
13565 */
13566 asc_dvc->cfg->control_flag = 0;
Matthew Wilcox9649af32007-07-26 21:51:47 -060013567 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
13568 if ((cmd & PCI_COMMAND_PARITY) == 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013569 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013570
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013571 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
13572 ADV_LIB_VERSION_MINOR;
13573 asc_dvc->cfg->chip_version =
13574 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013575
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013576 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
13577 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13578 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013579
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013580 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
13581 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13582 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013583
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013584 /*
13585 * Reset the chip to start and allow register writes.
13586 */
13587 if (AdvFindSignature(iop_base) == 0) {
13588 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13589 return ADV_ERROR;
13590 } else {
13591 /*
13592 * The caller must set 'chip_type' to a valid setting.
13593 */
13594 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13595 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13596 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13597 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13598 return ADV_ERROR;
13599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013601 /*
13602 * Reset Chip.
13603 */
13604 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13605 ADV_CTRL_REG_CMD_RESET);
13606 DvcSleepMilliSecond(100);
13607 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13608 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013609
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013610 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060013611 status = AdvInitFrom38C1600EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013612 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060013613 status = AdvInitFrom38C0800EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013614 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060013615 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013616 }
13617 warn_code |= status;
13618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013619
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013620 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013621}
13622
13623/*
13624 * Initialize the ASC-3550.
13625 *
13626 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13627 *
13628 * For a non-fatal error return a warning code. If there are no warnings
13629 * then 0 is returned.
13630 *
13631 * Needed after initialization for error recovery.
13632 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013633static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013634{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013635 AdvPortAddr iop_base;
13636 ushort warn_code;
13637 ADV_DCNT sum;
13638 int begin_addr;
13639 int end_addr;
13640 ushort code_sum;
13641 int word;
13642 int j;
13643 int adv_asc3550_expanded_size;
13644 ADV_CARR_T *carrp;
13645 ADV_DCNT contig_len;
13646 ADV_SDCNT buf_size;
13647 ADV_PADDR carr_paddr;
13648 int i;
13649 ushort scsi_cfg1;
13650 uchar tid;
13651 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
13652 ushort wdtr_able = 0, sdtr_able, tagqng_able;
13653 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070013654
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013655 /* If there is already an error, don't continue. */
13656 if (asc_dvc->err_code != 0) {
13657 return ADV_ERROR;
13658 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013659
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013660 /*
13661 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
13662 */
13663 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
13664 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13665 return ADV_ERROR;
13666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013667
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013668 warn_code = 0;
13669 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013670
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013671 /*
13672 * Save the RISC memory BIOS region before writing the microcode.
13673 * The BIOS may already be loaded and using its RISC LRAM region
13674 * so its region must be saved and restored.
13675 *
13676 * Note: This code makes the assumption, which is currently true,
13677 * that a chip reset does not clear RISC LRAM.
13678 */
13679 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
13680 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
13681 bios_mem[i]);
13682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013683
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013684 /*
13685 * Save current per TID negotiated values.
13686 */
13687 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
13688 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013689
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013690 bios_version =
13691 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
13692 major = (bios_version >> 12) & 0xF;
13693 minor = (bios_version >> 8) & 0xF;
13694 if (major < 3 || (major == 3 && minor == 1)) {
13695 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
13696 AdvReadWordLram(iop_base, 0x120, wdtr_able);
13697 } else {
13698 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
13699 }
13700 }
13701 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
13702 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
13703 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13704 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
13705 max_cmd[tid]);
13706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013707
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013708 /*
13709 * Load the Microcode
13710 *
13711 * Write the microcode image to RISC memory starting at address 0.
13712 */
13713 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
13714 /* Assume the following compressed format of the microcode buffer:
13715 *
13716 * 254 word (508 byte) table indexed by byte code followed
13717 * by the following byte codes:
13718 *
13719 * 1-Byte Code:
13720 * 00: Emit word 0 in table.
13721 * 01: Emit word 1 in table.
13722 * .
13723 * FD: Emit word 253 in table.
13724 *
13725 * Multi-Byte Code:
13726 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
13727 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
13728 */
13729 word = 0;
13730 for (i = 253 * 2; i < _adv_asc3550_size; i++) {
13731 if (_adv_asc3550_buf[i] == 0xff) {
13732 for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) {
13733 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13734 _adv_asc3550_buf
13735 [i +
13736 3] << 8) |
13737 _adv_asc3550_buf
13738 [i + 2]));
13739 word++;
13740 }
13741 i += 3;
13742 } else if (_adv_asc3550_buf[i] == 0xfe) {
13743 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13744 _adv_asc3550_buf[i +
13745 2]
13746 << 8) |
13747 _adv_asc3550_buf[i +
13748 1]));
13749 i += 2;
13750 word++;
13751 } else {
13752 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13753 _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
13754 word++;
13755 }
13756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013758 /*
13759 * Set 'word' for later use to clear the rest of memory and save
13760 * the expanded mcode size.
13761 */
13762 word *= 2;
13763 adv_asc3550_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013764
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013765 /*
13766 * Clear the rest of ASC-3550 Internal RAM (8KB).
13767 */
13768 for (; word < ADV_3550_MEMSIZE; word += 2) {
13769 AdvWriteWordAutoIncLram(iop_base, 0);
13770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013772 /*
13773 * Verify the microcode checksum.
13774 */
13775 sum = 0;
13776 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013777
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013778 for (word = 0; word < adv_asc3550_expanded_size; word += 2) {
13779 sum += AdvReadWordAutoIncLram(iop_base);
13780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013781
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013782 if (sum != _adv_asc3550_chksum) {
13783 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
13784 return ADV_ERROR;
13785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013786
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013787 /*
13788 * Restore the RISC memory BIOS region.
13789 */
13790 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
13791 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
13792 bios_mem[i]);
13793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013794
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013795 /*
13796 * Calculate and write the microcode code checksum to the microcode
13797 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
13798 */
13799 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
13800 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
13801 code_sum = 0;
13802 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
13803 for (word = begin_addr; word < end_addr; word += 2) {
13804 code_sum += AdvReadWordAutoIncLram(iop_base);
13805 }
13806 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013807
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013808 /*
13809 * Read and save microcode version and date.
13810 */
13811 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
13812 asc_dvc->cfg->mcode_date);
13813 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
13814 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013815
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013816 /*
13817 * Set the chip type to indicate the ASC3550.
13818 */
13819 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013820
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013821 /*
13822 * If the PCI Configuration Command Register "Parity Error Response
13823 * Control" Bit was clear (0), then set the microcode variable
13824 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
13825 * to ignore DMA parity errors.
13826 */
13827 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
13828 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
13829 word |= CONTROL_FLAG_IGNORE_PERR;
13830 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
13831 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013832
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013833 /*
13834 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
13835 * threshold of 128 bytes. This register is only accessible to the host.
13836 */
13837 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
13838 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013839
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013840 /*
13841 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040013842 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013843 * device reports it is capable of in Inquiry byte 7.
13844 *
13845 * If SCSI Bus Resets have been disabled, then directly set
13846 * SDTR and WDTR from the EEPROM configuration. This will allow
13847 * the BIOS and warm boot to work without a SCSI bus hang on
13848 * the Inquiry caused by host and target mismatched DTR values.
13849 * Without the SCSI Bus Reset, before an Inquiry a device can't
13850 * be assumed to be in Asynchronous, Narrow mode.
13851 */
13852 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
13853 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
13854 asc_dvc->wdtr_able);
13855 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
13856 asc_dvc->sdtr_able);
13857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013858
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013859 /*
13860 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
13861 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
13862 * bitmask. These values determine the maximum SDTR speed negotiated
13863 * with a device.
13864 *
13865 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
13866 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
13867 * without determining here whether the device supports SDTR.
13868 *
13869 * 4-bit speed SDTR speed name
13870 * =========== ===============
13871 * 0000b (0x0) SDTR disabled
13872 * 0001b (0x1) 5 Mhz
13873 * 0010b (0x2) 10 Mhz
13874 * 0011b (0x3) 20 Mhz (Ultra)
13875 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
13876 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
13877 * 0110b (0x6) Undefined
13878 * .
13879 * 1111b (0xF) Undefined
13880 */
13881 word = 0;
13882 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13883 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
13884 /* Set Ultra speed for TID 'tid'. */
13885 word |= (0x3 << (4 * (tid % 4)));
13886 } else {
13887 /* Set Fast speed for TID 'tid'. */
13888 word |= (0x2 << (4 * (tid % 4)));
13889 }
13890 if (tid == 3) { /* Check if done with sdtr_speed1. */
13891 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
13892 word = 0;
13893 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
13894 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
13895 word = 0;
13896 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
13897 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
13898 word = 0;
13899 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
13900 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
13901 /* End of loop. */
13902 }
13903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013904
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013905 /*
13906 * Set microcode operating variable for the disconnect per TID bitmask.
13907 */
13908 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
13909 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013910
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013911 /*
13912 * Set SCSI_CFG0 Microcode Default Value.
13913 *
13914 * The microcode will set the SCSI_CFG0 register using this value
13915 * after it is started below.
13916 */
13917 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
13918 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
13919 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013920
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013921 /*
13922 * Determine SCSI_CFG1 Microcode Default Value.
13923 *
13924 * The microcode will set the SCSI_CFG1 register using this value
13925 * after it is started below.
13926 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013927
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013928 /* Read current SCSI_CFG1 Register value. */
13929 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013930
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013931 /*
13932 * If all three connectors are in use, return an error.
13933 */
13934 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
13935 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
13936 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
13937 return ADV_ERROR;
13938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013940 /*
13941 * If the internal narrow cable is reversed all of the SCSI_CTRL
13942 * register signals will be set. Check for and return an error if
13943 * this condition is found.
13944 */
13945 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
13946 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
13947 return ADV_ERROR;
13948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013949
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013950 /*
13951 * If this is a differential board and a single-ended device
13952 * is attached to one of the connectors, return an error.
13953 */
13954 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
13955 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
13956 return ADV_ERROR;
13957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013958
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013959 /*
13960 * If automatic termination control is enabled, then set the
13961 * termination value based on a table listed in a_condor.h.
13962 *
13963 * If manual termination was specified with an EEPROM setting
13964 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
13965 * is ready to be 'ored' into SCSI_CFG1.
13966 */
13967 if (asc_dvc->cfg->termination == 0) {
13968 /*
13969 * The software always controls termination by setting TERM_CTL_SEL.
13970 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
13971 */
13972 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013973
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013974 switch (scsi_cfg1 & CABLE_DETECT) {
13975 /* TERM_CTL_H: on, TERM_CTL_L: on */
13976 case 0x3:
13977 case 0x7:
13978 case 0xB:
13979 case 0xD:
13980 case 0xE:
13981 case 0xF:
13982 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
13983 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013984
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013985 /* TERM_CTL_H: on, TERM_CTL_L: off */
13986 case 0x1:
13987 case 0x5:
13988 case 0x9:
13989 case 0xA:
13990 case 0xC:
13991 asc_dvc->cfg->termination |= TERM_CTL_H;
13992 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013993
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013994 /* TERM_CTL_H: off, TERM_CTL_L: off */
13995 case 0x2:
13996 case 0x6:
13997 break;
13998 }
13999 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014000
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014001 /*
14002 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
14003 */
14004 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014005
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014006 /*
14007 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
14008 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
14009 * referenced, because the hardware internally inverts
14010 * the Termination High and Low bits if TERM_POL is set.
14011 */
14012 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014013
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014014 /*
14015 * Set SCSI_CFG1 Microcode Default Value
14016 *
14017 * Set filter value and possibly modified termination control
14018 * bits in the Microcode SCSI_CFG1 Register Value.
14019 *
14020 * The microcode will set the SCSI_CFG1 register using this value
14021 * after it is started below.
14022 */
14023 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
14024 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014025
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014026 /*
14027 * Set MEM_CFG Microcode Default Value
14028 *
14029 * The microcode will set the MEM_CFG register using this value
14030 * after it is started below.
14031 *
14032 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
14033 * are defined.
14034 *
14035 * ASC-3550 has 8KB internal memory.
14036 */
14037 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
14038 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014039
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014040 /*
14041 * Set SEL_MASK Microcode Default Value
14042 *
14043 * The microcode will set the SEL_MASK register using this value
14044 * after it is started below.
14045 */
14046 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14047 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014049 /*
14050 * Build carrier freelist.
14051 *
14052 * Driver must have already allocated memory and set 'carrier_buf'.
14053 */
14054 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014055
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014056 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
14057 asc_dvc->carr_freelist = NULL;
14058 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
14059 buf_size = ADV_CARRIER_BUFSIZE;
14060 } else {
14061 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
14062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014063
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014064 do {
14065 /*
14066 * Get physical address of the carrier 'carrp'.
14067 */
14068 contig_len = sizeof(ADV_CARR_T);
14069 carr_paddr =
14070 cpu_to_le32(DvcGetPhyAddr
14071 (asc_dvc, NULL, (uchar *)carrp,
14072 (ADV_SDCNT *)&contig_len,
14073 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014074
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014075 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014076
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014077 /*
14078 * If the current carrier is not physically contiguous, then
14079 * maybe there was a page crossing. Try the next carrier aligned
14080 * start address.
14081 */
14082 if (contig_len < sizeof(ADV_CARR_T)) {
14083 carrp++;
14084 continue;
14085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014086
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014087 carrp->carr_pa = carr_paddr;
14088 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014089
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014090 /*
14091 * Insert the carrier at the beginning of the freelist.
14092 */
14093 carrp->next_vpa =
14094 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14095 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014096
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014097 carrp++;
14098 }
14099 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014100
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014101 /*
14102 * Set-up the Host->RISC Initiator Command Queue (ICQ).
14103 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014104
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014105 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
14106 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14107 return ADV_ERROR;
14108 }
14109 asc_dvc->carr_freelist = (ADV_CARR_T *)
14110 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014111
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014112 /*
14113 * The first command issued will be placed in the stopper carrier.
14114 */
14115 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014116
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014117 /*
14118 * Set RISC ICQ physical address start value.
14119 */
14120 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014121
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014122 /*
14123 * Set-up the RISC->Host Initiator Response Queue (IRQ).
14124 */
14125 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
14126 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14127 return ADV_ERROR;
14128 }
14129 asc_dvc->carr_freelist = (ADV_CARR_T *)
14130 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014131
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014132 /*
14133 * The first command completed by the RISC will be placed in
14134 * the stopper.
14135 *
14136 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
14137 * completed the RISC will set the ASC_RQ_STOPPER bit.
14138 */
14139 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014140
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014141 /*
14142 * Set RISC IRQ physical address start value.
14143 */
14144 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
14145 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014146
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014147 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14148 (ADV_INTR_ENABLE_HOST_INTR |
14149 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014150
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014151 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14152 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014153
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014154 /* finally, finally, gentlemen, start your engine */
14155 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014156
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014157 /*
14158 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14159 * Resets should be performed. The RISC has to be running
14160 * to issue a SCSI Bus Reset.
14161 */
14162 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
14163 /*
14164 * If the BIOS Signature is present in memory, restore the
14165 * BIOS Handshake Configuration Table and do not perform
14166 * a SCSI Bus Reset.
14167 */
14168 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
14169 0x55AA) {
14170 /*
14171 * Restore per TID negotiated values.
14172 */
14173 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14174 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14175 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
14176 tagqng_able);
14177 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14178 AdvWriteByteLram(iop_base,
14179 ASC_MC_NUMBER_OF_MAX_CMD + tid,
14180 max_cmd[tid]);
14181 }
14182 } else {
14183 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
14184 warn_code = ASC_WARN_BUSRESET_ERROR;
14185 }
14186 }
14187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014188
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014190}
14191
14192/*
14193 * Initialize the ASC-38C0800.
14194 *
14195 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14196 *
14197 * For a non-fatal error return a warning code. If there are no warnings
14198 * then 0 is returned.
14199 *
14200 * Needed after initialization for error recovery.
14201 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014202static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014203{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014204 AdvPortAddr iop_base;
14205 ushort warn_code;
14206 ADV_DCNT sum;
14207 int begin_addr;
14208 int end_addr;
14209 ushort code_sum;
14210 int word;
14211 int j;
14212 int adv_asc38C0800_expanded_size;
14213 ADV_CARR_T *carrp;
14214 ADV_DCNT contig_len;
14215 ADV_SDCNT buf_size;
14216 ADV_PADDR carr_paddr;
14217 int i;
14218 ushort scsi_cfg1;
14219 uchar byte;
14220 uchar tid;
14221 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
14222 ushort wdtr_able, sdtr_able, tagqng_able;
14223 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070014224
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014225 /* If there is already an error, don't continue. */
14226 if (asc_dvc->err_code != 0) {
14227 return ADV_ERROR;
14228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014229
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014230 /*
14231 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
14232 */
14233 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
14234 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
14235 return ADV_ERROR;
14236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014237
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014238 warn_code = 0;
14239 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014241 /*
14242 * Save the RISC memory BIOS region before writing the microcode.
14243 * The BIOS may already be loaded and using its RISC LRAM region
14244 * so its region must be saved and restored.
14245 *
14246 * Note: This code makes the assumption, which is currently true,
14247 * that a chip reset does not clear RISC LRAM.
14248 */
14249 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14250 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14251 bios_mem[i]);
14252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014254 /*
14255 * Save current per TID negotiated values.
14256 */
14257 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14258 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14259 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14260 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14261 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14262 max_cmd[tid]);
14263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014264
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014265 /*
14266 * RAM BIST (RAM Built-In Self Test)
14267 *
14268 * Address : I/O base + offset 0x38h register (byte).
14269 * Function: Bit 7-6(RW) : RAM mode
14270 * Normal Mode : 0x00
14271 * Pre-test Mode : 0x40
14272 * RAM Test Mode : 0x80
14273 * Bit 5 : unused
14274 * Bit 4(RO) : Done bit
14275 * Bit 3-0(RO) : Status
14276 * Host Error : 0x08
14277 * Int_RAM Error : 0x04
14278 * RISC Error : 0x02
14279 * SCSI Error : 0x01
14280 * No Error : 0x00
14281 *
14282 * Note: RAM BIST code should be put right here, before loading the
14283 * microcode and after saving the RISC memory BIOS region.
14284 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014285
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014286 /*
14287 * LRAM Pre-test
14288 *
14289 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
14290 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
14291 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
14292 * to NORMAL_MODE, return an error too.
14293 */
14294 for (i = 0; i < 2; i++) {
14295 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
14296 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14297 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14298 if ((byte & RAM_TEST_DONE) == 0
14299 || (byte & 0x0F) != PRE_TEST_VALUE) {
14300 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14301 return ADV_ERROR;
14302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014303
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014304 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
14305 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14306 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
14307 != NORMAL_VALUE) {
14308 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14309 return ADV_ERROR;
14310 }
14311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014312
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014313 /*
14314 * LRAM Test - It takes about 1.5 ms to run through the test.
14315 *
14316 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
14317 * If Done bit not set or Status not 0, save register byte, set the
14318 * err_code, and return an error.
14319 */
14320 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
14321 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014322
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014323 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14324 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
14325 /* Get here if Done bit not set or Status not 0. */
14326 asc_dvc->bist_err_code = byte; /* for BIOS display message */
14327 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
14328 return ADV_ERROR;
14329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014330
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014331 /* We need to reset back to normal mode after LRAM test passes. */
14332 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014333
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014334 /*
14335 * Load the Microcode
14336 *
14337 * Write the microcode image to RISC memory starting at address 0.
14338 *
14339 */
14340 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014341
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014342 /* Assume the following compressed format of the microcode buffer:
14343 *
14344 * 254 word (508 byte) table indexed by byte code followed
14345 * by the following byte codes:
14346 *
14347 * 1-Byte Code:
14348 * 00: Emit word 0 in table.
14349 * 01: Emit word 1 in table.
14350 * .
14351 * FD: Emit word 253 in table.
14352 *
14353 * Multi-Byte Code:
14354 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
14355 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
14356 */
14357 word = 0;
14358 for (i = 253 * 2; i < _adv_asc38C0800_size; i++) {
14359 if (_adv_asc38C0800_buf[i] == 0xff) {
14360 for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) {
14361 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14362 _adv_asc38C0800_buf
14363 [i +
14364 3] << 8) |
14365 _adv_asc38C0800_buf
14366 [i + 2]));
14367 word++;
14368 }
14369 i += 3;
14370 } else if (_adv_asc38C0800_buf[i] == 0xfe) {
14371 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14372 _adv_asc38C0800_buf
14373 [i +
14374 2] << 8) |
14375 _adv_asc38C0800_buf[i
14376 +
14377 1]));
14378 i += 2;
14379 word++;
14380 } else {
14381 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14382 _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
14383 word++;
14384 }
14385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014386
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014387 /*
14388 * Set 'word' for later use to clear the rest of memory and save
14389 * the expanded mcode size.
14390 */
14391 word *= 2;
14392 adv_asc38C0800_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014393
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014394 /*
14395 * Clear the rest of ASC-38C0800 Internal RAM (16KB).
14396 */
14397 for (; word < ADV_38C0800_MEMSIZE; word += 2) {
14398 AdvWriteWordAutoIncLram(iop_base, 0);
14399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014400
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014401 /*
14402 * Verify the microcode checksum.
14403 */
14404 sum = 0;
14405 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014406
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014407 for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) {
14408 sum += AdvReadWordAutoIncLram(iop_base);
14409 }
14410 ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014411
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014412 ASC_DBG2(1,
14413 "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n",
14414 (ulong)sum, (ulong)_adv_asc38C0800_chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014415
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014416 if (sum != _adv_asc38C0800_chksum) {
14417 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14418 return ADV_ERROR;
14419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014420
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014421 /*
14422 * Restore the RISC memory BIOS region.
14423 */
14424 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14425 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14426 bios_mem[i]);
14427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014428
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014429 /*
14430 * Calculate and write the microcode code checksum to the microcode
14431 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14432 */
14433 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14434 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14435 code_sum = 0;
14436 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
14437 for (word = begin_addr; word < end_addr; word += 2) {
14438 code_sum += AdvReadWordAutoIncLram(iop_base);
14439 }
14440 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014442 /*
14443 * Read microcode version and date.
14444 */
14445 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
14446 asc_dvc->cfg->mcode_date);
14447 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
14448 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014449
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014450 /*
14451 * Set the chip type to indicate the ASC38C0800.
14452 */
14453 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014454
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014455 /*
14456 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
14457 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
14458 * cable detection and then we are able to read C_DET[3:0].
14459 *
14460 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
14461 * Microcode Default Value' section below.
14462 */
14463 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14464 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
14465 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014466
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014467 /*
14468 * If the PCI Configuration Command Register "Parity Error Response
14469 * Control" Bit was clear (0), then set the microcode variable
14470 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14471 * to ignore DMA parity errors.
14472 */
14473 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
14474 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14475 word |= CONTROL_FLAG_IGNORE_PERR;
14476 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014478
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014479 /*
14480 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
14481 * bits for the default FIFO threshold.
14482 *
14483 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
14484 *
14485 * For DMA Errata #4 set the BC_THRESH_ENB bit.
14486 */
14487 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14488 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
14489 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014490
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014491 /*
14492 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040014493 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014494 * device reports it is capable of in Inquiry byte 7.
14495 *
14496 * If SCSI Bus Resets have been disabled, then directly set
14497 * SDTR and WDTR from the EEPROM configuration. This will allow
14498 * the BIOS and warm boot to work without a SCSI bus hang on
14499 * the Inquiry caused by host and target mismatched DTR values.
14500 * Without the SCSI Bus Reset, before an Inquiry a device can't
14501 * be assumed to be in Asynchronous, Narrow mode.
14502 */
14503 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
14504 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
14505 asc_dvc->wdtr_able);
14506 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
14507 asc_dvc->sdtr_able);
14508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014510 /*
14511 * Set microcode operating variables for DISC and SDTR_SPEED1,
14512 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
14513 * configuration values.
14514 *
14515 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
14516 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
14517 * without determining here whether the device supports SDTR.
14518 */
14519 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
14520 asc_dvc->cfg->disc_enable);
14521 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
14522 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
14523 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
14524 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014525
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014526 /*
14527 * Set SCSI_CFG0 Microcode Default Value.
14528 *
14529 * The microcode will set the SCSI_CFG0 register using this value
14530 * after it is started below.
14531 */
14532 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14533 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
14534 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014535
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014536 /*
14537 * Determine SCSI_CFG1 Microcode Default Value.
14538 *
14539 * The microcode will set the SCSI_CFG1 register using this value
14540 * after it is started below.
14541 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014542
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014543 /* Read current SCSI_CFG1 Register value. */
14544 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014545
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014546 /*
14547 * If the internal narrow cable is reversed all of the SCSI_CTRL
14548 * register signals will be set. Check for and return an error if
14549 * this condition is found.
14550 */
14551 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
14552 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14553 return ADV_ERROR;
14554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014555
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014556 /*
14557 * All kind of combinations of devices attached to one of four connectors
14558 * are acceptable except HVD device attached. For example, LVD device can
14559 * be attached to SE connector while SE device attached to LVD connector.
14560 * If LVD device attached to SE connector, it only runs up to Ultra speed.
14561 *
14562 * If an HVD device is attached to one of LVD connectors, return an error.
14563 * However, there is no way to detect HVD device attached to SE connectors.
14564 */
14565 if (scsi_cfg1 & HVD) {
14566 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
14567 return ADV_ERROR;
14568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014569
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014570 /*
14571 * If either SE or LVD automatic termination control is enabled, then
14572 * set the termination value based on a table listed in a_condor.h.
14573 *
14574 * If manual termination was specified with an EEPROM setting then
14575 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to
14576 * be 'ored' into SCSI_CFG1.
14577 */
14578 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
14579 /* SE automatic termination control is enabled. */
14580 switch (scsi_cfg1 & C_DET_SE) {
14581 /* TERM_SE_HI: on, TERM_SE_LO: on */
14582 case 0x1:
14583 case 0x2:
14584 case 0x3:
14585 asc_dvc->cfg->termination |= TERM_SE;
14586 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014588 /* TERM_SE_HI: on, TERM_SE_LO: off */
14589 case 0x0:
14590 asc_dvc->cfg->termination |= TERM_SE_HI;
14591 break;
14592 }
14593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014594
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014595 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
14596 /* LVD automatic termination control is enabled. */
14597 switch (scsi_cfg1 & C_DET_LVD) {
14598 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
14599 case 0x4:
14600 case 0x8:
14601 case 0xC:
14602 asc_dvc->cfg->termination |= TERM_LVD;
14603 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014604
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014605 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
14606 case 0x0:
14607 break;
14608 }
14609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014610
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014611 /*
14612 * Clear any set TERM_SE and TERM_LVD bits.
14613 */
14614 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014615
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014616 /*
14617 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
14618 */
14619 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014620
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014621 /*
14622 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits
14623 * and set possibly modified termination control bits in the Microcode
14624 * SCSI_CFG1 Register Value.
14625 */
14626 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014627
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014628 /*
14629 * Set SCSI_CFG1 Microcode Default Value
14630 *
14631 * Set possibly modified termination control and reset DIS_TERM_DRV
14632 * bits in the Microcode SCSI_CFG1 Register Value.
14633 *
14634 * The microcode will set the SCSI_CFG1 register using this value
14635 * after it is started below.
14636 */
14637 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014638
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014639 /*
14640 * Set MEM_CFG Microcode Default Value
14641 *
14642 * The microcode will set the MEM_CFG register using this value
14643 * after it is started below.
14644 *
14645 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
14646 * are defined.
14647 *
14648 * ASC-38C0800 has 16KB internal memory.
14649 */
14650 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
14651 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014652
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014653 /*
14654 * Set SEL_MASK Microcode Default Value
14655 *
14656 * The microcode will set the SEL_MASK register using this value
14657 * after it is started below.
14658 */
14659 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14660 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014661
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014662 /*
14663 * Build the carrier freelist.
14664 *
14665 * Driver must have already allocated memory and set 'carrier_buf'.
14666 */
14667 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014668
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014669 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
14670 asc_dvc->carr_freelist = NULL;
14671 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
14672 buf_size = ADV_CARRIER_BUFSIZE;
14673 } else {
14674 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
14675 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014676
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014677 do {
14678 /*
14679 * Get physical address for the carrier 'carrp'.
14680 */
14681 contig_len = sizeof(ADV_CARR_T);
14682 carr_paddr =
14683 cpu_to_le32(DvcGetPhyAddr
14684 (asc_dvc, NULL, (uchar *)carrp,
14685 (ADV_SDCNT *)&contig_len,
14686 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014687
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014688 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014689
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014690 /*
14691 * If the current carrier is not physically contiguous, then
14692 * maybe there was a page crossing. Try the next carrier aligned
14693 * start address.
14694 */
14695 if (contig_len < sizeof(ADV_CARR_T)) {
14696 carrp++;
14697 continue;
14698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014699
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014700 carrp->carr_pa = carr_paddr;
14701 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014702
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014703 /*
14704 * Insert the carrier at the beginning of the freelist.
14705 */
14706 carrp->next_vpa =
14707 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14708 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014709
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014710 carrp++;
14711 }
14712 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014713
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014714 /*
14715 * Set-up the Host->RISC Initiator Command Queue (ICQ).
14716 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014717
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014718 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
14719 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14720 return ADV_ERROR;
14721 }
14722 asc_dvc->carr_freelist = (ADV_CARR_T *)
14723 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014724
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014725 /*
14726 * The first command issued will be placed in the stopper carrier.
14727 */
14728 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014729
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014730 /*
14731 * Set RISC ICQ physical address start value.
14732 * carr_pa is LE, must be native before write
14733 */
14734 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014735
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014736 /*
14737 * Set-up the RISC->Host Initiator Response Queue (IRQ).
14738 */
14739 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
14740 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14741 return ADV_ERROR;
14742 }
14743 asc_dvc->carr_freelist = (ADV_CARR_T *)
14744 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014745
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014746 /*
14747 * The first command completed by the RISC will be placed in
14748 * the stopper.
14749 *
14750 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
14751 * completed the RISC will set the ASC_RQ_STOPPER bit.
14752 */
14753 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014754
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014755 /*
14756 * Set RISC IRQ physical address start value.
14757 *
14758 * carr_pa is LE, must be native before write *
14759 */
14760 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
14761 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014762
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014763 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14764 (ADV_INTR_ENABLE_HOST_INTR |
14765 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014766
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014767 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14768 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014769
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014770 /* finally, finally, gentlemen, start your engine */
14771 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014772
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014773 /*
14774 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14775 * Resets should be performed. The RISC has to be running
14776 * to issue a SCSI Bus Reset.
14777 */
14778 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
14779 /*
14780 * If the BIOS Signature is present in memory, restore the
14781 * BIOS Handshake Configuration Table and do not perform
14782 * a SCSI Bus Reset.
14783 */
14784 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
14785 0x55AA) {
14786 /*
14787 * Restore per TID negotiated values.
14788 */
14789 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14790 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14791 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
14792 tagqng_able);
14793 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14794 AdvWriteByteLram(iop_base,
14795 ASC_MC_NUMBER_OF_MAX_CMD + tid,
14796 max_cmd[tid]);
14797 }
14798 } else {
14799 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
14800 warn_code = ASC_WARN_BUSRESET_ERROR;
14801 }
14802 }
14803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014804
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014805 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014806}
14807
14808/*
14809 * Initialize the ASC-38C1600.
14810 *
14811 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
14812 *
14813 * For a non-fatal error return a warning code. If there are no warnings
14814 * then 0 is returned.
14815 *
14816 * Needed after initialization for error recovery.
14817 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014818static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014819{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014820 AdvPortAddr iop_base;
14821 ushort warn_code;
14822 ADV_DCNT sum;
14823 int begin_addr;
14824 int end_addr;
14825 ushort code_sum;
14826 long word;
14827 int j;
14828 int adv_asc38C1600_expanded_size;
14829 ADV_CARR_T *carrp;
14830 ADV_DCNT contig_len;
14831 ADV_SDCNT buf_size;
14832 ADV_PADDR carr_paddr;
14833 int i;
14834 ushort scsi_cfg1;
14835 uchar byte;
14836 uchar tid;
14837 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
14838 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
14839 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070014840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014841 /* If there is already an error, don't continue. */
14842 if (asc_dvc->err_code != 0) {
14843 return ADV_ERROR;
14844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014845
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014846 /*
14847 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
14848 */
14849 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
14850 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
14851 return ADV_ERROR;
14852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014853
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014854 warn_code = 0;
14855 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014857 /*
14858 * Save the RISC memory BIOS region before writing the microcode.
14859 * The BIOS may already be loaded and using its RISC LRAM region
14860 * so its region must be saved and restored.
14861 *
14862 * Note: This code makes the assumption, which is currently true,
14863 * that a chip reset does not clear RISC LRAM.
14864 */
14865 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14866 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14867 bios_mem[i]);
14868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014869
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014870 /*
14871 * Save current per TID negotiated values.
14872 */
14873 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14874 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14875 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14876 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14877 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
14878 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14879 max_cmd[tid]);
14880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014881
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014882 /*
14883 * RAM BIST (Built-In Self Test)
14884 *
14885 * Address : I/O base + offset 0x38h register (byte).
14886 * Function: Bit 7-6(RW) : RAM mode
14887 * Normal Mode : 0x00
14888 * Pre-test Mode : 0x40
14889 * RAM Test Mode : 0x80
14890 * Bit 5 : unused
14891 * Bit 4(RO) : Done bit
14892 * Bit 3-0(RO) : Status
14893 * Host Error : 0x08
14894 * Int_RAM Error : 0x04
14895 * RISC Error : 0x02
14896 * SCSI Error : 0x01
14897 * No Error : 0x00
14898 *
14899 * Note: RAM BIST code should be put right here, before loading the
14900 * microcode and after saving the RISC memory BIOS region.
14901 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014902
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014903 /*
14904 * LRAM Pre-test
14905 *
14906 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
14907 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
14908 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
14909 * to NORMAL_MODE, return an error too.
14910 */
14911 for (i = 0; i < 2; i++) {
14912 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
14913 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14914 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14915 if ((byte & RAM_TEST_DONE) == 0
14916 || (byte & 0x0F) != PRE_TEST_VALUE) {
14917 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14918 return ADV_ERROR;
14919 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014920
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014921 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
14922 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14923 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
14924 != NORMAL_VALUE) {
14925 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14926 return ADV_ERROR;
14927 }
14928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014929
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014930 /*
14931 * LRAM Test - It takes about 1.5 ms to run through the test.
14932 *
14933 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
14934 * If Done bit not set or Status not 0, save register byte, set the
14935 * err_code, and return an error.
14936 */
14937 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
14938 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014940 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14941 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
14942 /* Get here if Done bit not set or Status not 0. */
14943 asc_dvc->bist_err_code = byte; /* for BIOS display message */
14944 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
14945 return ADV_ERROR;
14946 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014947
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014948 /* We need to reset back to normal mode after LRAM test passes. */
14949 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014950
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014951 /*
14952 * Load the Microcode
14953 *
14954 * Write the microcode image to RISC memory starting at address 0.
14955 *
14956 */
14957 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014958
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014959 /*
14960 * Assume the following compressed format of the microcode buffer:
14961 *
14962 * 254 word (508 byte) table indexed by byte code followed
14963 * by the following byte codes:
14964 *
14965 * 1-Byte Code:
14966 * 00: Emit word 0 in table.
14967 * 01: Emit word 1 in table.
14968 * .
14969 * FD: Emit word 253 in table.
14970 *
14971 * Multi-Byte Code:
14972 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
14973 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
14974 */
14975 word = 0;
14976 for (i = 253 * 2; i < _adv_asc38C1600_size; i++) {
14977 if (_adv_asc38C1600_buf[i] == 0xff) {
14978 for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) {
14979 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14980 _adv_asc38C1600_buf
14981 [i +
14982 3] << 8) |
14983 _adv_asc38C1600_buf
14984 [i + 2]));
14985 word++;
14986 }
14987 i += 3;
14988 } else if (_adv_asc38C1600_buf[i] == 0xfe) {
14989 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14990 _adv_asc38C1600_buf
14991 [i +
14992 2] << 8) |
14993 _adv_asc38C1600_buf[i
14994 +
14995 1]));
14996 i += 2;
14997 word++;
14998 } else {
14999 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15000 _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2]));
15001 word++;
15002 }
15003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015004
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015005 /*
15006 * Set 'word' for later use to clear the rest of memory and save
15007 * the expanded mcode size.
15008 */
15009 word *= 2;
15010 adv_asc38C1600_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015011
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015012 /*
15013 * Clear the rest of ASC-38C1600 Internal RAM (32KB).
15014 */
15015 for (; word < ADV_38C1600_MEMSIZE; word += 2) {
15016 AdvWriteWordAutoIncLram(iop_base, 0);
15017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015018
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015019 /*
15020 * Verify the microcode checksum.
15021 */
15022 sum = 0;
15023 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015024
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015025 for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) {
15026 sum += AdvReadWordAutoIncLram(iop_base);
15027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015028
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015029 if (sum != _adv_asc38C1600_chksum) {
15030 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
15031 return ADV_ERROR;
15032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015033
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015034 /*
15035 * Restore the RISC memory BIOS region.
15036 */
15037 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
15038 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
15039 bios_mem[i]);
15040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015041
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015042 /*
15043 * Calculate and write the microcode code checksum to the microcode
15044 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
15045 */
15046 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
15047 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
15048 code_sum = 0;
15049 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
15050 for (word = begin_addr; word < end_addr; word += 2) {
15051 code_sum += AdvReadWordAutoIncLram(iop_base);
15052 }
15053 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015054
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015055 /*
15056 * Read microcode version and date.
15057 */
15058 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
15059 asc_dvc->cfg->mcode_date);
15060 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
15061 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015062
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015063 /*
15064 * Set the chip type to indicate the ASC38C1600.
15065 */
15066 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015067
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015068 /*
15069 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
15070 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
15071 * cable detection and then we are able to read C_DET[3:0].
15072 *
15073 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
15074 * Microcode Default Value' section below.
15075 */
15076 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
15077 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
15078 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015080 /*
15081 * If the PCI Configuration Command Register "Parity Error Response
15082 * Control" Bit was clear (0), then set the microcode variable
15083 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
15084 * to ignore DMA parity errors.
15085 */
15086 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
15087 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15088 word |= CONTROL_FLAG_IGNORE_PERR;
15089 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015091
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015092 /*
15093 * If the BIOS control flag AIPP (Asynchronous Information
15094 * Phase Protection) disable bit is not set, then set the firmware
15095 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
15096 * AIPP checking and encoding.
15097 */
15098 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
15099 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15100 word |= CONTROL_FLAG_ENABLE_AIPP;
15101 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015103
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015104 /*
15105 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
15106 * and START_CTL_TH [3:2].
15107 */
15108 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
15109 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015111 /*
15112 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040015113 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015114 * device reports it is capable of in Inquiry byte 7.
15115 *
15116 * If SCSI Bus Resets have been disabled, then directly set
15117 * SDTR and WDTR from the EEPROM configuration. This will allow
15118 * the BIOS and warm boot to work without a SCSI bus hang on
15119 * the Inquiry caused by host and target mismatched DTR values.
15120 * Without the SCSI Bus Reset, before an Inquiry a device can't
15121 * be assumed to be in Asynchronous, Narrow mode.
15122 */
15123 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
15124 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
15125 asc_dvc->wdtr_able);
15126 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
15127 asc_dvc->sdtr_able);
15128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015129
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015130 /*
15131 * Set microcode operating variables for DISC and SDTR_SPEED1,
15132 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
15133 * configuration values.
15134 *
15135 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
15136 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
15137 * without determining here whether the device supports SDTR.
15138 */
15139 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
15140 asc_dvc->cfg->disc_enable);
15141 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
15142 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
15143 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
15144 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015145
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015146 /*
15147 * Set SCSI_CFG0 Microcode Default Value.
15148 *
15149 * The microcode will set the SCSI_CFG0 register using this value
15150 * after it is started below.
15151 */
15152 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
15153 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
15154 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015155
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015156 /*
15157 * Calculate SCSI_CFG1 Microcode Default Value.
15158 *
15159 * The microcode will set the SCSI_CFG1 register using this value
15160 * after it is started below.
15161 *
15162 * Each ASC-38C1600 function has only two cable detect bits.
15163 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
15164 */
15165 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015166
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015167 /*
15168 * If the cable is reversed all of the SCSI_CTRL register signals
15169 * will be set. Check for and return an error if this condition is
15170 * found.
15171 */
15172 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
15173 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
15174 return ADV_ERROR;
15175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015176
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015177 /*
15178 * Each ASC-38C1600 function has two connectors. Only an HVD device
15179 * can not be connected to either connector. An LVD device or SE device
15180 * may be connected to either connecor. If an SE device is connected,
15181 * then at most Ultra speed (20 Mhz) can be used on both connectors.
15182 *
15183 * If an HVD device is attached, return an error.
15184 */
15185 if (scsi_cfg1 & HVD) {
15186 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
15187 return ADV_ERROR;
15188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015189
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015190 /*
15191 * Each function in the ASC-38C1600 uses only the SE cable detect and
15192 * termination because there are two connectors for each function. Each
15193 * function may use either LVD or SE mode. Corresponding the SE automatic
15194 * termination control EEPROM bits are used for each function. Each
15195 * function has its own EEPROM. If SE automatic control is enabled for
15196 * the function, then set the termination value based on a table listed
15197 * in a_condor.h.
15198 *
15199 * If manual termination is specified in the EEPROM for the function,
15200 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
15201 * ready to be 'ored' into SCSI_CFG1.
15202 */
15203 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
15204 /* SE automatic termination control is enabled. */
15205 switch (scsi_cfg1 & C_DET_SE) {
15206 /* TERM_SE_HI: on, TERM_SE_LO: on */
15207 case 0x1:
15208 case 0x2:
15209 case 0x3:
15210 asc_dvc->cfg->termination |= TERM_SE;
15211 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015212
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015213 case 0x0:
15214 if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) {
15215 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
15216 } else {
15217 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
15218 asc_dvc->cfg->termination |= TERM_SE_HI;
15219 }
15220 break;
15221 }
15222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015223
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015224 /*
15225 * Clear any set TERM_SE bits.
15226 */
15227 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015228
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015229 /*
15230 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
15231 */
15232 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015233
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015234 /*
15235 * Clear Big Endian and Terminator Polarity bits and set possibly
15236 * modified termination control bits in the Microcode SCSI_CFG1
15237 * Register Value.
15238 *
15239 * Big Endian bit is not used even on big endian machines.
15240 */
15241 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015242
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015243 /*
15244 * Set SCSI_CFG1 Microcode Default Value
15245 *
15246 * Set possibly modified termination control bits in the Microcode
15247 * SCSI_CFG1 Register Value.
15248 *
15249 * The microcode will set the SCSI_CFG1 register using this value
15250 * after it is started below.
15251 */
15252 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015254 /*
15255 * Set MEM_CFG Microcode Default Value
15256 *
15257 * The microcode will set the MEM_CFG register using this value
15258 * after it is started below.
15259 *
15260 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
15261 * are defined.
15262 *
15263 * ASC-38C1600 has 32KB internal memory.
15264 *
15265 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
15266 * out a special 16K Adv Library and Microcode version. After the issue
15267 * resolved, we should turn back to the 32K support. Both a_condor.h and
15268 * mcode.sas files also need to be updated.
15269 *
15270 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15271 * BIOS_EN | RAM_SZ_32KB);
15272 */
15273 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15274 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015275
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015276 /*
15277 * Set SEL_MASK Microcode Default Value
15278 *
15279 * The microcode will set the SEL_MASK register using this value
15280 * after it is started below.
15281 */
15282 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
15283 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015284
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015285 /*
15286 * Build the carrier freelist.
15287 *
15288 * Driver must have already allocated memory and set 'carrier_buf'.
15289 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015290
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015291 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015292
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015293 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
15294 asc_dvc->carr_freelist = NULL;
15295 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
15296 buf_size = ADV_CARRIER_BUFSIZE;
15297 } else {
15298 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
15299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015300
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015301 do {
15302 /*
15303 * Get physical address for the carrier 'carrp'.
15304 */
15305 contig_len = sizeof(ADV_CARR_T);
15306 carr_paddr =
15307 cpu_to_le32(DvcGetPhyAddr
15308 (asc_dvc, NULL, (uchar *)carrp,
15309 (ADV_SDCNT *)&contig_len,
15310 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015311
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015312 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015313
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015314 /*
15315 * If the current carrier is not physically contiguous, then
15316 * maybe there was a page crossing. Try the next carrier aligned
15317 * start address.
15318 */
15319 if (contig_len < sizeof(ADV_CARR_T)) {
15320 carrp++;
15321 continue;
15322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015323
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015324 carrp->carr_pa = carr_paddr;
15325 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015326
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015327 /*
15328 * Insert the carrier at the beginning of the freelist.
15329 */
15330 carrp->next_vpa =
15331 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
15332 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015333
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015334 carrp++;
15335 }
15336 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015337
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015338 /*
15339 * Set-up the Host->RISC Initiator Command Queue (ICQ).
15340 */
15341 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
15342 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15343 return ADV_ERROR;
15344 }
15345 asc_dvc->carr_freelist = (ADV_CARR_T *)
15346 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015347
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015348 /*
15349 * The first command issued will be placed in the stopper carrier.
15350 */
15351 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015352
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015353 /*
15354 * Set RISC ICQ physical address start value. Initialize the
15355 * COMMA register to the same value otherwise the RISC will
15356 * prematurely detect a command is available.
15357 */
15358 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
15359 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
15360 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015362 /*
15363 * Set-up the RISC->Host Initiator Response Queue (IRQ).
15364 */
15365 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
15366 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15367 return ADV_ERROR;
15368 }
15369 asc_dvc->carr_freelist = (ADV_CARR_T *)
15370 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015371
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015372 /*
15373 * The first command completed by the RISC will be placed in
15374 * the stopper.
15375 *
15376 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
15377 * completed the RISC will set the ASC_RQ_STOPPER bit.
15378 */
15379 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015380
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015381 /*
15382 * Set RISC IRQ physical address start value.
15383 */
15384 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
15385 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015386
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015387 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
15388 (ADV_INTR_ENABLE_HOST_INTR |
15389 ADV_INTR_ENABLE_GLOBAL_INTR));
15390 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
15391 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015392
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015393 /* finally, finally, gentlemen, start your engine */
15394 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015396 /*
15397 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
15398 * Resets should be performed. The RISC has to be running
15399 * to issue a SCSI Bus Reset.
15400 */
15401 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
15402 /*
15403 * If the BIOS Signature is present in memory, restore the
15404 * per TID microcode operating variables.
15405 */
15406 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
15407 0x55AA) {
15408 /*
15409 * Restore per TID negotiated values.
15410 */
15411 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15412 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15413 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
15414 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
15415 tagqng_able);
15416 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
15417 AdvWriteByteLram(iop_base,
15418 ASC_MC_NUMBER_OF_MAX_CMD + tid,
15419 max_cmd[tid]);
15420 }
15421 } else {
15422 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
15423 warn_code = ASC_WARN_BUSRESET_ERROR;
15424 }
15425 }
15426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015427
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015428 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015429}
15430
15431/*
15432 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
15433 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
15434 * all of this is done.
15435 *
15436 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
15437 *
15438 * For a non-fatal error return a warning code. If there are no warnings
15439 * then 0 is returned.
15440 *
15441 * Note: Chip is stopped on entry.
15442 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015443static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015444{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015445 AdvPortAddr iop_base;
15446 ushort warn_code;
15447 ADVEEP_3550_CONFIG eep_config;
15448 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015449
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015450 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015451
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015452 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015453
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015454 /*
15455 * Read the board's EEPROM configuration.
15456 *
15457 * Set default values if a bad checksum is found.
15458 */
15459 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
15460 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015461
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015462 /*
15463 * Set EEPROM default values.
15464 */
15465 for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) {
15466 *((uchar *)&eep_config + i) =
15467 *((uchar *)&Default_3550_EEPROM_Config + i);
15468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015469
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015470 /*
15471 * Assume the 6 byte board serial number that was read
15472 * from EEPROM is correct even if the EEPROM checksum
15473 * failed.
15474 */
15475 eep_config.serial_number_word3 =
15476 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015477
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015478 eep_config.serial_number_word2 =
15479 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015480
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015481 eep_config.serial_number_word1 =
15482 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015483
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015484 AdvSet3550EEPConfig(iop_base, &eep_config);
15485 }
15486 /*
15487 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
15488 * EEPROM configuration that was read.
15489 *
15490 * This is the mapping of EEPROM fields to Adv Library fields.
15491 */
15492 asc_dvc->wdtr_able = eep_config.wdtr_able;
15493 asc_dvc->sdtr_able = eep_config.sdtr_able;
15494 asc_dvc->ultra_able = eep_config.ultra_able;
15495 asc_dvc->tagqng_able = eep_config.tagqng_able;
15496 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
15497 asc_dvc->max_host_qng = eep_config.max_host_qng;
15498 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
15499 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
15500 asc_dvc->start_motor = eep_config.start_motor;
15501 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
15502 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
15503 asc_dvc->no_scam = eep_config.scam_tolerant;
15504 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
15505 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
15506 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015507
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015508 /*
15509 * Set the host maximum queuing (max. 253, min. 16) and the per device
15510 * maximum queuing (max. 63, min. 4).
15511 */
15512 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
15513 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15514 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
15515 /* If the value is zero, assume it is uninitialized. */
15516 if (eep_config.max_host_qng == 0) {
15517 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15518 } else {
15519 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
15520 }
15521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015522
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015523 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
15524 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15525 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
15526 /* If the value is zero, assume it is uninitialized. */
15527 if (eep_config.max_dvc_qng == 0) {
15528 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15529 } else {
15530 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
15531 }
15532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015533
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015534 /*
15535 * If 'max_dvc_qng' is greater than 'max_host_qng', then
15536 * set 'max_dvc_qng' to 'max_host_qng'.
15537 */
15538 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
15539 eep_config.max_dvc_qng = eep_config.max_host_qng;
15540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015541
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015542 /*
15543 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
15544 * values based on possibly adjusted EEPROM values.
15545 */
15546 asc_dvc->max_host_qng = eep_config.max_host_qng;
15547 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015548
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015549 /*
15550 * If the EEPROM 'termination' field is set to automatic (0), then set
15551 * the ADV_DVC_CFG 'termination' field to automatic also.
15552 *
15553 * If the termination is specified with a non-zero 'termination'
15554 * value check that a legal value is set and set the ADV_DVC_CFG
15555 * 'termination' field appropriately.
15556 */
15557 if (eep_config.termination == 0) {
15558 asc_dvc->cfg->termination = 0; /* auto termination */
15559 } else {
15560 /* Enable manual control with low off / high off. */
15561 if (eep_config.termination == 1) {
15562 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015563
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015564 /* Enable manual control with low off / high on. */
15565 } else if (eep_config.termination == 2) {
15566 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015567
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015568 /* Enable manual control with low on / high on. */
15569 } else if (eep_config.termination == 3) {
15570 asc_dvc->cfg->termination =
15571 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
15572 } else {
15573 /*
15574 * The EEPROM 'termination' field contains a bad value. Use
15575 * automatic termination instead.
15576 */
15577 asc_dvc->cfg->termination = 0;
15578 warn_code |= ASC_WARN_EEPROM_TERMINATION;
15579 }
15580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015581
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015582 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015583}
15584
15585/*
15586 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
15587 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
15588 * all of this is done.
15589 *
15590 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
15591 *
15592 * For a non-fatal error return a warning code. If there are no warnings
15593 * then 0 is returned.
15594 *
15595 * Note: Chip is stopped on entry.
15596 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015597static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015598{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015599 AdvPortAddr iop_base;
15600 ushort warn_code;
15601 ADVEEP_38C0800_CONFIG eep_config;
15602 int i;
15603 uchar tid, termination;
15604 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015605
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015606 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015607
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015608 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015609
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015610 /*
15611 * Read the board's EEPROM configuration.
15612 *
15613 * Set default values if a bad checksum is found.
15614 */
15615 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
15616 eep_config.check_sum) {
15617 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015618
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015619 /*
15620 * Set EEPROM default values.
15621 */
15622 for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) {
15623 *((uchar *)&eep_config + i) =
15624 *((uchar *)&Default_38C0800_EEPROM_Config + i);
15625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015626
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015627 /*
15628 * Assume the 6 byte board serial number that was read
15629 * from EEPROM is correct even if the EEPROM checksum
15630 * failed.
15631 */
15632 eep_config.serial_number_word3 =
15633 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015634
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015635 eep_config.serial_number_word2 =
15636 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015637
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015638 eep_config.serial_number_word1 =
15639 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015641 AdvSet38C0800EEPConfig(iop_base, &eep_config);
15642 }
15643 /*
15644 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
15645 * EEPROM configuration that was read.
15646 *
15647 * This is the mapping of EEPROM fields to Adv Library fields.
15648 */
15649 asc_dvc->wdtr_able = eep_config.wdtr_able;
15650 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
15651 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
15652 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
15653 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
15654 asc_dvc->tagqng_able = eep_config.tagqng_able;
15655 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
15656 asc_dvc->max_host_qng = eep_config.max_host_qng;
15657 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
15658 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
15659 asc_dvc->start_motor = eep_config.start_motor;
15660 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
15661 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
15662 asc_dvc->no_scam = eep_config.scam_tolerant;
15663 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
15664 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
15665 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015666
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015667 /*
15668 * For every Target ID if any of its 'sdtr_speed[1234]' bits
15669 * are set, then set an 'sdtr_able' bit for it.
15670 */
15671 asc_dvc->sdtr_able = 0;
15672 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
15673 if (tid == 0) {
15674 sdtr_speed = asc_dvc->sdtr_speed1;
15675 } else if (tid == 4) {
15676 sdtr_speed = asc_dvc->sdtr_speed2;
15677 } else if (tid == 8) {
15678 sdtr_speed = asc_dvc->sdtr_speed3;
15679 } else if (tid == 12) {
15680 sdtr_speed = asc_dvc->sdtr_speed4;
15681 }
15682 if (sdtr_speed & ADV_MAX_TID) {
15683 asc_dvc->sdtr_able |= (1 << tid);
15684 }
15685 sdtr_speed >>= 4;
15686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015687
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015688 /*
15689 * Set the host maximum queuing (max. 253, min. 16) and the per device
15690 * maximum queuing (max. 63, min. 4).
15691 */
15692 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
15693 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15694 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
15695 /* If the value is zero, assume it is uninitialized. */
15696 if (eep_config.max_host_qng == 0) {
15697 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15698 } else {
15699 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
15700 }
15701 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015702
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015703 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
15704 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15705 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
15706 /* If the value is zero, assume it is uninitialized. */
15707 if (eep_config.max_dvc_qng == 0) {
15708 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15709 } else {
15710 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
15711 }
15712 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015713
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015714 /*
15715 * If 'max_dvc_qng' is greater than 'max_host_qng', then
15716 * set 'max_dvc_qng' to 'max_host_qng'.
15717 */
15718 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
15719 eep_config.max_dvc_qng = eep_config.max_host_qng;
15720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015721
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015722 /*
15723 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
15724 * values based on possibly adjusted EEPROM values.
15725 */
15726 asc_dvc->max_host_qng = eep_config.max_host_qng;
15727 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015728
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015729 /*
15730 * If the EEPROM 'termination' field is set to automatic (0), then set
15731 * the ADV_DVC_CFG 'termination' field to automatic also.
15732 *
15733 * If the termination is specified with a non-zero 'termination'
15734 * value check that a legal value is set and set the ADV_DVC_CFG
15735 * 'termination' field appropriately.
15736 */
15737 if (eep_config.termination_se == 0) {
15738 termination = 0; /* auto termination for SE */
15739 } else {
15740 /* Enable manual control with low off / high off. */
15741 if (eep_config.termination_se == 1) {
15742 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015743
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015744 /* Enable manual control with low off / high on. */
15745 } else if (eep_config.termination_se == 2) {
15746 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015747
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015748 /* Enable manual control with low on / high on. */
15749 } else if (eep_config.termination_se == 3) {
15750 termination = TERM_SE;
15751 } else {
15752 /*
15753 * The EEPROM 'termination_se' field contains a bad value.
15754 * Use automatic termination instead.
15755 */
15756 termination = 0;
15757 warn_code |= ASC_WARN_EEPROM_TERMINATION;
15758 }
15759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015760
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015761 if (eep_config.termination_lvd == 0) {
15762 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
15763 } else {
15764 /* Enable manual control with low off / high off. */
15765 if (eep_config.termination_lvd == 1) {
15766 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015767
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015768 /* Enable manual control with low off / high on. */
15769 } else if (eep_config.termination_lvd == 2) {
15770 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015772 /* Enable manual control with low on / high on. */
15773 } else if (eep_config.termination_lvd == 3) {
15774 asc_dvc->cfg->termination = termination | TERM_LVD;
15775 } else {
15776 /*
15777 * The EEPROM 'termination_lvd' field contains a bad value.
15778 * Use automatic termination instead.
15779 */
15780 asc_dvc->cfg->termination = termination;
15781 warn_code |= ASC_WARN_EEPROM_TERMINATION;
15782 }
15783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015784
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015785 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015786}
15787
15788/*
15789 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
15790 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
15791 * all of this is done.
15792 *
15793 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
15794 *
15795 * For a non-fatal error return a warning code. If there are no warnings
15796 * then 0 is returned.
15797 *
15798 * Note: Chip is stopped on entry.
15799 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015800static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015801{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015802 AdvPortAddr iop_base;
15803 ushort warn_code;
15804 ADVEEP_38C1600_CONFIG eep_config;
15805 int i;
15806 uchar tid, termination;
15807 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015808
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015809 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015810
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015811 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015812
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015813 /*
15814 * Read the board's EEPROM configuration.
15815 *
15816 * Set default values if a bad checksum is found.
15817 */
15818 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
15819 eep_config.check_sum) {
15820 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015821
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015822 /*
15823 * Set EEPROM default values.
15824 */
15825 for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) {
15826 if (i == 1
15827 && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) !=
15828 0) {
15829 /*
15830 * Set Function 1 EEPROM Word 0 MSB
15831 *
15832 * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11)
15833 * EEPROM bits.
15834 *
15835 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and
15836 * old Mac system booting problem. The Expansion ROM must
15837 * be disabled in Function 1 for these systems.
15838 *
15839 */
15840 *((uchar *)&eep_config + i) =
15841 ((*
15842 ((uchar *)&Default_38C1600_EEPROM_Config
15843 +
15844 i)) &
15845 (~
15846 (((ADV_EEPROM_BIOS_ENABLE |
15847 ADV_EEPROM_INTAB) >> 8) & 0xFF)));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015848
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015849 /*
15850 * Set the INTAB (bit 11) if the GPIO 0 input indicates
15851 * the Function 1 interrupt line is wired to INTA.
15852 *
15853 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
15854 * 1 - Function 1 interrupt line wired to INT A.
15855 * 0 - Function 1 interrupt line wired to INT B.
15856 *
15857 * Note: Adapter boards always have Function 0 wired to INTA.
15858 * Put all 5 GPIO bits in input mode and then read
15859 * their input values.
15860 */
15861 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL,
15862 0);
15863 if (AdvReadByteRegister
15864 (iop_base, IOPB_GPIO_DATA) & 0x01) {
15865 /* Function 1 interrupt wired to INTA; Set EEPROM bit. */
15866 *((uchar *)&eep_config + i) |=
15867 ((ADV_EEPROM_INTAB >> 8) & 0xFF);
15868 }
15869 } else {
15870 *((uchar *)&eep_config + i) =
15871 *((uchar *)&Default_38C1600_EEPROM_Config
15872 + i);
15873 }
15874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015875
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015876 /*
15877 * Assume the 6 byte board serial number that was read
15878 * from EEPROM is correct even if the EEPROM checksum
15879 * failed.
15880 */
15881 eep_config.serial_number_word3 =
15882 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015883
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015884 eep_config.serial_number_word2 =
15885 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015887 eep_config.serial_number_word1 =
15888 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015889
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015890 AdvSet38C1600EEPConfig(iop_base, &eep_config);
15891 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015892
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015893 /*
15894 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
15895 * EEPROM configuration that was read.
15896 *
15897 * This is the mapping of EEPROM fields to Adv Library fields.
15898 */
15899 asc_dvc->wdtr_able = eep_config.wdtr_able;
15900 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
15901 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
15902 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
15903 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
15904 asc_dvc->ppr_able = 0;
15905 asc_dvc->tagqng_able = eep_config.tagqng_able;
15906 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
15907 asc_dvc->max_host_qng = eep_config.max_host_qng;
15908 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
15909 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
15910 asc_dvc->start_motor = eep_config.start_motor;
15911 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
15912 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
15913 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015914
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015915 /*
15916 * For every Target ID if any of its 'sdtr_speed[1234]' bits
15917 * are set, then set an 'sdtr_able' bit for it.
15918 */
15919 asc_dvc->sdtr_able = 0;
15920 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
15921 if (tid == 0) {
15922 sdtr_speed = asc_dvc->sdtr_speed1;
15923 } else if (tid == 4) {
15924 sdtr_speed = asc_dvc->sdtr_speed2;
15925 } else if (tid == 8) {
15926 sdtr_speed = asc_dvc->sdtr_speed3;
15927 } else if (tid == 12) {
15928 sdtr_speed = asc_dvc->sdtr_speed4;
15929 }
15930 if (sdtr_speed & ASC_MAX_TID) {
15931 asc_dvc->sdtr_able |= (1 << tid);
15932 }
15933 sdtr_speed >>= 4;
15934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015935
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015936 /*
15937 * Set the host maximum queuing (max. 253, min. 16) and the per device
15938 * maximum queuing (max. 63, min. 4).
15939 */
15940 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
15941 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15942 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
15943 /* If the value is zero, assume it is uninitialized. */
15944 if (eep_config.max_host_qng == 0) {
15945 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15946 } else {
15947 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
15948 }
15949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015950
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015951 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
15952 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15953 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
15954 /* If the value is zero, assume it is uninitialized. */
15955 if (eep_config.max_dvc_qng == 0) {
15956 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15957 } else {
15958 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
15959 }
15960 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015961
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015962 /*
15963 * If 'max_dvc_qng' is greater than 'max_host_qng', then
15964 * set 'max_dvc_qng' to 'max_host_qng'.
15965 */
15966 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
15967 eep_config.max_dvc_qng = eep_config.max_host_qng;
15968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015969
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015970 /*
15971 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
15972 * values based on possibly adjusted EEPROM values.
15973 */
15974 asc_dvc->max_host_qng = eep_config.max_host_qng;
15975 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015976
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015977 /*
15978 * If the EEPROM 'termination' field is set to automatic (0), then set
15979 * the ASC_DVC_CFG 'termination' field to automatic also.
15980 *
15981 * If the termination is specified with a non-zero 'termination'
15982 * value check that a legal value is set and set the ASC_DVC_CFG
15983 * 'termination' field appropriately.
15984 */
15985 if (eep_config.termination_se == 0) {
15986 termination = 0; /* auto termination for SE */
15987 } else {
15988 /* Enable manual control with low off / high off. */
15989 if (eep_config.termination_se == 1) {
15990 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015991
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015992 /* Enable manual control with low off / high on. */
15993 } else if (eep_config.termination_se == 2) {
15994 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015995
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015996 /* Enable manual control with low on / high on. */
15997 } else if (eep_config.termination_se == 3) {
15998 termination = TERM_SE;
15999 } else {
16000 /*
16001 * The EEPROM 'termination_se' field contains a bad value.
16002 * Use automatic termination instead.
16003 */
16004 termination = 0;
16005 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16006 }
16007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016008
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016009 if (eep_config.termination_lvd == 0) {
16010 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
16011 } else {
16012 /* Enable manual control with low off / high off. */
16013 if (eep_config.termination_lvd == 1) {
16014 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016015
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016016 /* Enable manual control with low off / high on. */
16017 } else if (eep_config.termination_lvd == 2) {
16018 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016019
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016020 /* Enable manual control with low on / high on. */
16021 } else if (eep_config.termination_lvd == 3) {
16022 asc_dvc->cfg->termination = termination | TERM_LVD;
16023 } else {
16024 /*
16025 * The EEPROM 'termination_lvd' field contains a bad value.
16026 * Use automatic termination instead.
16027 */
16028 asc_dvc->cfg->termination = termination;
16029 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16030 }
16031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016032
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016033 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016034}
16035
16036/*
16037 * Read EEPROM configuration into the specified buffer.
16038 *
16039 * Return a checksum based on the EEPROM configuration read.
16040 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016041static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070016042AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
16043{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016044 ushort wval, chksum;
16045 ushort *wbuf;
16046 int eep_addr;
16047 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016049 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
16050 wbuf = (ushort *)cfg_buf;
16051 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016052
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016053 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16054 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16055 wval = AdvReadEEPWord(iop_base, eep_addr);
16056 chksum += wval; /* Checksum is calculated from word values. */
16057 if (*charfields++) {
16058 *wbuf = le16_to_cpu(wval);
16059 } else {
16060 *wbuf = wval;
16061 }
16062 }
16063 /* Read checksum word. */
16064 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16065 wbuf++;
16066 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016067
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016068 /* Read rest of EEPROM not covered by the checksum. */
16069 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16070 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16071 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16072 if (*charfields++) {
16073 *wbuf = le16_to_cpu(*wbuf);
16074 }
16075 }
16076 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016077}
16078
16079/*
16080 * Read EEPROM configuration into the specified buffer.
16081 *
16082 * Return a checksum based on the EEPROM configuration read.
16083 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016084static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016085AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016086{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016087 ushort wval, chksum;
16088 ushort *wbuf;
16089 int eep_addr;
16090 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016091
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016092 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
16093 wbuf = (ushort *)cfg_buf;
16094 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016095
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016096 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16097 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16098 wval = AdvReadEEPWord(iop_base, eep_addr);
16099 chksum += wval; /* Checksum is calculated from word values. */
16100 if (*charfields++) {
16101 *wbuf = le16_to_cpu(wval);
16102 } else {
16103 *wbuf = wval;
16104 }
16105 }
16106 /* Read checksum word. */
16107 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16108 wbuf++;
16109 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016111 /* Read rest of EEPROM not covered by the checksum. */
16112 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16113 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16114 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16115 if (*charfields++) {
16116 *wbuf = le16_to_cpu(*wbuf);
16117 }
16118 }
16119 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016120}
16121
16122/*
16123 * Read EEPROM configuration into the specified buffer.
16124 *
16125 * Return a checksum based on the EEPROM configuration read.
16126 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016127static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016128AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016129{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016130 ushort wval, chksum;
16131 ushort *wbuf;
16132 int eep_addr;
16133 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016134
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016135 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
16136 wbuf = (ushort *)cfg_buf;
16137 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016138
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016139 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16140 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16141 wval = AdvReadEEPWord(iop_base, eep_addr);
16142 chksum += wval; /* Checksum is calculated from word values. */
16143 if (*charfields++) {
16144 *wbuf = le16_to_cpu(wval);
16145 } else {
16146 *wbuf = wval;
16147 }
16148 }
16149 /* Read checksum word. */
16150 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16151 wbuf++;
16152 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016153
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016154 /* Read rest of EEPROM not covered by the checksum. */
16155 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16156 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16157 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16158 if (*charfields++) {
16159 *wbuf = le16_to_cpu(*wbuf);
16160 }
16161 }
16162 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016163}
16164
16165/*
16166 * Read the EEPROM from specified location
16167 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016168static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016169{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016170 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16171 ASC_EEP_CMD_READ | eep_word_addr);
16172 AdvWaitEEPCmd(iop_base);
16173 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016174}
16175
16176/*
16177 * Wait for EEPROM command to complete
16178 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016179static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016180{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016181 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016182
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016183 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
16184 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
16185 ASC_EEP_CMD_DONE) {
16186 break;
16187 }
16188 DvcSleepMilliSecond(1);
16189 }
16190 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
16191 0) {
16192 ASC_ASSERT(0);
16193 }
16194 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016195}
16196
16197/*
16198 * Write the EEPROM from 'cfg_buf'.
16199 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016200void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070016201AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
16202{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016203 ushort *wbuf;
16204 ushort addr, chksum;
16205 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016206
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016207 wbuf = (ushort *)cfg_buf;
16208 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
16209 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016210
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016211 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16212 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016213
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016214 /*
16215 * Write EEPROM from word 0 to word 20.
16216 */
16217 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16218 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16219 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016220
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016221 if (*charfields++) {
16222 word = cpu_to_le16(*wbuf);
16223 } else {
16224 word = *wbuf;
16225 }
16226 chksum += *wbuf; /* Checksum is calculated from word values. */
16227 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16228 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16229 ASC_EEP_CMD_WRITE | addr);
16230 AdvWaitEEPCmd(iop_base);
16231 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016233
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016234 /*
16235 * Write EEPROM checksum at word 21.
16236 */
16237 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16238 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16239 AdvWaitEEPCmd(iop_base);
16240 wbuf++;
16241 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016242
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016243 /*
16244 * Write EEPROM OEM name at words 22 to 29.
16245 */
16246 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16247 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16248 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016249
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016250 if (*charfields++) {
16251 word = cpu_to_le16(*wbuf);
16252 } else {
16253 word = *wbuf;
16254 }
16255 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16256 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16257 ASC_EEP_CMD_WRITE | addr);
16258 AdvWaitEEPCmd(iop_base);
16259 }
16260 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16261 AdvWaitEEPCmd(iop_base);
16262 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016263}
16264
16265/*
16266 * Write the EEPROM from 'cfg_buf'.
16267 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016268void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016269AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016270{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016271 ushort *wbuf;
16272 ushort *charfields;
16273 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016274
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016275 wbuf = (ushort *)cfg_buf;
16276 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
16277 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016278
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016279 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16280 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016281
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016282 /*
16283 * Write EEPROM from word 0 to word 20.
16284 */
16285 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16286 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16287 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016288
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016289 if (*charfields++) {
16290 word = cpu_to_le16(*wbuf);
16291 } else {
16292 word = *wbuf;
16293 }
16294 chksum += *wbuf; /* Checksum is calculated from word values. */
16295 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16296 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16297 ASC_EEP_CMD_WRITE | addr);
16298 AdvWaitEEPCmd(iop_base);
16299 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016301
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016302 /*
16303 * Write EEPROM checksum at word 21.
16304 */
16305 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16306 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16307 AdvWaitEEPCmd(iop_base);
16308 wbuf++;
16309 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016310
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016311 /*
16312 * Write EEPROM OEM name at words 22 to 29.
16313 */
16314 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16315 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16316 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016317
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016318 if (*charfields++) {
16319 word = cpu_to_le16(*wbuf);
16320 } else {
16321 word = *wbuf;
16322 }
16323 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16324 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16325 ASC_EEP_CMD_WRITE | addr);
16326 AdvWaitEEPCmd(iop_base);
16327 }
16328 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16329 AdvWaitEEPCmd(iop_base);
16330 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016331}
16332
16333/*
16334 * Write the EEPROM from 'cfg_buf'.
16335 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016336void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016337AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016338{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016339 ushort *wbuf;
16340 ushort *charfields;
16341 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016342
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016343 wbuf = (ushort *)cfg_buf;
16344 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
16345 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016346
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016347 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16348 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016349
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016350 /*
16351 * Write EEPROM from word 0 to word 20.
16352 */
16353 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16354 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16355 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016356
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016357 if (*charfields++) {
16358 word = cpu_to_le16(*wbuf);
16359 } else {
16360 word = *wbuf;
16361 }
16362 chksum += *wbuf; /* Checksum is calculated from word values. */
16363 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16364 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16365 ASC_EEP_CMD_WRITE | addr);
16366 AdvWaitEEPCmd(iop_base);
16367 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016369
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016370 /*
16371 * Write EEPROM checksum at word 21.
16372 */
16373 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16374 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16375 AdvWaitEEPCmd(iop_base);
16376 wbuf++;
16377 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016378
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016379 /*
16380 * Write EEPROM OEM name at words 22 to 29.
16381 */
16382 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16383 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16384 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016385
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016386 if (*charfields++) {
16387 word = cpu_to_le16(*wbuf);
16388 } else {
16389 word = *wbuf;
16390 }
16391 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16392 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16393 ASC_EEP_CMD_WRITE | addr);
16394 AdvWaitEEPCmd(iop_base);
16395 }
16396 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16397 AdvWaitEEPCmd(iop_base);
16398 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016399}
16400
16401/* a_advlib.c */
16402/*
16403 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
16404 *
16405 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
16406 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
16407 * RISC to notify it a new command is ready to be executed.
16408 *
16409 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
16410 * set to SCSI_MAX_RETRY.
16411 *
16412 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
16413 * for DMA addresses or math operations are byte swapped to little-endian
16414 * order.
16415 *
16416 * Return:
16417 * ADV_SUCCESS(1) - The request was successfully queued.
16418 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
16419 * request completes.
16420 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
16421 * host IC error.
16422 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016423static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016424{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016425 ulong last_int_level;
16426 AdvPortAddr iop_base;
16427 ADV_DCNT req_size;
16428 ADV_PADDR req_paddr;
16429 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016430
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016431 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070016432
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016433 /*
16434 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
16435 */
16436 if (scsiq->target_id > ADV_MAX_TID) {
16437 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
16438 scsiq->done_status = QD_WITH_ERROR;
16439 return ADV_ERROR;
16440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016442 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016443
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016444 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070016445
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016446 /*
16447 * Allocate a carrier ensuring at least one carrier always
16448 * remains on the freelist and initialize fields.
16449 */
16450 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
16451 DvcLeaveCritical(last_int_level);
16452 return ADV_BUSY;
16453 }
16454 asc_dvc->carr_freelist = (ADV_CARR_T *)
16455 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
16456 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016457
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016458 /*
16459 * Set the carrier to be a stopper by setting 'next_vpa'
16460 * to the stopper value. The current stopper will be changed
16461 * below to point to the new stopper.
16462 */
16463 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016464
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016465 /*
16466 * Clear the ADV_SCSI_REQ_Q done flag.
16467 */
16468 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016469
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016470 req_size = sizeof(ADV_SCSI_REQ_Q);
16471 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
16472 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016473
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016474 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
16475 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016476
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016477 /* Wait for assertion before making little-endian */
16478 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016479
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016480 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
16481 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
16482 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016483
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016484 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
16485 /*
16486 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
16487 * order during initialization.
16488 */
16489 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016490
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016491 /*
16492 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
16493 * the microcode. The newly allocated stopper will become the new
16494 * stopper.
16495 */
16496 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016497
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016498 /*
16499 * Set the 'next_vpa' pointer for the old stopper to be the
16500 * physical address of the new stopper. The RISC can only
16501 * follow physical addresses.
16502 */
16503 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016504
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016505 /*
16506 * Set the host adapter stopper pointer to point to the new carrier.
16507 */
16508 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016510 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
16511 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
16512 /*
16513 * Tickle the RISC to tell it to read its Command Queue Head pointer.
16514 */
16515 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
16516 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
16517 /*
16518 * Clear the tickle value. In the ASC-3550 the RISC flag
16519 * command 'clr_tickle_a' does not work unless the host
16520 * value is cleared.
16521 */
16522 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
16523 ADV_TICKLE_NOP);
16524 }
16525 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
16526 /*
16527 * Notify the RISC a carrier is ready by writing the physical
16528 * address of the new carrier stopper to the COMMA register.
16529 */
16530 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
16531 le32_to_cpu(new_carrp->carr_pa));
16532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016533
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016534 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016535
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016536 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016537}
16538
16539/*
16540 * Reset SCSI Bus and purge all outstanding requests.
16541 *
16542 * Return Value:
16543 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
16544 * ADV_FALSE(0) - Microcode command failed.
16545 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
16546 * may be hung which requires driver recovery.
16547 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016548static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016549{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016550 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016551
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016552 /*
16553 * Send the SCSI Bus Reset idle start idle command which asserts
16554 * the SCSI Bus Reset signal.
16555 */
16556 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
16557 if (status != ADV_TRUE) {
16558 return status;
16559 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016560
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016561 /*
16562 * Delay for the specified SCSI Bus Reset hold time.
16563 *
16564 * The hold time delay is done on the host because the RISC has no
16565 * microsecond accurate timer.
16566 */
16567 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016568
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016569 /*
16570 * Send the SCSI Bus Reset end idle command which de-asserts
16571 * the SCSI Bus Reset signal and purges any pending requests.
16572 */
16573 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
16574 if (status != ADV_TRUE) {
16575 return status;
16576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016577
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016578 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016579
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016580 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016581}
16582
16583/*
16584 * Reset chip and SCSI Bus.
16585 *
16586 * Return Value:
16587 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
16588 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
16589 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016590static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016591{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016592 int status;
16593 ushort wdtr_able, sdtr_able, tagqng_able;
16594 ushort ppr_able = 0;
16595 uchar tid, max_cmd[ADV_MAX_TID + 1];
16596 AdvPortAddr iop_base;
16597 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016598
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016599 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016601 /*
16602 * Save current per TID negotiated values.
16603 */
16604 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16605 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16606 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
16607 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
16608 }
16609 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
16610 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
16611 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
16612 max_cmd[tid]);
16613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016614
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016615 /*
16616 * Force the AdvInitAsc3550/38C0800Driver() function to
16617 * perform a SCSI Bus Reset by clearing the BIOS signature word.
16618 * The initialization functions assumes a SCSI Bus Reset is not
16619 * needed if the BIOS signature word is present.
16620 */
16621 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
16622 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016623
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016624 /*
16625 * Stop chip and reset it.
16626 */
16627 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
16628 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
16629 DvcSleepMilliSecond(100);
16630 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
16631 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016632
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016633 /*
16634 * Reset Adv Library error code, if any, and try
16635 * re-initializing the chip.
16636 */
16637 asc_dvc->err_code = 0;
16638 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
16639 status = AdvInitAsc38C1600Driver(asc_dvc);
16640 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
16641 status = AdvInitAsc38C0800Driver(asc_dvc);
16642 } else {
16643 status = AdvInitAsc3550Driver(asc_dvc);
16644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016645
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016646 /* Translate initialization return value to status value. */
16647 if (status == 0) {
16648 status = ADV_TRUE;
16649 } else {
16650 status = ADV_FALSE;
16651 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016652
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016653 /*
16654 * Restore the BIOS signature word.
16655 */
16656 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016657
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016658 /*
16659 * Restore per TID negotiated values.
16660 */
16661 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16662 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16663 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
16664 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
16665 }
16666 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
16667 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
16668 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
16669 max_cmd[tid]);
16670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016671
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016672 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016673}
16674
16675/*
16676 * Adv Library Interrupt Service Routine
16677 *
16678 * This function is called by a driver's interrupt service routine.
16679 * The function disables and re-enables interrupts.
16680 *
16681 * When a microcode idle command is completed, the ADV_DVC_VAR
16682 * 'idle_cmd_done' field is set to ADV_TRUE.
16683 *
16684 * Note: AdvISR() can be called when interrupts are disabled or even
16685 * when there is no hardware interrupt condition present. It will
16686 * always check for completed idle commands and microcode requests.
16687 * This is an important feature that shouldn't be changed because it
16688 * allows commands to be completed from polling mode loops.
16689 *
16690 * Return:
16691 * ADV_TRUE(1) - interrupt was pending
16692 * ADV_FALSE(0) - no interrupt was pending
16693 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016694static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016695{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016696 AdvPortAddr iop_base;
16697 uchar int_stat;
16698 ushort target_bit;
16699 ADV_CARR_T *free_carrp;
16700 ADV_VADDR irq_next_vpa;
16701 int flags;
16702 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016703
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016704 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070016705
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016706 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016707
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016708 /* Reading the register clears the interrupt. */
16709 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016710
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016711 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
16712 ADV_INTR_STATUS_INTRC)) == 0) {
16713 DvcLeaveCritical(flags);
16714 return ADV_FALSE;
16715 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016716
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016717 /*
16718 * Notify the driver of an asynchronous microcode condition by
Matthew Wilcox895d6b42007-07-26 11:57:06 -040016719 * calling the adv_async_callback function. The function
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016720 * is passed the microcode ASC_MC_INTRB_CODE byte value.
16721 */
16722 if (int_stat & ADV_INTR_STATUS_INTRB) {
16723 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016724
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016725 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016726
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016727 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
16728 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
16729 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
16730 asc_dvc->carr_pending_cnt != 0) {
16731 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
16732 ADV_TICKLE_A);
16733 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
16734 AdvWriteByteRegister(iop_base,
16735 IOPB_TICKLE,
16736 ADV_TICKLE_NOP);
16737 }
16738 }
16739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016740
Matthew Wilcox895d6b42007-07-26 11:57:06 -040016741 adv_async_callback(asc_dvc, intrb_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016742 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016743
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016744 /*
16745 * Check if the IRQ stopper carrier contains a completed request.
16746 */
16747 while (((irq_next_vpa =
16748 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
16749 /*
16750 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
16751 * The RISC will have set 'areq_vpa' to a virtual address.
16752 *
16753 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
16754 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
16755 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
16756 * in AdvExeScsiQueue().
16757 */
16758 scsiq = (ADV_SCSI_REQ_Q *)
16759 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016760
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016761 /*
16762 * Request finished with good status and the queue was not
16763 * DMAed to host memory by the firmware. Set all status fields
16764 * to indicate good status.
16765 */
16766 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
16767 scsiq->done_status = QD_NO_ERROR;
16768 scsiq->host_status = scsiq->scsi_status = 0;
16769 scsiq->data_cnt = 0L;
16770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016772 /*
16773 * Advance the stopper pointer to the next carrier
16774 * ignoring the lower four bits. Free the previous
16775 * stopper carrier.
16776 */
16777 free_carrp = asc_dvc->irq_sp;
16778 asc_dvc->irq_sp = (ADV_CARR_T *)
16779 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016780
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016781 free_carrp->next_vpa =
16782 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
16783 asc_dvc->carr_freelist = free_carrp;
16784 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016785
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016786 ASC_ASSERT(scsiq != NULL);
16787 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016788
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016789 /*
16790 * Clear request microcode control flag.
16791 */
16792 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016793
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016794 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016795 * Notify the driver of the completed request by passing
16796 * the ADV_SCSI_REQ_Q pointer to its callback function.
16797 */
16798 scsiq->a_flag |= ADV_SCSIQ_DONE;
Matthew Wilcox895d6b42007-07-26 11:57:06 -040016799 adv_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016800 /*
16801 * Note: After the driver callback function is called, 'scsiq'
16802 * can no longer be referenced.
16803 *
16804 * Fall through and continue processing other completed
16805 * requests...
16806 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070016807
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016808 /*
16809 * Disable interrupts again in case the driver inadvertently
16810 * enabled interrupts in its callback function.
16811 *
16812 * The DvcEnterCritical() return value is ignored, because
16813 * the 'flags' saved when AdvISR() was first entered will be
16814 * used to restore the interrupt flag on exit.
16815 */
16816 (void)DvcEnterCritical();
16817 }
16818 DvcLeaveCritical(flags);
16819 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016820}
16821
16822/*
16823 * Send an idle command to the chip and wait for completion.
16824 *
16825 * Command completion is polled for once per microsecond.
16826 *
16827 * The function can be called from anywhere including an interrupt handler.
16828 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
16829 * functions to prevent reentrancy.
16830 *
16831 * Return Values:
16832 * ADV_TRUE - command completed successfully
16833 * ADV_FALSE - command failed
16834 * ADV_ERROR - command timed out
16835 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016836static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070016837AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016838 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016839{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016840 ulong last_int_level;
16841 int result;
16842 ADV_DCNT i, j;
16843 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016844
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016845 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070016846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016847 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016848
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016849 /*
16850 * Clear the idle command status which is set by the microcode
16851 * to a non-zero value to indicate when the command is completed.
16852 * The non-zero result is one of the IDLE_CMD_STATUS_* values
16853 * defined in a_advlib.h.
16854 */
16855 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016857 /*
16858 * Write the idle command value after the idle command parameter
16859 * has been written to avoid a race condition. If the order is not
16860 * followed, the microcode may process the idle command before the
16861 * parameters have been written to LRAM.
16862 */
16863 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
16864 cpu_to_le32(idle_cmd_parameter));
16865 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016866
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016867 /*
16868 * Tickle the RISC to tell it to process the idle command.
16869 */
16870 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
16871 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
16872 /*
16873 * Clear the tickle value. In the ASC-3550 the RISC flag
16874 * command 'clr_tickle_b' does not work unless the host
16875 * value is cleared.
16876 */
16877 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
16878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016879
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016880 /* Wait for up to 100 millisecond for the idle command to timeout. */
16881 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
16882 /* Poll once each microsecond for command completion. */
16883 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
16884 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
16885 result);
16886 if (result != 0) {
16887 DvcLeaveCritical(last_int_level);
16888 return result;
16889 }
16890 DvcDelayMicroSecond(asc_dvc, (ushort)1);
16891 }
16892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016893
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016894 ASC_ASSERT(0); /* The idle command should never timeout. */
16895 DvcLeaveCritical(last_int_level);
16896 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016897}
16898
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060016899static int __devinit
16900advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
16901{
16902 int req_cnt = 0;
16903 adv_req_t *reqp = NULL;
16904 int sg_cnt = 0;
16905 adv_sgblk_t *sgp;
16906 int warn_code, err_code;
16907
16908 /*
16909 * Allocate buffer carrier structures. The total size
16910 * is about 4 KB, so allocate all at once.
16911 */
16912 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
16913 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
16914
16915 if (!boardp->carrp)
16916 goto kmalloc_failed;
16917
16918 /*
16919 * Allocate up to 'max_host_qng' request structures for the Wide
16920 * board. The total size is about 16 KB, so allocate all at once.
16921 * If the allocation fails decrement and try again.
16922 */
16923 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
16924 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
16925
16926 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
16927 "bytes %lu\n", reqp, req_cnt,
16928 (ulong)sizeof(adv_req_t) * req_cnt);
16929
16930 if (reqp)
16931 break;
16932 }
16933
16934 if (!reqp)
16935 goto kmalloc_failed;
16936
16937 boardp->orig_reqp = reqp;
16938
16939 /*
16940 * Allocate up to ADV_TOT_SG_BLOCK request structures for
16941 * the Wide board. Each structure is about 136 bytes.
16942 */
16943 boardp->adv_sgblkp = NULL;
16944 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
16945 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
16946
16947 if (!sgp)
16948 break;
16949
16950 sgp->next_sgblkp = boardp->adv_sgblkp;
16951 boardp->adv_sgblkp = sgp;
16952
16953 }
16954
16955 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
16956 sg_cnt, sizeof(adv_sgblk_t),
16957 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
16958
16959 if (!boardp->adv_sgblkp)
16960 goto kmalloc_failed;
16961
16962 adv_dvc_varp->carrier_buf = boardp->carrp;
16963
16964 /*
16965 * Point 'adv_reqp' to the request structures and
16966 * link them together.
16967 */
16968 req_cnt--;
16969 reqp[req_cnt].next_reqp = NULL;
16970 for (; req_cnt > 0; req_cnt--) {
16971 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
16972 }
16973 boardp->adv_reqp = &reqp[0];
16974
16975 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
16976 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
16977 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
16978 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
16979 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
16980 "\n");
16981 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
16982 } else {
16983 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
16984 "\n");
16985 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
16986 }
16987 err_code = adv_dvc_varp->err_code;
16988
16989 if (warn_code || err_code) {
16990 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
16991 " error 0x%x\n", boardp->id, warn_code, err_code);
16992 }
16993
16994 goto exit;
16995
16996 kmalloc_failed:
16997 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
16998 "failed\n", boardp->id);
16999 err_code = ADV_ERROR;
17000 exit:
17001 return err_code;
17002}
17003
17004static void advansys_wide_free_mem(asc_board_t *boardp)
17005{
17006 kfree(boardp->carrp);
17007 boardp->carrp = NULL;
17008 kfree(boardp->orig_reqp);
17009 boardp->orig_reqp = boardp->adv_reqp = NULL;
17010 while (boardp->adv_sgblkp) {
17011 adv_sgblk_t *sgp = boardp->adv_sgblkp;
17012 boardp->adv_sgblkp = sgp->next_sgblkp;
17013 kfree(sgp);
17014 }
17015}
17016
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017017static struct Scsi_Host *__devinit
17018advansys_board_found(int iop, struct device *dev, int bus_type)
17019{
17020 struct Scsi_Host *shost;
17021 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
17022 asc_board_t *boardp;
17023 ASC_DVC_VAR *asc_dvc_varp = NULL;
17024 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017025 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017026 int warn_code, err_code;
17027 int ret;
17028
17029 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017030 * Register the adapter, get its configuration, and
17031 * initialize it.
17032 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017033 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
17034 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017035 if (!shost)
17036 return NULL;
17037
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017038 /* Initialize private per board data */
17039 boardp = ASC_BOARDP(shost);
17040 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017041 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017042 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040017043 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017044
17045 /*
17046 * Handle both narrow and wide boards.
17047 *
17048 * If a Wide board was detected, set the board structure
17049 * wide board flag. Set-up the board structure based on
17050 * the board type.
17051 */
17052#ifdef CONFIG_PCI
17053 if (bus_type == ASC_IS_PCI &&
17054 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
17055 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
17056 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
17057 boardp->flags |= ASC_IS_WIDE_BOARD;
17058 }
17059#endif /* CONFIG_PCI */
17060
17061 if (ASC_NARROW_BOARD(boardp)) {
17062 ASC_DBG(1, "advansys_board_found: narrow board\n");
17063 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
17064 asc_dvc_varp->bus_type = bus_type;
17065 asc_dvc_varp->drv_ptr = boardp;
17066 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
17067 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
17068 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017069 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040017070#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017071 ASC_DBG(1, "advansys_board_found: wide board\n");
17072 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
17073 adv_dvc_varp->drv_ptr = boardp;
17074 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017075 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
17076 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
17077 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
17078 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
17079 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
17080 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
17081 } else {
17082 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
17083 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
17084 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017085
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040017086 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
17087 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
17088 boardp->asc_n_io_port);
17089 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017090 ASC_PRINT3
17091 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040017092 boardp->id, pci_resource_start(pdev, 1),
17093 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017094 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017095 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040017096 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060017097 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017098 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017099
17100 /*
17101 * Even though it isn't used to access wide boards, other
17102 * than for the debug line below, save I/O Port address so
17103 * that it can be reported.
17104 */
17105 boardp->ioport = iop;
17106
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040017107 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
17108 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
17109 (ushort)inpw(iop));
17110#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017111 }
17112
17113#ifdef CONFIG_PROC_FS
17114 /*
17115 * Allocate buffer for printing information from
17116 * /proc/scsi/advansys/[0...].
17117 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017118 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
17119 if (!boardp->prtbuf) {
17120 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
17121 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
17122 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017123 }
17124#endif /* CONFIG_PROC_FS */
17125
17126 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017127 /*
17128 * Set the board bus type and PCI IRQ before
17129 * calling AscInitGetConfig().
17130 */
17131 switch (asc_dvc_varp->bus_type) {
17132#ifdef CONFIG_ISA
17133 case ASC_IS_ISA:
17134 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017135 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017136 break;
17137 case ASC_IS_VL:
17138 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017139 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017140 break;
17141 case ASC_IS_EISA:
17142 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017143 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017144 break;
17145#endif /* CONFIG_ISA */
17146#ifdef CONFIG_PCI
17147 case ASC_IS_PCI:
17148 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
17149 asc_dvc_varp->cfg->pci_slot_info =
17150 ASC_PCI_MKID(pdev->bus->number,
17151 PCI_SLOT(pdev->devfn),
17152 PCI_FUNC(pdev->devfn));
17153 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017154 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017155 break;
17156#endif /* CONFIG_PCI */
17157 default:
17158 ASC_PRINT2
17159 ("advansys_board_found: board %d: unknown adapter type: %d\n",
17160 boardp->id, asc_dvc_varp->bus_type);
17161 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017162 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017163 break;
17164 }
17165 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017166 /*
17167 * For Wide boards set PCI information before calling
17168 * AdvInitGetConfig().
17169 */
17170#ifdef CONFIG_PCI
17171 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
17172 adv_dvc_varp->cfg->pci_slot_info =
17173 ASC_PCI_MKID(pdev->bus->number,
17174 PCI_SLOT(pdev->devfn),
17175 PCI_FUNC(pdev->devfn));
17176 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017177 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017178#endif /* CONFIG_PCI */
17179 }
17180
17181 /*
17182 * Read the board configuration.
17183 */
17184 if (ASC_NARROW_BOARD(boardp)) {
17185 /*
17186 * NOTE: AscInitGetConfig() may change the board's
17187 * bus_type value. The bus_type value should no
17188 * longer be used. If the bus_type field must be
17189 * referenced only use the bit-wise AND operator "&".
17190 */
17191 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
17192 switch (ret = AscInitGetConfig(asc_dvc_varp)) {
17193 case 0: /* No error */
17194 break;
17195 case ASC_WARN_IO_PORT_ROTATE:
17196 ASC_PRINT1
17197 ("AscInitGetConfig: board %d: I/O port address modified\n",
17198 boardp->id);
17199 break;
17200 case ASC_WARN_AUTO_CONFIG:
17201 ASC_PRINT1
17202 ("AscInitGetConfig: board %d: I/O port increment switch enabled\n",
17203 boardp->id);
17204 break;
17205 case ASC_WARN_EEPROM_CHKSUM:
17206 ASC_PRINT1
17207 ("AscInitGetConfig: board %d: EEPROM checksum error\n",
17208 boardp->id);
17209 break;
17210 case ASC_WARN_IRQ_MODIFIED:
17211 ASC_PRINT1
17212 ("AscInitGetConfig: board %d: IRQ modified\n",
17213 boardp->id);
17214 break;
17215 case ASC_WARN_CMD_QNG_CONFLICT:
17216 ASC_PRINT1
17217 ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
17218 boardp->id);
17219 break;
17220 default:
17221 ASC_PRINT2
17222 ("AscInitGetConfig: board %d: unknown warning: 0x%x\n",
17223 boardp->id, ret);
17224 break;
17225 }
17226 if ((err_code = asc_dvc_varp->err_code) != 0) {
17227 ASC_PRINT3
17228 ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
17229 boardp->id,
17230 asc_dvc_varp->init_state, asc_dvc_varp->err_code);
17231 }
17232 } else {
17233 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040017234
17235 ret = AdvInitGetConfig(pdev, adv_dvc_varp);
17236 if (ret != 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017237 ASC_PRINT2
17238 ("AdvInitGetConfig: board %d: warning: 0x%x\n",
17239 boardp->id, ret);
17240 }
17241 if ((err_code = adv_dvc_varp->err_code) != 0) {
17242 ASC_PRINT2
17243 ("AdvInitGetConfig: board %d error: err_code 0x%x\n",
17244 boardp->id, adv_dvc_varp->err_code);
17245 }
17246 }
17247
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017248 if (err_code != 0)
17249 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017250
17251 /*
17252 * Save the EEPROM configuration so that it can be displayed
17253 * from /proc/scsi/advansys/[0...].
17254 */
17255 if (ASC_NARROW_BOARD(boardp)) {
17256
17257 ASCEEP_CONFIG *ep;
17258
17259 /*
17260 * Set the adapter's target id bit in the 'init_tidmask' field.
17261 */
17262 boardp->init_tidmask |=
17263 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
17264
17265 /*
17266 * Save EEPROM settings for the board.
17267 */
17268 ep = &boardp->eep_config.asc_eep;
17269
17270 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
17271 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
17272 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
17273 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
17274 ep->start_motor = asc_dvc_varp->start_motor;
17275 ep->cntl = asc_dvc_varp->dvc_cntl;
17276 ep->no_scam = asc_dvc_varp->no_scam;
17277 ep->max_total_qng = asc_dvc_varp->max_total_qng;
17278 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
17279 /* 'max_tag_qng' is set to the same value for every device. */
17280 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
17281 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
17282 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
17283 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
17284 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
17285 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
17286 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
17287
17288 /*
17289 * Modify board configuration.
17290 */
17291 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040017292 switch (ret = AscInitSetConfig(pdev, asc_dvc_varp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017293 case 0: /* No error. */
17294 break;
17295 case ASC_WARN_IO_PORT_ROTATE:
17296 ASC_PRINT1
17297 ("AscInitSetConfig: board %d: I/O port address modified\n",
17298 boardp->id);
17299 break;
17300 case ASC_WARN_AUTO_CONFIG:
17301 ASC_PRINT1
17302 ("AscInitSetConfig: board %d: I/O port increment switch enabled\n",
17303 boardp->id);
17304 break;
17305 case ASC_WARN_EEPROM_CHKSUM:
17306 ASC_PRINT1
17307 ("AscInitSetConfig: board %d: EEPROM checksum error\n",
17308 boardp->id);
17309 break;
17310 case ASC_WARN_IRQ_MODIFIED:
17311 ASC_PRINT1
17312 ("AscInitSetConfig: board %d: IRQ modified\n",
17313 boardp->id);
17314 break;
17315 case ASC_WARN_CMD_QNG_CONFLICT:
17316 ASC_PRINT1
17317 ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
17318 boardp->id);
17319 break;
17320 default:
17321 ASC_PRINT2
17322 ("AscInitSetConfig: board %d: unknown warning: 0x%x\n",
17323 boardp->id, ret);
17324 break;
17325 }
17326 if (asc_dvc_varp->err_code != 0) {
17327 ASC_PRINT3
17328 ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
17329 boardp->id,
17330 asc_dvc_varp->init_state, asc_dvc_varp->err_code);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017331 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017332 }
17333
17334 /*
17335 * Finish initializing the 'Scsi_Host' structure.
17336 */
17337 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
17338 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
17339 shost->irq = asc_dvc_varp->irq_no;
17340 }
17341 } else {
17342 ADVEEP_3550_CONFIG *ep_3550;
17343 ADVEEP_38C0800_CONFIG *ep_38C0800;
17344 ADVEEP_38C1600_CONFIG *ep_38C1600;
17345
17346 /*
17347 * Save Wide EEP Configuration Information.
17348 */
17349 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
17350 ep_3550 = &boardp->eep_config.adv_3550_eep;
17351
17352 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
17353 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
17354 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
17355 ep_3550->termination = adv_dvc_varp->cfg->termination;
17356 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
17357 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
17358 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
17359 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
17360 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
17361 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
17362 ep_3550->start_motor = adv_dvc_varp->start_motor;
17363 ep_3550->scsi_reset_delay =
17364 adv_dvc_varp->scsi_reset_wait;
17365 ep_3550->serial_number_word1 =
17366 adv_dvc_varp->cfg->serial1;
17367 ep_3550->serial_number_word2 =
17368 adv_dvc_varp->cfg->serial2;
17369 ep_3550->serial_number_word3 =
17370 adv_dvc_varp->cfg->serial3;
17371 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
17372 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
17373
17374 ep_38C0800->adapter_scsi_id =
17375 adv_dvc_varp->chip_scsi_id;
17376 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
17377 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
17378 ep_38C0800->termination_lvd =
17379 adv_dvc_varp->cfg->termination;
17380 ep_38C0800->disc_enable =
17381 adv_dvc_varp->cfg->disc_enable;
17382 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
17383 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
17384 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
17385 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
17386 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
17387 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
17388 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
17389 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
17390 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
17391 ep_38C0800->scsi_reset_delay =
17392 adv_dvc_varp->scsi_reset_wait;
17393 ep_38C0800->serial_number_word1 =
17394 adv_dvc_varp->cfg->serial1;
17395 ep_38C0800->serial_number_word2 =
17396 adv_dvc_varp->cfg->serial2;
17397 ep_38C0800->serial_number_word3 =
17398 adv_dvc_varp->cfg->serial3;
17399 } else {
17400 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
17401
17402 ep_38C1600->adapter_scsi_id =
17403 adv_dvc_varp->chip_scsi_id;
17404 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
17405 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
17406 ep_38C1600->termination_lvd =
17407 adv_dvc_varp->cfg->termination;
17408 ep_38C1600->disc_enable =
17409 adv_dvc_varp->cfg->disc_enable;
17410 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
17411 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
17412 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
17413 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
17414 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
17415 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
17416 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
17417 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
17418 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
17419 ep_38C1600->scsi_reset_delay =
17420 adv_dvc_varp->scsi_reset_wait;
17421 ep_38C1600->serial_number_word1 =
17422 adv_dvc_varp->cfg->serial1;
17423 ep_38C1600->serial_number_word2 =
17424 adv_dvc_varp->cfg->serial2;
17425 ep_38C1600->serial_number_word3 =
17426 adv_dvc_varp->cfg->serial3;
17427 }
17428
17429 /*
17430 * Set the adapter's target id bit in the 'init_tidmask' field.
17431 */
17432 boardp->init_tidmask |=
17433 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017434 }
17435
17436 /*
17437 * Channels are numbered beginning with 0. For AdvanSys one host
17438 * structure supports one channel. Multi-channel boards have a
17439 * separate host structure for each channel.
17440 */
17441 shost->max_channel = 0;
17442 if (ASC_NARROW_BOARD(boardp)) {
17443 shost->max_id = ASC_MAX_TID + 1;
17444 shost->max_lun = ASC_MAX_LUN + 1;
17445
17446 shost->io_port = asc_dvc_varp->iop_base;
17447 boardp->asc_n_io_port = ASC_IOADR_GAP;
17448 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
17449
17450 /* Set maximum number of queues the adapter can handle. */
17451 shost->can_queue = asc_dvc_varp->max_total_qng;
17452 } else {
17453 shost->max_id = ADV_MAX_TID + 1;
17454 shost->max_lun = ADV_MAX_LUN + 1;
17455
17456 /*
17457 * Save the I/O Port address and length even though
17458 * I/O ports are not used to access Wide boards.
17459 * Instead the Wide boards are accessed with
17460 * PCI Memory Mapped I/O.
17461 */
17462 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017463
17464 shost->this_id = adv_dvc_varp->chip_scsi_id;
17465
17466 /* Set maximum number of queues the adapter can handle. */
17467 shost->can_queue = adv_dvc_varp->max_host_qng;
17468 }
17469
17470 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017471 * Following v1.3.89, 'cmd_per_lun' is no longer needed
17472 * and should be set to zero.
17473 *
17474 * But because of a bug introduced in v1.3.89 if the driver is
17475 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
17476 * SCSI function 'allocate_device' will panic. To allow the driver
17477 * to work as a module in these kernels set 'cmd_per_lun' to 1.
17478 *
17479 * Note: This is wrong. cmd_per_lun should be set to the depth
17480 * you want on untagged devices always.
17481 #ifdef MODULE
17482 */
17483 shost->cmd_per_lun = 1;
17484/* #else
17485 shost->cmd_per_lun = 0;
17486#endif */
17487
17488 /*
17489 * Set the maximum number of scatter-gather elements the
17490 * adapter can handle.
17491 */
17492 if (ASC_NARROW_BOARD(boardp)) {
17493 /*
17494 * Allow two commands with 'sg_tablesize' scatter-gather
17495 * elements to be executed simultaneously. This value is
17496 * the theoretical hardware limit. It may be decreased
17497 * below.
17498 */
17499 shost->sg_tablesize =
17500 (((asc_dvc_varp->max_total_qng - 2) / 2) *
17501 ASC_SG_LIST_PER_Q) + 1;
17502 } else {
17503 shost->sg_tablesize = ADV_MAX_SG_LIST;
17504 }
17505
17506 /*
17507 * The value of 'sg_tablesize' can not exceed the SCSI
17508 * mid-level driver definition of SG_ALL. SG_ALL also
17509 * must not be exceeded, because it is used to define the
17510 * size of the scatter-gather table in 'struct asc_sg_head'.
17511 */
17512 if (shost->sg_tablesize > SG_ALL) {
17513 shost->sg_tablesize = SG_ALL;
17514 }
17515
17516 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
17517
17518 /* BIOS start address. */
17519 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017520 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
17521 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017522 } else {
17523 /*
17524 * Fill-in BIOS board variables. The Wide BIOS saves
17525 * information in LRAM that is used by the driver.
17526 */
17527 AdvReadWordLram(adv_dvc_varp->iop_base,
17528 BIOS_SIGNATURE, boardp->bios_signature);
17529 AdvReadWordLram(adv_dvc_varp->iop_base,
17530 BIOS_VERSION, boardp->bios_version);
17531 AdvReadWordLram(adv_dvc_varp->iop_base,
17532 BIOS_CODESEG, boardp->bios_codeseg);
17533 AdvReadWordLram(adv_dvc_varp->iop_base,
17534 BIOS_CODELEN, boardp->bios_codelen);
17535
17536 ASC_DBG2(1,
17537 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
17538 boardp->bios_signature, boardp->bios_version);
17539
17540 ASC_DBG2(1,
17541 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
17542 boardp->bios_codeseg, boardp->bios_codelen);
17543
17544 /*
17545 * If the BIOS saved a valid signature, then fill in
17546 * the BIOS code segment base address.
17547 */
17548 if (boardp->bios_signature == 0x55AA) {
17549 /*
17550 * Convert x86 realmode code segment to a linear
17551 * address by shifting left 4.
17552 */
17553 shost->base = ((ulong)boardp->bios_codeseg << 4);
17554 } else {
17555 shost->base = 0;
17556 }
17557 }
17558
17559 /*
17560 * Register Board Resources - I/O Port, DMA, IRQ
17561 */
17562
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017563 /* Register DMA Channel for Narrow boards. */
17564 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
17565#ifdef CONFIG_ISA
17566 if (ASC_NARROW_BOARD(boardp)) {
17567 /* Register DMA channel for ISA bus. */
17568 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
17569 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017570 ret = request_dma(shost->dma_channel, "advansys");
17571 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017572 ASC_PRINT3
17573 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
17574 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060017575 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017576 }
17577 AscEnableIsaDma(shost->dma_channel);
17578 }
17579 }
17580#endif /* CONFIG_ISA */
17581
17582 /* Register IRQ Number. */
17583 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017584
17585 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
17586 "advansys", shost);
17587
17588 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017589 if (ret == -EBUSY) {
17590 ASC_PRINT2
17591 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
17592 boardp->id, shost->irq);
17593 } else if (ret == -EINVAL) {
17594 ASC_PRINT2
17595 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
17596 boardp->id, shost->irq);
17597 } else {
17598 ASC_PRINT3
17599 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
17600 boardp->id, shost->irq, ret);
17601 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017602 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017603 }
17604
17605 /*
17606 * Initialize board RISC chip and enable interrupts.
17607 */
17608 if (ASC_NARROW_BOARD(boardp)) {
17609 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
17610 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
17611 err_code = asc_dvc_varp->err_code;
17612
17613 if (warn_code || err_code) {
17614 ASC_PRINT4
17615 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
17616 boardp->id,
17617 asc_dvc_varp->init_state, warn_code, err_code);
17618 }
17619 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017620 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017621 }
17622
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017623 if (err_code != 0)
17624 goto err_free_wide_mem;
17625
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017626 ASC_DBG_PRT_SCSI_HOST(2, shost);
17627
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017628 ret = scsi_add_host(shost, dev);
17629 if (ret)
17630 goto err_free_wide_mem;
17631
17632 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017633 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017634
17635 err_free_wide_mem:
17636 advansys_wide_free_mem(boardp);
17637 free_irq(shost->irq, shost);
17638 err_free_dma:
17639 if (shost->dma_channel != NO_ISA_DMA)
17640 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017641 err_free_proc:
17642 kfree(boardp->prtbuf);
17643 err_unmap:
17644 if (boardp->ioremap_addr)
17645 iounmap(boardp->ioremap_addr);
17646 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017647 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017648 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017649}
17650
17651/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017652 * advansys_release()
17653 *
17654 * Release resources allocated for a single AdvanSys adapter.
17655 */
17656static int advansys_release(struct Scsi_Host *shost)
17657{
17658 asc_board_t *boardp;
17659
17660 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017661 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017662 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017663 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017664 if (shost->dma_channel != NO_ISA_DMA) {
17665 ASC_DBG(1, "advansys_release: free_dma()\n");
17666 free_dma(shost->dma_channel);
17667 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017668 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017669 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017670 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017671 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017672 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017673 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017674 ASC_DBG(1, "advansys_release: end\n");
17675 return 0;
17676}
17677
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017678static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
17679 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
17680 0x0210, 0x0230, 0x0250, 0x0330
17681};
17682
17683static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
17684{
17685 PortAddr iop_base = _asc_def_iop_base[id];
17686 struct Scsi_Host *shost;
17687
17688 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060017689 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
17690 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017691 return -ENODEV;
17692 }
17693 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017694 if (!AscFindSignature(iop_base))
17695 goto nodev;
17696 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
17697 goto nodev;
17698
17699 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017700 if (!shost)
17701 goto nodev;
17702
17703 dev_set_drvdata(dev, shost);
17704 return 0;
17705
17706 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060017707 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017708 return -ENODEV;
17709}
17710
17711static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
17712{
Matthew Wilcox71f36112007-07-30 08:04:53 -060017713 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017714 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060017715 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017716 return 0;
17717}
17718
17719static struct isa_driver advansys_isa_driver = {
17720 .probe = advansys_isa_probe,
17721 .remove = __devexit_p(advansys_isa_remove),
17722 .driver = {
17723 .owner = THIS_MODULE,
17724 .name = "advansys",
17725 },
17726};
17727
17728static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
17729{
17730 PortAddr iop_base = _asc_def_iop_base[id];
17731 struct Scsi_Host *shost;
17732
17733 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060017734 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
17735 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017736 return -ENODEV;
17737 }
17738 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017739 if (!AscFindSignature(iop_base))
17740 goto nodev;
17741 /*
17742 * I don't think this condition can actually happen, but the old
17743 * driver did it, and the chances of finding a VLB setup in 2007
17744 * to do testing with is slight to none.
17745 */
17746 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
17747 goto nodev;
17748
17749 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017750 if (!shost)
17751 goto nodev;
17752
17753 dev_set_drvdata(dev, shost);
17754 return 0;
17755
17756 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060017757 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017758 return -ENODEV;
17759}
17760
17761static struct isa_driver advansys_vlb_driver = {
17762 .probe = advansys_vlb_probe,
17763 .remove = __devexit_p(advansys_isa_remove),
17764 .driver = {
17765 .owner = THIS_MODULE,
17766 .name = "advansys",
17767 },
17768};
17769
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017770static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
17771 { "ABP7401" },
17772 { "ABP7501" },
17773 { "" }
17774};
17775
17776MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
17777
17778/*
17779 * EISA is a little more tricky than PCI; each EISA device may have two
17780 * channels, and this driver is written to make each channel its own Scsi_Host
17781 */
17782struct eisa_scsi_data {
17783 struct Scsi_Host *host[2];
17784};
17785
17786static int __devinit advansys_eisa_probe(struct device *dev)
17787{
17788 int i, ioport;
17789 int err;
17790 struct eisa_device *edev = to_eisa_device(dev);
17791 struct eisa_scsi_data *data;
17792
17793 err = -ENOMEM;
17794 data = kzalloc(sizeof(*data), GFP_KERNEL);
17795 if (!data)
17796 goto fail;
17797 ioport = edev->base_addr + 0xc30;
17798
17799 err = -ENODEV;
17800 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060017801 if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
17802 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
17803 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017804 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060017805 }
17806 if (!AscFindSignature(ioport)) {
17807 release_region(ioport, ASC_IOADR_GAP);
17808 continue;
17809 }
17810
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017811 /*
17812 * I don't know why we need to do this for EISA chips, but
17813 * not for any others. It looks to be equivalent to
17814 * AscGetChipCfgMsw, but I may have overlooked something,
17815 * so I'm not converting it until I get an EISA board to
17816 * test with.
17817 */
17818 inw(ioport + 4);
17819 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f36112007-07-30 08:04:53 -060017820 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017821 err = 0;
Matthew Wilcox71f36112007-07-30 08:04:53 -060017822 } else {
17823 release_region(ioport, ASC_IOADR_GAP);
17824 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017825 }
17826
17827 if (err) {
17828 kfree(data);
17829 } else {
17830 dev_set_drvdata(dev, data);
17831 }
17832
17833 fail:
17834 return err;
17835}
17836
17837static __devexit int advansys_eisa_remove(struct device *dev)
17838{
17839 int i;
17840 struct eisa_scsi_data *data = dev_get_drvdata(dev);
17841
17842 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060017843 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017844 struct Scsi_Host *shost = data->host[i];
17845 if (!shost)
17846 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060017847 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017848 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060017849 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017850 }
17851
17852 kfree(data);
17853 return 0;
17854}
17855
17856static struct eisa_driver advansys_eisa_driver = {
17857 .id_table = advansys_eisa_table,
17858 .driver = {
17859 .name = "advansys",
17860 .probe = advansys_eisa_probe,
17861 .remove = __devexit_p(advansys_eisa_remove),
17862 }
17863};
17864
Dave Jones2672ea82006-08-02 17:11:49 -040017865/* PCI Devices supported by this driver */
17866static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017867 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
17868 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
17869 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
17870 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
17871 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
17872 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
17873 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
17874 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
17875 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
17876 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
17877 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
17878 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
17879 {}
Dave Jones2672ea82006-08-02 17:11:49 -040017880};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017881
Dave Jones2672ea82006-08-02 17:11:49 -040017882MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017883
Matthew Wilcox9649af32007-07-26 21:51:47 -060017884static void __devinit advansys_set_latency(struct pci_dev *pdev)
17885{
17886 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
17887 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
17888 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
17889 } else {
17890 u8 latency;
17891 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
17892 if (latency < 0x20)
17893 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
17894 }
17895}
17896
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017897static int __devinit
17898advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
17899{
17900 int err, ioport;
17901 struct Scsi_Host *shost;
17902
17903 err = pci_enable_device(pdev);
17904 if (err)
17905 goto fail;
Matthew Wilcox71f36112007-07-30 08:04:53 -060017906 err = pci_request_regions(pdev, "advansys");
17907 if (err)
17908 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060017909 pci_set_master(pdev);
17910 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017911
17912 if (pci_resource_len(pdev, 0) == 0)
17913 goto nodev;
17914
17915 ioport = pci_resource_start(pdev, 0);
17916 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
17917
17918 if (!shost)
17919 goto nodev;
17920
17921 pci_set_drvdata(pdev, shost);
17922 return 0;
17923
17924 nodev:
17925 err = -ENODEV;
Matthew Wilcox71f36112007-07-30 08:04:53 -060017926 pci_release_regions(pdev);
17927 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017928 pci_disable_device(pdev);
17929 fail:
17930 return err;
17931}
17932
17933static void __devexit advansys_pci_remove(struct pci_dev *pdev)
17934{
17935 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060017936 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017937 pci_disable_device(pdev);
17938}
17939
17940static struct pci_driver advansys_pci_driver = {
17941 .name = "advansys",
17942 .id_table = advansys_pci_tbl,
17943 .probe = advansys_pci_probe,
17944 .remove = __devexit_p(advansys_pci_remove),
17945};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040017946
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017947static int __init advansys_init(void)
17948{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017949 int error;
17950
17951 error = isa_register_driver(&advansys_isa_driver,
17952 ASC_IOADR_TABLE_MAX_IX);
17953 if (error)
17954 goto fail;
17955
17956 error = isa_register_driver(&advansys_vlb_driver,
17957 ASC_IOADR_TABLE_MAX_IX);
17958 if (error)
17959 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017960
17961 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017962 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017963 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017964
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017965 error = pci_register_driver(&advansys_pci_driver);
17966 if (error)
17967 goto unregister_eisa;
17968
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017969 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017970
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017971 unregister_eisa:
17972 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017973 unregister_vlb:
17974 isa_unregister_driver(&advansys_vlb_driver);
17975 unregister_isa:
17976 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017977 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017978 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017979}
17980
17981static void __exit advansys_exit(void)
17982{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017983 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060017984 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060017985 isa_unregister_driver(&advansys_vlb_driver);
17986 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017987}
17988
17989module_init(advansys_init);
17990module_exit(advansys_exit);
17991
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040017992MODULE_LICENSE("GPL");