blob: eda41f245bb433b0dbc5a0f00e8dffe814dc37ff [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)
857#define AscPCIConfigVendorIDRegister 0x0000
858#define AscPCIConfigDeviceIDRegister 0x0002
859#define AscPCIConfigCommandRegister 0x0004
860#define AscPCIConfigStatusRegister 0x0006
861#define AscPCIConfigRevisionIDRegister 0x0008
862#define AscPCIConfigCacheSize 0x000C
863#define AscPCIConfigLatencyTimer 0x000D
864#define AscPCIIOBaseRegister 0x0010
865#define AscPCICmdRegBits_IOMemBusMaster 0x0007
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866#define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7)
867#define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869#define ASC_DVCLIB_CALL_DONE (1)
870#define ASC_DVCLIB_CALL_FAILED (0)
871#define ASC_DVCLIB_CALL_ERROR (-1)
872
Dave Jones2672ea82006-08-02 17:11:49 -0400873#define PCI_VENDOR_ID_ASP 0x10cd
874#define PCI_DEVICE_ID_ASP_1200A 0x1100
875#define PCI_DEVICE_ID_ASP_ABP940 0x1200
876#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
877#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
878#define PCI_DEVICE_ID_38C0800_REV1 0x2500
879#define PCI_DEVICE_ID_38C1600_REV1 0x2700
880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881/*
882 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
883 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
884 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
885 * SRB structure.
886 */
887#define CC_VERY_LONG_SG_LIST 0
888#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
889
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400890#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891#define inp(port) inb(port)
892#define outp(port, byte) outb((byte), (port))
893
894#define inpw(port) inw(port)
895#define outpw(port, word) outw((word), (port))
896
897#define ASC_MAX_SG_QUEUE 7
898#define ASC_MAX_SG_LIST 255
899
900#define ASC_CS_TYPE unsigned short
901
902#define ASC_IS_ISA (0x0001)
903#define ASC_IS_ISAPNP (0x0081)
904#define ASC_IS_EISA (0x0002)
905#define ASC_IS_PCI (0x0004)
906#define ASC_IS_PCI_ULTRA (0x0104)
907#define ASC_IS_PCMCIA (0x0008)
908#define ASC_IS_MCA (0x0020)
909#define ASC_IS_VL (0x0040)
910#define ASC_ISA_PNP_PORT_ADDR (0x279)
911#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
912#define ASC_IS_WIDESCSI_16 (0x0100)
913#define ASC_IS_WIDESCSI_32 (0x0200)
914#define ASC_IS_BIG_ENDIAN (0x8000)
915#define ASC_CHIP_MIN_VER_VL (0x01)
916#define ASC_CHIP_MAX_VER_VL (0x07)
917#define ASC_CHIP_MIN_VER_PCI (0x09)
918#define ASC_CHIP_MAX_VER_PCI (0x0F)
919#define ASC_CHIP_VER_PCI_BIT (0x08)
920#define ASC_CHIP_MIN_VER_ISA (0x11)
921#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
922#define ASC_CHIP_MAX_VER_ISA (0x27)
923#define ASC_CHIP_VER_ISA_BIT (0x30)
924#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
925#define ASC_CHIP_VER_ASYN_BUG (0x21)
926#define ASC_CHIP_VER_PCI 0x08
927#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
928#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
929#define ASC_CHIP_MIN_VER_EISA (0x41)
930#define ASC_CHIP_MAX_VER_EISA (0x47)
931#define ASC_CHIP_VER_EISA_BIT (0x40)
932#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
933#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
934#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
935#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
936#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
937#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
938#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
939#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
940#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
941#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
942#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
943
944#define ASC_SCSI_ID_BITS 3
945#define ASC_SCSI_TIX_TYPE uchar
946#define ASC_ALL_DEVICE_BIT_SET 0xFF
947#define ASC_SCSI_BIT_ID_TYPE uchar
948#define ASC_MAX_TID 7
949#define ASC_MAX_LUN 7
950#define ASC_SCSI_WIDTH_BIT_SET 0xFF
951#define ASC_MAX_SENSE_LEN 32
952#define ASC_MIN_SENSE_LEN 14
953#define ASC_MAX_CDB_LEN 12
954#define ASC_SCSI_RESET_HOLD_TIME_US 60
955
956#define ADV_INQ_CLOCKING_ST_ONLY 0x0
957#define ADV_INQ_CLOCKING_DT_ONLY 0x1
958#define ADV_INQ_CLOCKING_ST_AND_DT 0x3
959
960/*
961 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
962 * and CmdDt (Command Support Data) field bit definitions.
963 */
964#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
965#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
966#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
967#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
968
969#define ASC_SCSIDIR_NOCHK 0x00
970#define ASC_SCSIDIR_T2H 0x08
971#define ASC_SCSIDIR_H2T 0x10
972#define ASC_SCSIDIR_NODATA 0x18
973#define SCSI_ASC_NOMEDIA 0x3A
974#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
975#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
976#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
977#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
978#define MS_CMD_DONE 0x00
979#define MS_EXTEND 0x01
980#define MS_SDTR_LEN 0x03
981#define MS_SDTR_CODE 0x01
982#define MS_WDTR_LEN 0x02
983#define MS_WDTR_CODE 0x03
984#define MS_MDP_LEN 0x05
985#define MS_MDP_CODE 0x00
986
987/*
988 * Inquiry data structure and bitfield macros
989 *
990 * Only quantities of more than 1 bit are shifted, since the others are
991 * just tested for true or false. C bitfields aren't portable between big
992 * and little-endian platforms so they are not used.
993 */
994
995#define ASC_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f)
996#define ASC_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5)
997#define ASC_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f)
998#define ASC_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80)
999#define ASC_INQ_ANSI_VER(inq) ((inq)->ver & 0x07)
1000#define ASC_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3)
1001#define ASC_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6)
1002#define ASC_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f)
1003#define ASC_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40)
1004#define ASC_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80)
1005#define ASC_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01)
1006#define ASC_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02)
1007#define ASC_INQ_LINK_CMD(inq) ((inq)->flags & 0x08)
1008#define ASC_INQ_SYNC(inq) ((inq)->flags & 0x10)
1009#define ASC_INQ_WIDE16(inq) ((inq)->flags & 0x20)
1010#define ASC_INQ_WIDE32(inq) ((inq)->flags & 0x40)
1011#define ASC_INQ_REL_ADDR(inq) ((inq)->flags & 0x80)
1012#define ASC_INQ_INFO_UNIT(inq) ((inq)->info & 0x01)
1013#define ASC_INQ_QUICK_ARB(inq) ((inq)->info & 0x02)
1014#define ASC_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2)
1015
1016typedef struct {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001017 uchar periph;
1018 uchar devtype;
1019 uchar ver;
1020 uchar byte3;
1021 uchar add_len;
1022 uchar res1;
1023 uchar res2;
1024 uchar flags;
1025 uchar vendor_id[8];
1026 uchar product_id[16];
1027 uchar product_rev_level[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028} ASC_SCSI_INQUIRY;
1029
1030#define ASC_SG_LIST_PER_Q 7
1031#define QS_FREE 0x00
1032#define QS_READY 0x01
1033#define QS_DISC1 0x02
1034#define QS_DISC2 0x04
1035#define QS_BUSY 0x08
1036#define QS_ABORTED 0x40
1037#define QS_DONE 0x80
1038#define QC_NO_CALLBACK 0x01
1039#define QC_SG_SWAP_QUEUE 0x02
1040#define QC_SG_HEAD 0x04
1041#define QC_DATA_IN 0x08
1042#define QC_DATA_OUT 0x10
1043#define QC_URGENT 0x20
1044#define QC_MSG_OUT 0x40
1045#define QC_REQ_SENSE 0x80
1046#define QCSG_SG_XFER_LIST 0x02
1047#define QCSG_SG_XFER_MORE 0x04
1048#define QCSG_SG_XFER_END 0x08
1049#define QD_IN_PROGRESS 0x00
1050#define QD_NO_ERROR 0x01
1051#define QD_ABORTED_BY_HOST 0x02
1052#define QD_WITH_ERROR 0x04
1053#define QD_INVALID_REQUEST 0x80
1054#define QD_INVALID_HOST_NUM 0x81
1055#define QD_INVALID_DEVICE 0x82
1056#define QD_ERR_INTERNAL 0xFF
1057#define QHSTA_NO_ERROR 0x00
1058#define QHSTA_M_SEL_TIMEOUT 0x11
1059#define QHSTA_M_DATA_OVER_RUN 0x12
1060#define QHSTA_M_DATA_UNDER_RUN 0x12
1061#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
1062#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
1063#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1064#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
1065#define QHSTA_D_HOST_ABORT_FAILED 0x23
1066#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
1067#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1068#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
1069#define QHSTA_M_WTM_TIMEOUT 0x41
1070#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
1071#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
1072#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1073#define QHSTA_M_TARGET_STATUS_BUSY 0x45
1074#define QHSTA_M_BAD_TAG_CODE 0x46
1075#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
1076#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
1077#define QHSTA_D_LRAM_CMP_ERROR 0x81
1078#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1079#define ASC_FLAG_SCSIQ_REQ 0x01
1080#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1081#define ASC_FLAG_BIOS_ASYNC_IO 0x04
1082#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1083#define ASC_FLAG_WIN16 0x10
1084#define ASC_FLAG_WIN32 0x20
1085#define ASC_FLAG_ISA_OVER_16MB 0x40
1086#define ASC_FLAG_DOS_VM_CALLBACK 0x80
1087#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
1088#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
1089#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
1090#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
1091#define ASC_SCSIQ_CPY_BEG 4
1092#define ASC_SCSIQ_SGHD_CPY_BEG 2
1093#define ASC_SCSIQ_B_FWD 0
1094#define ASC_SCSIQ_B_BWD 1
1095#define ASC_SCSIQ_B_STATUS 2
1096#define ASC_SCSIQ_B_QNO 3
1097#define ASC_SCSIQ_B_CNTL 4
1098#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1099#define ASC_SCSIQ_D_DATA_ADDR 8
1100#define ASC_SCSIQ_D_DATA_CNT 12
1101#define ASC_SCSIQ_B_SENSE_LEN 20
1102#define ASC_SCSIQ_DONE_INFO_BEG 22
1103#define ASC_SCSIQ_D_SRBPTR 22
1104#define ASC_SCSIQ_B_TARGET_IX 26
1105#define ASC_SCSIQ_B_CDB_LEN 28
1106#define ASC_SCSIQ_B_TAG_CODE 29
1107#define ASC_SCSIQ_W_VM_ID 30
1108#define ASC_SCSIQ_DONE_STATUS 32
1109#define ASC_SCSIQ_HOST_STATUS 33
1110#define ASC_SCSIQ_SCSI_STATUS 34
1111#define ASC_SCSIQ_CDB_BEG 36
1112#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1113#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1114#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
1115#define ASC_SCSIQ_B_SG_WK_QP 49
1116#define ASC_SCSIQ_B_SG_WK_IX 50
1117#define ASC_SCSIQ_W_ALT_DC1 52
1118#define ASC_SCSIQ_B_LIST_CNT 6
1119#define ASC_SCSIQ_B_CUR_LIST_CNT 7
1120#define ASC_SGQ_B_SG_CNTL 4
1121#define ASC_SGQ_B_SG_HEAD_QP 5
1122#define ASC_SGQ_B_SG_LIST_CNT 6
1123#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1124#define ASC_SGQ_LIST_BEG 8
1125#define ASC_DEF_SCSI1_QNG 4
1126#define ASC_MAX_SCSI1_QNG 4
1127#define ASC_DEF_SCSI2_QNG 16
1128#define ASC_MAX_SCSI2_QNG 32
1129#define ASC_TAG_CODE_MASK 0x23
1130#define ASC_STOP_REQ_RISC_STOP 0x01
1131#define ASC_STOP_ACK_RISC_STOP 0x03
1132#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1133#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1134#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1135#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
1136#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
1137#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
1138#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
1139#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
1140#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
1141#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
1142
1143typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001144 uchar status;
1145 uchar q_no;
1146 uchar cntl;
1147 uchar sg_queue_cnt;
1148 uchar target_id;
1149 uchar target_lun;
1150 ASC_PADDR data_addr;
1151 ASC_DCNT data_cnt;
1152 ASC_PADDR sense_addr;
1153 uchar sense_len;
1154 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155} ASC_SCSIQ_1;
1156
1157typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001158 ASC_VADDR srb_ptr;
1159 uchar target_ix;
1160 uchar flag;
1161 uchar cdb_len;
1162 uchar tag_code;
1163 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164} ASC_SCSIQ_2;
1165
1166typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001167 uchar done_stat;
1168 uchar host_stat;
1169 uchar scsi_stat;
1170 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171} ASC_SCSIQ_3;
1172
1173typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001174 uchar cdb[ASC_MAX_CDB_LEN];
1175 uchar y_first_sg_list_qp;
1176 uchar y_working_sg_qp;
1177 uchar y_working_sg_ix;
1178 uchar y_res;
1179 ushort x_req_count;
1180 ushort x_reconnect_rtn;
1181 ASC_PADDR x_saved_data_addr;
1182 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183} ASC_SCSIQ_4;
1184
1185typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001186 ASC_SCSIQ_2 d2;
1187 ASC_SCSIQ_3 d3;
1188 uchar q_status;
1189 uchar q_no;
1190 uchar cntl;
1191 uchar sense_len;
1192 uchar extra_bytes;
1193 uchar res;
1194 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195} ASC_QDONE_INFO;
1196
1197typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001198 ASC_PADDR addr;
1199 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200} ASC_SG_LIST;
1201
1202typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001203 ushort entry_cnt;
1204 ushort queue_cnt;
1205 ushort entry_to_copy;
1206 ushort res;
1207 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208} ASC_SG_HEAD;
1209
1210#define ASC_MIN_SG_LIST 2
1211
1212typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001213 ushort entry_cnt;
1214 ushort queue_cnt;
1215 ushort entry_to_copy;
1216 ushort res;
1217 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218} ASC_MIN_SG_HEAD;
1219
1220#define QCX_SORT (0x0001)
1221#define QCX_COALEASE (0x0002)
1222
1223typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001224 ASC_SCSIQ_1 q1;
1225 ASC_SCSIQ_2 q2;
1226 uchar *cdbptr;
1227 ASC_SG_HEAD *sg_head;
1228 ushort remain_sg_entry_cnt;
1229 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230} ASC_SCSI_Q;
1231
1232typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001233 ASC_SCSIQ_1 r1;
1234 ASC_SCSIQ_2 r2;
1235 uchar *cdbptr;
1236 ASC_SG_HEAD *sg_head;
1237 uchar *sense_ptr;
1238 ASC_SCSIQ_3 r3;
1239 uchar cdb[ASC_MAX_CDB_LEN];
1240 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241} ASC_SCSI_REQ_Q;
1242
1243typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001244 ASC_SCSIQ_1 r1;
1245 ASC_SCSIQ_2 r2;
1246 uchar *cdbptr;
1247 ASC_SG_HEAD *sg_head;
1248 uchar *sense_ptr;
1249 ASC_SCSIQ_3 r3;
1250 uchar cdb[ASC_MAX_CDB_LEN];
1251 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252} ASC_SCSI_BIOS_REQ_Q;
1253
1254typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001255 uchar fwd;
1256 uchar bwd;
1257 ASC_SCSIQ_1 i1;
1258 ASC_SCSIQ_2 i2;
1259 ASC_SCSIQ_3 i3;
1260 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261} ASC_RISC_Q;
1262
1263typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001264 uchar seq_no;
1265 uchar q_no;
1266 uchar cntl;
1267 uchar sg_head_qp;
1268 uchar sg_list_cnt;
1269 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270} ASC_SG_LIST_Q;
1271
1272typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001273 uchar fwd;
1274 uchar bwd;
1275 ASC_SG_LIST_Q sg;
1276 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277} ASC_RISC_SG_LIST_Q;
1278
1279#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1280#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1281#define ASCQ_ERR_NO_ERROR 0
1282#define ASCQ_ERR_IO_NOT_FOUND 1
1283#define ASCQ_ERR_LOCAL_MEM 2
1284#define ASCQ_ERR_CHKSUM 3
1285#define ASCQ_ERR_START_CHIP 4
1286#define ASCQ_ERR_INT_TARGET_ID 5
1287#define ASCQ_ERR_INT_LOCAL_MEM 6
1288#define ASCQ_ERR_HALT_RISC 7
1289#define ASCQ_ERR_GET_ASPI_ENTRY 8
1290#define ASCQ_ERR_CLOSE_ASPI 9
1291#define ASCQ_ERR_HOST_INQUIRY 0x0A
1292#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1293#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1294#define ASCQ_ERR_Q_STATUS 0x0D
1295#define ASCQ_ERR_WR_SCSIQ 0x0E
1296#define ASCQ_ERR_PC_ADDR 0x0F
1297#define ASCQ_ERR_SYN_OFFSET 0x10
1298#define ASCQ_ERR_SYN_XFER_TIME 0x11
1299#define ASCQ_ERR_LOCK_DMA 0x12
1300#define ASCQ_ERR_UNLOCK_DMA 0x13
1301#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1302#define ASCQ_ERR_MICRO_CODE_HALT 0x15
1303#define ASCQ_ERR_SET_LRAM_ADDR 0x16
1304#define ASCQ_ERR_CUR_QNG 0x17
1305#define ASCQ_ERR_SG_Q_LINKS 0x18
1306#define ASCQ_ERR_SCSIQ_PTR 0x19
1307#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1308#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1309#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1310#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1311#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1312#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1313#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1314#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1315#define ASCQ_ERR_SEND_SCSI_Q 0x22
1316#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1317#define ASCQ_ERR_RESET_SDTR 0x24
1318
1319/*
1320 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
1321 */
1322#define ASC_WARN_NO_ERROR 0x0000
1323#define ASC_WARN_IO_PORT_ROTATE 0x0001
1324#define ASC_WARN_EEPROM_CHKSUM 0x0002
1325#define ASC_WARN_IRQ_MODIFIED 0x0004
1326#define ASC_WARN_AUTO_CONFIG 0x0008
1327#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1328#define ASC_WARN_EEPROM_RECOVER 0x0020
1329#define ASC_WARN_CFG_MSW_RECOVER 0x0040
1330#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
1331
1332/*
1333 * Error code values are set in ASC_DVC_VAR 'err_code'.
1334 */
1335#define ASC_IERR_WRITE_EEPROM 0x0001
1336#define ASC_IERR_MCODE_CHKSUM 0x0002
1337#define ASC_IERR_SET_PC_ADDR 0x0004
1338#define ASC_IERR_START_STOP_CHIP 0x0008
1339#define ASC_IERR_IRQ_NO 0x0010
1340#define ASC_IERR_SET_IRQ_NO 0x0020
1341#define ASC_IERR_CHIP_VERSION 0x0040
1342#define ASC_IERR_SET_SCSI_ID 0x0080
1343#define ASC_IERR_GET_PHY_ADDR 0x0100
1344#define ASC_IERR_BAD_SIGNATURE 0x0200
1345#define ASC_IERR_NO_BUS_TYPE 0x0400
1346#define ASC_IERR_SCAM 0x0800
1347#define ASC_IERR_SET_SDTR 0x1000
1348#define ASC_IERR_RW_LRAM 0x8000
1349
1350#define ASC_DEF_IRQ_NO 10
1351#define ASC_MAX_IRQ_NO 15
1352#define ASC_MIN_IRQ_NO 10
1353#define ASC_MIN_REMAIN_Q (0x02)
1354#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
1355#define ASC_MIN_TAG_Q_PER_DVC (0x04)
1356#define ASC_DEF_TAG_Q_PER_DVC (0x04)
1357#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1358#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
1359#define ASC_MAX_TOTAL_QNG 240
1360#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
1361#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
1362#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1363#define ASC_MAX_INRAM_TAG_QNG 16
1364#define ASC_IOADR_TABLE_MAX_IX 11
1365#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366#define ASC_LIB_SCSIQ_WK_SP 256
1367#define ASC_MAX_SYN_XFER_NO 16
1368#define ASC_SYN_MAX_OFFSET 0x0F
1369#define ASC_DEF_SDTR_OFFSET 0x0F
1370#define ASC_DEF_SDTR_INDEX 0x00
1371#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
1372#define SYN_XFER_NS_0 25
1373#define SYN_XFER_NS_1 30
1374#define SYN_XFER_NS_2 35
1375#define SYN_XFER_NS_3 40
1376#define SYN_XFER_NS_4 50
1377#define SYN_XFER_NS_5 60
1378#define SYN_XFER_NS_6 70
1379#define SYN_XFER_NS_7 85
1380#define SYN_ULTRA_XFER_NS_0 12
1381#define SYN_ULTRA_XFER_NS_1 19
1382#define SYN_ULTRA_XFER_NS_2 25
1383#define SYN_ULTRA_XFER_NS_3 32
1384#define SYN_ULTRA_XFER_NS_4 38
1385#define SYN_ULTRA_XFER_NS_5 44
1386#define SYN_ULTRA_XFER_NS_6 50
1387#define SYN_ULTRA_XFER_NS_7 57
1388#define SYN_ULTRA_XFER_NS_8 63
1389#define SYN_ULTRA_XFER_NS_9 69
1390#define SYN_ULTRA_XFER_NS_10 75
1391#define SYN_ULTRA_XFER_NS_11 82
1392#define SYN_ULTRA_XFER_NS_12 88
1393#define SYN_ULTRA_XFER_NS_13 94
1394#define SYN_ULTRA_XFER_NS_14 100
1395#define SYN_ULTRA_XFER_NS_15 107
1396
1397typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001398 uchar msg_type;
1399 uchar msg_len;
1400 uchar msg_req;
1401 union {
1402 struct {
1403 uchar sdtr_xfer_period;
1404 uchar sdtr_req_ack_offset;
1405 } sdtr;
1406 struct {
1407 uchar wdtr_width;
1408 } wdtr;
1409 struct {
1410 uchar mdp_b3;
1411 uchar mdp_b2;
1412 uchar mdp_b1;
1413 uchar mdp_b0;
1414 } mdp;
1415 } u_ext_msg;
1416 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417} EXT_MSG;
1418
1419#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
1420#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
1421#define wdtr_width u_ext_msg.wdtr.wdtr_width
1422#define mdp_b3 u_ext_msg.mdp_b3
1423#define mdp_b2 u_ext_msg.mdp_b2
1424#define mdp_b1 u_ext_msg.mdp_b1
1425#define mdp_b0 u_ext_msg.mdp_b0
1426
1427typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001428 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1429 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1430 ASC_SCSI_BIT_ID_TYPE disc_enable;
1431 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
1432 uchar chip_scsi_id;
1433 uchar isa_dma_speed;
1434 uchar isa_dma_channel;
1435 uchar chip_version;
1436 ushort lib_serial_no;
1437 ushort lib_version;
1438 ushort mcode_date;
1439 ushort mcode_version;
1440 uchar max_tag_qng[ASC_MAX_TID + 1];
1441 uchar *overrun_buf;
1442 uchar sdtr_period_offset[ASC_MAX_TID + 1];
1443 ushort pci_slot_info;
1444 uchar adapter_info[6];
1445 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446} ASC_DVC_CFG;
1447
1448#define ASC_DEF_DVC_CNTL 0xFFFF
1449#define ASC_DEF_CHIP_SCSI_ID 7
1450#define ASC_DEF_ISA_DMA_SPEED 4
1451#define ASC_INIT_STATE_NULL 0x0000
1452#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1453#define ASC_INIT_STATE_END_GET_CFG 0x0002
1454#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1455#define ASC_INIT_STATE_END_SET_CFG 0x0008
1456#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1457#define ASC_INIT_STATE_END_LOAD_MC 0x0020
1458#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1459#define ASC_INIT_STATE_END_INQUIRY 0x0080
1460#define ASC_INIT_RESET_SCSI_DONE 0x0100
1461#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
1463#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
1464#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1465#define ASC_MIN_TAGGED_CMD 7
1466#define ASC_MAX_SCSI_RESET_WAIT 30
1467
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001468struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001470typedef void (*ASC_ISR_CALLBACK) (struct asc_dvc_var *, ASC_QDONE_INFO *);
1471typedef int (*ASC_EXE_CALLBACK) (struct asc_dvc_var *, ASC_SCSI_Q *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001474 PortAddr iop_base;
1475 ushort err_code;
1476 ushort dvc_cntl;
1477 ushort bug_fix_cntl;
1478 ushort bus_type;
1479 ASC_ISR_CALLBACK isr_callback;
1480 ASC_EXE_CALLBACK exe_callback;
1481 ASC_SCSI_BIT_ID_TYPE init_sdtr;
1482 ASC_SCSI_BIT_ID_TYPE sdtr_done;
1483 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1484 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1485 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1486 ASC_SCSI_BIT_ID_TYPE start_motor;
1487 uchar scsi_reset_wait;
1488 uchar chip_no;
1489 char is_in_int;
1490 uchar max_total_qng;
1491 uchar cur_total_qng;
1492 uchar in_critical_cnt;
1493 uchar irq_no;
1494 uchar last_q_shortage;
1495 ushort init_state;
1496 uchar cur_dvc_qng[ASC_MAX_TID + 1];
1497 uchar max_dvc_qng[ASC_MAX_TID + 1];
1498 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
1499 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
1500 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
1501 ASC_DVC_CFG *cfg;
1502 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
1503 char redo_scam;
1504 ushort res2;
1505 uchar dos_int13_table[ASC_MAX_TID + 1];
1506 ASC_DCNT max_dma_count;
1507 ASC_SCSI_BIT_ID_TYPE no_scam;
1508 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1509 uchar max_sdtr_index;
1510 uchar host_init_sdtr_index;
1511 struct asc_board *drv_ptr;
1512 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513} ASC_DVC_VAR;
1514
1515typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001516 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517} ASC_DVC_INQ_INFO;
1518
1519typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001520 ASC_DCNT lba;
1521 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522} ASC_CAP_INFO;
1523
1524typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001525 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526} ASC_CAP_INFO_ARRAY;
1527
1528#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
1529#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
1530#define ASC_CNTL_INITIATOR (ushort)0x0001
1531#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
1532#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
1533#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
1534#define ASC_CNTL_NO_SCAM (ushort)0x0010
1535#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
1536#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
1537#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
1538#define ASC_CNTL_RESET_SCSI (ushort)0x0200
1539#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
1540#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
1541#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
1542#define ASC_CNTL_BURST_MODE (ushort)0x2000
1543#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
1544#define ASC_EEP_DVC_CFG_BEG_VL 2
1545#define ASC_EEP_MAX_DVC_ADDR_VL 15
1546#define ASC_EEP_DVC_CFG_BEG 32
1547#define ASC_EEP_MAX_DVC_ADDR 45
1548#define ASC_EEP_DEFINED_WORDS 10
1549#define ASC_EEP_MAX_ADDR 63
1550#define ASC_EEP_RES_WORDS 0
1551#define ASC_EEP_MAX_RETRY 20
1552#define ASC_MAX_INIT_BUSY_RETRY 8
1553#define ASC_EEP_ISA_PNP_WSIZE 16
1554
1555/*
1556 * These macros keep the chip SCSI id and ISA DMA speed
1557 * bitfields in board order. C bitfields aren't portable
1558 * between big and little-endian platforms so they are
1559 * not used.
1560 */
1561
1562#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
1563#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
1564#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
1565 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
1566#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
1567 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
1568
1569typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001570 ushort cfg_lsw;
1571 ushort cfg_msw;
1572 uchar init_sdtr;
1573 uchar disc_enable;
1574 uchar use_cmd_qng;
1575 uchar start_motor;
1576 uchar max_total_qng;
1577 uchar max_tag_qng;
1578 uchar bios_scan;
1579 uchar power_up_wait;
1580 uchar no_scam;
1581 uchar id_speed; /* low order 4 bits is chip scsi id */
1582 /* high order 4 bits is isa dma speed */
1583 uchar dos_int13_table[ASC_MAX_TID + 1];
1584 uchar adapter_info[6];
1585 ushort cntl;
1586 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587} ASCEEP_CONFIG;
1588
1589#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
1590#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
1591#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
1592
1593#define ASC_EEP_CMD_READ 0x80
1594#define ASC_EEP_CMD_WRITE 0x40
1595#define ASC_EEP_CMD_WRITE_ABLE 0x30
1596#define ASC_EEP_CMD_WRITE_DISABLE 0x00
1597#define ASC_OVERRUN_BSIZE 0x00000048UL
1598#define ASC_CTRL_BREAK_ONCE 0x0001
1599#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
1600#define ASCV_MSGOUT_BEG 0x0000
1601#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1602#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1603#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
1604#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1605#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1606#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1607#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1608#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1609#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
1610#define ASCV_BREAK_ADDR (ushort)0x0028
1611#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
1612#define ASCV_BREAK_CONTROL (ushort)0x002C
1613#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
1614
1615#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
1616#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
1617#define ASCV_MCODE_SIZE_W (ushort)0x0034
1618#define ASCV_STOP_CODE_B (ushort)0x0036
1619#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
1620#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
1621#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
1622#define ASCV_HALTCODE_W (ushort)0x0040
1623#define ASCV_CHKSUM_W (ushort)0x0042
1624#define ASCV_MC_DATE_W (ushort)0x0044
1625#define ASCV_MC_VER_W (ushort)0x0046
1626#define ASCV_NEXTRDY_B (ushort)0x0048
1627#define ASCV_DONENEXT_B (ushort)0x0049
1628#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
1629#define ASCV_SCSIBUSY_B (ushort)0x004B
1630#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
1631#define ASCV_CURCDB_B (ushort)0x004D
1632#define ASCV_RCLUN_B (ushort)0x004E
1633#define ASCV_BUSY_QHEAD_B (ushort)0x004F
1634#define ASCV_DISC1_QHEAD_B (ushort)0x0050
1635#define ASCV_DISC_ENABLE_B (ushort)0x0052
1636#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
1637#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
1638#define ASCV_MCODE_CNTL_B (ushort)0x0056
1639#define ASCV_NULL_TARGET_B (ushort)0x0057
1640#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
1641#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
1642#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
1643#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
1644#define ASCV_HOST_FLAG_B (ushort)0x005D
1645#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
1646#define ASCV_VER_SERIAL_B (ushort)0x0065
1647#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
1648#define ASCV_WTM_FLAG_B (ushort)0x0068
1649#define ASCV_RISC_FLAG_B (ushort)0x006A
1650#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
1651#define ASC_HOST_FLAG_IN_ISR 0x01
1652#define ASC_HOST_FLAG_ACK_INT 0x02
1653#define ASC_RISC_FLAG_GEN_INT 0x01
1654#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1655#define IOP_CTRL (0x0F)
1656#define IOP_STATUS (0x0E)
1657#define IOP_INT_ACK IOP_STATUS
1658#define IOP_REG_IFC (0x0D)
1659#define IOP_SYN_OFFSET (0x0B)
1660#define IOP_EXTRA_CONTROL (0x0D)
1661#define IOP_REG_PC (0x0C)
1662#define IOP_RAM_ADDR (0x0A)
1663#define IOP_RAM_DATA (0x08)
1664#define IOP_EEP_DATA (0x06)
1665#define IOP_EEP_CMD (0x07)
1666#define IOP_VERSION (0x03)
1667#define IOP_CONFIG_HIGH (0x04)
1668#define IOP_CONFIG_LOW (0x02)
1669#define IOP_SIG_BYTE (0x01)
1670#define IOP_SIG_WORD (0x00)
1671#define IOP_REG_DC1 (0x0E)
1672#define IOP_REG_DC0 (0x0C)
1673#define IOP_REG_SB (0x0B)
1674#define IOP_REG_DA1 (0x0A)
1675#define IOP_REG_DA0 (0x08)
1676#define IOP_REG_SC (0x09)
1677#define IOP_DMA_SPEED (0x07)
1678#define IOP_REG_FLAG (0x07)
1679#define IOP_FIFO_H (0x06)
1680#define IOP_FIFO_L (0x04)
1681#define IOP_REG_ID (0x05)
1682#define IOP_REG_QP (0x03)
1683#define IOP_REG_IH (0x02)
1684#define IOP_REG_IX (0x01)
1685#define IOP_REG_AX (0x00)
1686#define IFC_REG_LOCK (0x00)
1687#define IFC_REG_UNLOCK (0x09)
1688#define IFC_WR_EN_FILTER (0x10)
1689#define IFC_RD_NO_EEPROM (0x10)
1690#define IFC_SLEW_RATE (0x20)
1691#define IFC_ACT_NEG (0x40)
1692#define IFC_INP_FILTER (0x80)
1693#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
1694#define SC_SEL (uchar)(0x80)
1695#define SC_BSY (uchar)(0x40)
1696#define SC_ACK (uchar)(0x20)
1697#define SC_REQ (uchar)(0x10)
1698#define SC_ATN (uchar)(0x08)
1699#define SC_IO (uchar)(0x04)
1700#define SC_CD (uchar)(0x02)
1701#define SC_MSG (uchar)(0x01)
1702#define SEC_SCSI_CTL (uchar)(0x80)
1703#define SEC_ACTIVE_NEGATE (uchar)(0x40)
1704#define SEC_SLEW_RATE (uchar)(0x20)
1705#define SEC_ENABLE_FILTER (uchar)(0x10)
1706#define ASC_HALT_EXTMSG_IN (ushort)0x8000
1707#define ASC_HALT_CHK_CONDITION (ushort)0x8100
1708#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
1709#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
1710#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
1711#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
1712#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
1713#define ASC_MAX_QNO 0xF8
1714#define ASC_DATA_SEC_BEG (ushort)0x0080
1715#define ASC_DATA_SEC_END (ushort)0x0080
1716#define ASC_CODE_SEC_BEG (ushort)0x0080
1717#define ASC_CODE_SEC_END (ushort)0x0080
1718#define ASC_QADR_BEG (0x4000)
1719#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
1720#define ASC_QADR_END (ushort)0x7FFF
1721#define ASC_QLAST_ADR (ushort)0x7FC0
1722#define ASC_QBLK_SIZE 0x40
1723#define ASC_BIOS_DATA_QBEG 0xF8
1724#define ASC_MIN_ACTIVE_QNO 0x01
1725#define ASC_QLINK_END 0xFF
1726#define ASC_EEPROM_WORDS 0x10
1727#define ASC_MAX_MGS_LEN 0x10
1728#define ASC_BIOS_ADDR_DEF 0xDC00
1729#define ASC_BIOS_SIZE 0x3800
1730#define ASC_BIOS_RAM_OFF 0x3800
1731#define ASC_BIOS_RAM_SIZE 0x800
1732#define ASC_BIOS_MIN_ADDR 0xC000
1733#define ASC_BIOS_MAX_ADDR 0xEC00
1734#define ASC_BIOS_BANK_SIZE 0x0400
1735#define ASC_MCODE_START_ADDR 0x0080
1736#define ASC_CFG0_HOST_INT_ON 0x0020
1737#define ASC_CFG0_BIOS_ON 0x0040
1738#define ASC_CFG0_VERA_BURST_ON 0x0080
1739#define ASC_CFG0_SCSI_PARITY_ON 0x0800
1740#define ASC_CFG1_SCSI_TARGET_ON 0x0080
1741#define ASC_CFG1_LRAM_8BITS_ON 0x0800
1742#define ASC_CFG_MSW_CLR_MASK 0x3080
1743#define CSW_TEST1 (ASC_CS_TYPE)0x8000
1744#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
1745#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
1746#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
1747#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
1748#define CSW_TEST2 (ASC_CS_TYPE)0x0400
1749#define CSW_TEST3 (ASC_CS_TYPE)0x0200
1750#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
1751#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
1752#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
1753#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
1754#define CSW_HALTED (ASC_CS_TYPE)0x0010
1755#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
1756#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
1757#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
1758#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
1759#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
1760#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
1761#define CIW_TEST1 (ASC_CS_TYPE)0x0200
1762#define CIW_TEST2 (ASC_CS_TYPE)0x0400
1763#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
1764#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
1765#define CC_CHIP_RESET (uchar)0x80
1766#define CC_SCSI_RESET (uchar)0x40
1767#define CC_HALT (uchar)0x20
1768#define CC_SINGLE_STEP (uchar)0x10
1769#define CC_DMA_ABLE (uchar)0x08
1770#define CC_TEST (uchar)0x04
1771#define CC_BANK_ONE (uchar)0x02
1772#define CC_DIAG (uchar)0x01
1773#define ASC_1000_ID0W 0x04C1
1774#define ASC_1000_ID0W_FIX 0x00C1
1775#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776#define ASC_EISA_REV_IOP_MASK (0x0C83)
1777#define ASC_EISA_PID_IOP_MASK (0x0C80)
1778#define ASC_EISA_CFG_IOP_MASK (0x0C86)
1779#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780#define INS_HALTINT (ushort)0x6281
1781#define INS_HALT (ushort)0x6280
1782#define INS_SINT (ushort)0x6200
1783#define INS_RFLAG_WTM (ushort)0x7380
1784#define ASC_MC_SAVE_CODE_WSIZE 0x500
1785#define ASC_MC_SAVE_DATA_WSIZE 0x40
1786
1787typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001788 ushort data[ASC_MC_SAVE_DATA_WSIZE];
1789 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790} ASC_MC_SAVED;
1791
1792#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
1793#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1794#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1795#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1796#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1797#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1798#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1799#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1800#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1801#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1802#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1803#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1804#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1805#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1806#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1807#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1808#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1809#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1810#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1811#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1812#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1813#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1814#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1815#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1816#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1817#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1818#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1819#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1820#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1821#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1822#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1823#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1824#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1825#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1826#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1827#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1828#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1829#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1830#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1831#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1832#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1833#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1834#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1835#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1836#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1837#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1838#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1839#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1840#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1841#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1842#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1843#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1844#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1845#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1846#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1847#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1848#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1849#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1850#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1851#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1852#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1853#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1854#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1855#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1856#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1857#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1858#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1859#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1860
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001861static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1862static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1863static void AscWaitEEPRead(void);
1864static void AscWaitEEPWrite(void);
1865static ushort AscReadEEPWord(PortAddr, uchar);
1866static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1867static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1868static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1869static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1870static int AscStartChip(PortAddr);
1871static int AscStopChip(PortAddr);
1872static void AscSetChipIH(PortAddr, ushort);
1873static int AscIsChipHalted(PortAddr);
1874static void AscAckInterrupt(PortAddr);
1875static void AscDisableInterrupt(PortAddr);
1876static void AscEnableInterrupt(PortAddr);
1877static void AscSetBank(PortAddr, uchar);
1878static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001880static ushort AscGetIsaDmaChannel(PortAddr);
1881static ushort AscSetIsaDmaChannel(PortAddr, ushort);
1882static uchar AscSetIsaDmaSpeed(PortAddr, uchar);
1883static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001885static uchar AscReadLramByte(PortAddr, ushort);
1886static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001888static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001890static void AscWriteLramWord(PortAddr, ushort, ushort);
1891static void AscWriteLramByte(PortAddr, ushort, uchar);
1892static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1893static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1894static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1895static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1896static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1897static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1898static ushort AscInitFromEEP(ASC_DVC_VAR *);
1899static ushort AscInitFromAscDvcVar(ASC_DVC_VAR *);
1900static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1901static int AscTestExternalLram(ASC_DVC_VAR *);
1902static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1903static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1904static void AscSetChipSDTR(PortAddr, uchar, uchar);
1905static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1906static uchar AscAllocFreeQueue(PortAddr, uchar);
1907static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1908static int AscHostReqRiscHalt(PortAddr);
1909static int AscStopQueueExe(PortAddr);
1910static int AscSendScsiQueue(ASC_DVC_VAR *,
1911 ASC_SCSI_Q *scsiq, uchar n_q_required);
1912static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1913static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1914static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1915static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1916static ushort AscInitLram(ASC_DVC_VAR *);
1917static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1918static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1919static int AscIsrChipHalted(ASC_DVC_VAR *);
1920static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1921 ASC_QDONE_INFO *, ASC_DCNT);
1922static int AscIsrQDone(ASC_DVC_VAR *);
1923static int AscCompareString(uchar *, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001925static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001927static uchar AscGetChipScsiCtrl(PortAddr);
1928static uchar AscSetChipScsiID(PortAddr, uchar);
1929static uchar AscGetChipVersion(PortAddr, ushort);
1930static ushort AscGetChipBusType(PortAddr);
1931static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
1932static int AscFindSignature(PortAddr);
1933static void AscToggleIRQAct(PortAddr);
1934static uchar AscGetChipIRQ(PortAddr, ushort);
1935static uchar AscSetChipIRQ(PortAddr, uchar, ushort);
1936static ushort AscGetChipBiosAddress(PortAddr, ushort);
1937static inline ulong DvcEnterCritical(void);
1938static inline void DvcLeaveCritical(ulong);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001940static uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort);
1941static void DvcWritePCIConfigByte(ASC_DVC_VAR *, ushort, uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001943static ushort AscGetChipBiosAddress(PortAddr, ushort);
1944static void DvcSleepMilliSecond(ASC_DCNT);
1945static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1946static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1947static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
1948static ushort AscInitGetConfig(ASC_DVC_VAR *);
1949static ushort AscInitSetConfig(ASC_DVC_VAR *);
1950static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
1951static void AscAsyncFix(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *);
1952static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
1953static void AscInquiryHandling(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *);
1954static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1955static int AscISR(ASC_DVC_VAR *);
1956static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1957static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001959static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001961static ASC_DCNT AscGetMaxDmaCount(ushort);
1962static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963
1964/*
1965 * --- Adv Library Constants and Macros
1966 */
1967
1968#define ADV_LIB_VERSION_MAJOR 5
1969#define ADV_LIB_VERSION_MINOR 14
1970
1971/*
1972 * Define Adv Library required special types.
1973 */
1974
1975/*
1976 * Portable Data Types
1977 *
1978 * Any instance where a 32-bit long or pointer type is assumed
1979 * for precision or HW defined structures, the following define
1980 * types must be used. In Linux the char, short, and int types
1981 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1982 * and long types are 64 bits on Alpha and UltraSPARC.
1983 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001984#define ADV_PADDR __u32 /* Physical address data type. */
1985#define ADV_VADDR __u32 /* Virtual address data type. */
1986#define ADV_DCNT __u32 /* Unsigned Data count type. */
1987#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
1989/*
1990 * These macros are used to convert a virtual address to a
1991 * 32-bit value. This currently can be used on Linux Alpha
1992 * which uses 64-bit virtual address but a 32-bit bus address.
1993 * This is likely to break in the future, but doing this now
1994 * will give us time to change the HW and FW to handle 64-bit
1995 * addresses.
1996 */
1997#define ADV_VADDR_TO_U32 virt_to_bus
1998#define ADV_U32_TO_VADDR bus_to_virt
1999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002000#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
2002/*
2003 * Define Adv Library required memory access macros.
2004 */
2005#define ADV_MEM_READB(addr) readb(addr)
2006#define ADV_MEM_READW(addr) readw(addr)
2007#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
2008#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
2009#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
2010
2011#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
2012
2013/*
2014 * For wide boards a CDB length maximum of 16 bytes
2015 * is supported.
2016 */
2017#define ADV_MAX_CDB_LEN 16
2018
2019/*
2020 * Define total number of simultaneous maximum element scatter-gather
2021 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
2022 * maximum number of outstanding commands per wide host adapter. Each
2023 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
2024 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
2025 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
2026 * structures or 255 scatter-gather elements.
2027 *
2028 */
2029#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
2030
2031/*
2032 * Define Adv Library required maximum number of scatter-gather
2033 * elements per request.
2034 */
2035#define ADV_MAX_SG_LIST 255
2036
2037/* Number of SG blocks needed. */
2038#define ADV_NUM_SG_BLOCK \
2039 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
2040
2041/* Total contiguous memory needed for SG blocks. */
2042#define ADV_SG_TOTAL_MEM_SIZE \
2043 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
2044
2045#define ADV_PAGE_SIZE PAGE_SIZE
2046
2047#define ADV_NUM_PAGE_CROSSING \
2048 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050#define ADV_EEP_DVC_CFG_BEGIN (0x00)
2051#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002052#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053#define ADV_EEP_MAX_WORD_ADDR (0x1E)
2054
2055#define ADV_EEP_DELAY_MS 100
2056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002057#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
2058#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059/*
2060 * For the ASC3550 Bit 13 is Termination Polarity control bit.
2061 * For later ICs Bit 13 controls whether the CIS (Card Information
2062 * Service Section) is loaded from EEPROM.
2063 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002064#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
2065#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066/*
2067 * ASC38C1600 Bit 11
2068 *
2069 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
2070 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
2071 * Function 0 will specify INT B.
2072 *
2073 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
2074 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
2075 * Function 1 will specify INT A.
2076 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002077#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002079typedef struct adveep_3550_config {
2080 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002082 ushort cfg_lsw; /* 00 power up initialization */
2083 /* bit 13 set - Term Polarity Control */
2084 /* bit 14 set - BIOS Enable */
2085 /* bit 15 set - Big Endian Mode */
2086 ushort cfg_msw; /* 01 unused */
2087 ushort disc_enable; /* 02 disconnect enable */
2088 ushort wdtr_able; /* 03 Wide DTR able */
2089 ushort sdtr_able; /* 04 Synchronous DTR able */
2090 ushort start_motor; /* 05 send start up motor */
2091 ushort tagqng_able; /* 06 tag queuing able */
2092 ushort bios_scan; /* 07 BIOS device control */
2093 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002095 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2096 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002098 uchar scsi_reset_delay; /* 10 reset delay */
2099 uchar bios_id_lun; /* first boot device scsi id & lun */
2100 /* high nibble is lun */
2101 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002103 uchar termination; /* 11 0 - automatic */
2104 /* 1 - low off / high off */
2105 /* 2 - low off / high on */
2106 /* 3 - low on / high on */
2107 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002109 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002111 ushort bios_ctrl; /* 12 BIOS control bits */
2112 /* bit 0 BIOS don't act as initiator. */
2113 /* bit 1 BIOS > 1 GB support */
2114 /* bit 2 BIOS > 2 Disk Support */
2115 /* bit 3 BIOS don't support removables */
2116 /* bit 4 BIOS support bootable CD */
2117 /* bit 5 BIOS scan enabled */
2118 /* bit 6 BIOS support multiple LUNs */
2119 /* bit 7 BIOS display of message */
2120 /* bit 8 SCAM disabled */
2121 /* bit 9 Reset SCSI bus during init. */
2122 /* bit 10 */
2123 /* bit 11 No verbose initialization. */
2124 /* bit 12 SCSI parity enabled */
2125 /* bit 13 */
2126 /* bit 14 */
2127 /* bit 15 */
2128 ushort ultra_able; /* 13 ULTRA speed able */
2129 ushort reserved2; /* 14 reserved */
2130 uchar max_host_qng; /* 15 maximum host queuing */
2131 uchar max_dvc_qng; /* maximum per device queuing */
2132 ushort dvc_cntl; /* 16 control bit for driver */
2133 ushort bug_fix; /* 17 control bit for bug fix */
2134 ushort serial_number_word1; /* 18 Board serial number word 1 */
2135 ushort serial_number_word2; /* 19 Board serial number word 2 */
2136 ushort serial_number_word3; /* 20 Board serial number word 3 */
2137 ushort check_sum; /* 21 EEP check sum */
2138 uchar oem_name[16]; /* 22 OEM name */
2139 ushort dvc_err_code; /* 30 last device driver error code */
2140 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2141 ushort adv_err_addr; /* 32 last uc error address */
2142 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2143 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2144 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2145 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146} ADVEEP_3550_CONFIG;
2147
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002148typedef struct adveep_38C0800_config {
2149 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002151 ushort cfg_lsw; /* 00 power up initialization */
2152 /* bit 13 set - Load CIS */
2153 /* bit 14 set - BIOS Enable */
2154 /* bit 15 set - Big Endian Mode */
2155 ushort cfg_msw; /* 01 unused */
2156 ushort disc_enable; /* 02 disconnect enable */
2157 ushort wdtr_able; /* 03 Wide DTR able */
2158 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2159 ushort start_motor; /* 05 send start up motor */
2160 ushort tagqng_able; /* 06 tag queuing able */
2161 ushort bios_scan; /* 07 BIOS device control */
2162 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002164 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2165 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002167 uchar scsi_reset_delay; /* 10 reset delay */
2168 uchar bios_id_lun; /* first boot device scsi id & lun */
2169 /* high nibble is lun */
2170 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002172 uchar termination_se; /* 11 0 - automatic */
2173 /* 1 - low off / high off */
2174 /* 2 - low off / high on */
2175 /* 3 - low on / high on */
2176 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002178 uchar termination_lvd; /* 11 0 - automatic */
2179 /* 1 - low off / high off */
2180 /* 2 - low off / high on */
2181 /* 3 - low on / high on */
2182 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002184 ushort bios_ctrl; /* 12 BIOS control bits */
2185 /* bit 0 BIOS don't act as initiator. */
2186 /* bit 1 BIOS > 1 GB support */
2187 /* bit 2 BIOS > 2 Disk Support */
2188 /* bit 3 BIOS don't support removables */
2189 /* bit 4 BIOS support bootable CD */
2190 /* bit 5 BIOS scan enabled */
2191 /* bit 6 BIOS support multiple LUNs */
2192 /* bit 7 BIOS display of message */
2193 /* bit 8 SCAM disabled */
2194 /* bit 9 Reset SCSI bus during init. */
2195 /* bit 10 */
2196 /* bit 11 No verbose initialization. */
2197 /* bit 12 SCSI parity enabled */
2198 /* bit 13 */
2199 /* bit 14 */
2200 /* bit 15 */
2201 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2202 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2203 uchar max_host_qng; /* 15 maximum host queueing */
2204 uchar max_dvc_qng; /* maximum per device queuing */
2205 ushort dvc_cntl; /* 16 control bit for driver */
2206 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2207 ushort serial_number_word1; /* 18 Board serial number word 1 */
2208 ushort serial_number_word2; /* 19 Board serial number word 2 */
2209 ushort serial_number_word3; /* 20 Board serial number word 3 */
2210 ushort check_sum; /* 21 EEP check sum */
2211 uchar oem_name[16]; /* 22 OEM name */
2212 ushort dvc_err_code; /* 30 last device driver error code */
2213 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2214 ushort adv_err_addr; /* 32 last uc error address */
2215 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2216 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2217 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2218 ushort reserved36; /* 36 reserved */
2219 ushort reserved37; /* 37 reserved */
2220 ushort reserved38; /* 38 reserved */
2221 ushort reserved39; /* 39 reserved */
2222 ushort reserved40; /* 40 reserved */
2223 ushort reserved41; /* 41 reserved */
2224 ushort reserved42; /* 42 reserved */
2225 ushort reserved43; /* 43 reserved */
2226 ushort reserved44; /* 44 reserved */
2227 ushort reserved45; /* 45 reserved */
2228 ushort reserved46; /* 46 reserved */
2229 ushort reserved47; /* 47 reserved */
2230 ushort reserved48; /* 48 reserved */
2231 ushort reserved49; /* 49 reserved */
2232 ushort reserved50; /* 50 reserved */
2233 ushort reserved51; /* 51 reserved */
2234 ushort reserved52; /* 52 reserved */
2235 ushort reserved53; /* 53 reserved */
2236 ushort reserved54; /* 54 reserved */
2237 ushort reserved55; /* 55 reserved */
2238 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2239 ushort cisprt_msw; /* 57 CIS PTR MSW */
2240 ushort subsysvid; /* 58 SubSystem Vendor ID */
2241 ushort subsysid; /* 59 SubSystem ID */
2242 ushort reserved60; /* 60 reserved */
2243 ushort reserved61; /* 61 reserved */
2244 ushort reserved62; /* 62 reserved */
2245 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246} ADVEEP_38C0800_CONFIG;
2247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002248typedef struct adveep_38C1600_config {
2249 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002251 ushort cfg_lsw; /* 00 power up initialization */
2252 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
2253 /* clear - Func. 0 INTA, Func. 1 INTB */
2254 /* bit 13 set - Load CIS */
2255 /* bit 14 set - BIOS Enable */
2256 /* bit 15 set - Big Endian Mode */
2257 ushort cfg_msw; /* 01 unused */
2258 ushort disc_enable; /* 02 disconnect enable */
2259 ushort wdtr_able; /* 03 Wide DTR able */
2260 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2261 ushort start_motor; /* 05 send start up motor */
2262 ushort tagqng_able; /* 06 tag queuing able */
2263 ushort bios_scan; /* 07 BIOS device control */
2264 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002266 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2267 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002269 uchar scsi_reset_delay; /* 10 reset delay */
2270 uchar bios_id_lun; /* first boot device scsi id & lun */
2271 /* high nibble is lun */
2272 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002274 uchar termination_se; /* 11 0 - automatic */
2275 /* 1 - low off / high off */
2276 /* 2 - low off / high on */
2277 /* 3 - low on / high on */
2278 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002280 uchar termination_lvd; /* 11 0 - automatic */
2281 /* 1 - low off / high off */
2282 /* 2 - low off / high on */
2283 /* 3 - low on / high on */
2284 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002286 ushort bios_ctrl; /* 12 BIOS control bits */
2287 /* bit 0 BIOS don't act as initiator. */
2288 /* bit 1 BIOS > 1 GB support */
2289 /* bit 2 BIOS > 2 Disk Support */
2290 /* bit 3 BIOS don't support removables */
2291 /* bit 4 BIOS support bootable CD */
2292 /* bit 5 BIOS scan enabled */
2293 /* bit 6 BIOS support multiple LUNs */
2294 /* bit 7 BIOS display of message */
2295 /* bit 8 SCAM disabled */
2296 /* bit 9 Reset SCSI bus during init. */
2297 /* bit 10 Basic Integrity Checking disabled */
2298 /* bit 11 No verbose initialization. */
2299 /* bit 12 SCSI parity enabled */
2300 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
2301 /* bit 14 */
2302 /* bit 15 */
2303 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2304 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2305 uchar max_host_qng; /* 15 maximum host queueing */
2306 uchar max_dvc_qng; /* maximum per device queuing */
2307 ushort dvc_cntl; /* 16 control bit for driver */
2308 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2309 ushort serial_number_word1; /* 18 Board serial number word 1 */
2310 ushort serial_number_word2; /* 19 Board serial number word 2 */
2311 ushort serial_number_word3; /* 20 Board serial number word 3 */
2312 ushort check_sum; /* 21 EEP check sum */
2313 uchar oem_name[16]; /* 22 OEM name */
2314 ushort dvc_err_code; /* 30 last device driver error code */
2315 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2316 ushort adv_err_addr; /* 32 last uc error address */
2317 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2318 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2319 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2320 ushort reserved36; /* 36 reserved */
2321 ushort reserved37; /* 37 reserved */
2322 ushort reserved38; /* 38 reserved */
2323 ushort reserved39; /* 39 reserved */
2324 ushort reserved40; /* 40 reserved */
2325 ushort reserved41; /* 41 reserved */
2326 ushort reserved42; /* 42 reserved */
2327 ushort reserved43; /* 43 reserved */
2328 ushort reserved44; /* 44 reserved */
2329 ushort reserved45; /* 45 reserved */
2330 ushort reserved46; /* 46 reserved */
2331 ushort reserved47; /* 47 reserved */
2332 ushort reserved48; /* 48 reserved */
2333 ushort reserved49; /* 49 reserved */
2334 ushort reserved50; /* 50 reserved */
2335 ushort reserved51; /* 51 reserved */
2336 ushort reserved52; /* 52 reserved */
2337 ushort reserved53; /* 53 reserved */
2338 ushort reserved54; /* 54 reserved */
2339 ushort reserved55; /* 55 reserved */
2340 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2341 ushort cisprt_msw; /* 57 CIS PTR MSW */
2342 ushort subsysvid; /* 58 SubSystem Vendor ID */
2343 ushort subsysid; /* 59 SubSystem ID */
2344 ushort reserved60; /* 60 reserved */
2345 ushort reserved61; /* 61 reserved */
2346 ushort reserved62; /* 62 reserved */
2347 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348} ADVEEP_38C1600_CONFIG;
2349
2350/*
2351 * EEPROM Commands
2352 */
2353#define ASC_EEP_CMD_DONE 0x0200
2354#define ASC_EEP_CMD_DONE_ERR 0x0001
2355
2356/* cfg_word */
2357#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
2358
2359/* bios_ctrl */
2360#define BIOS_CTRL_BIOS 0x0001
2361#define BIOS_CTRL_EXTENDED_XLAT 0x0002
2362#define BIOS_CTRL_GT_2_DISK 0x0004
2363#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
2364#define BIOS_CTRL_BOOTABLE_CD 0x0010
2365#define BIOS_CTRL_MULTIPLE_LUN 0x0040
2366#define BIOS_CTRL_DISPLAY_MSG 0x0080
2367#define BIOS_CTRL_NO_SCAM 0x0100
2368#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
2369#define BIOS_CTRL_INIT_VERBOSE 0x0800
2370#define BIOS_CTRL_SCSI_PARITY 0x1000
2371#define BIOS_CTRL_AIPP_DIS 0x2000
2372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002373#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
2374#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002376#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
2377#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
2379/*
2380 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
2381 * a special 16K Adv Library and Microcode version. After the issue is
2382 * resolved, should restore 32K support.
2383 *
2384 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
2385 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002386#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
2387#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */
2388#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389
2390/*
2391 * Byte I/O register address from base of 'iop_base'.
2392 */
2393#define IOPB_INTR_STATUS_REG 0x00
2394#define IOPB_CHIP_ID_1 0x01
2395#define IOPB_INTR_ENABLES 0x02
2396#define IOPB_CHIP_TYPE_REV 0x03
2397#define IOPB_RES_ADDR_4 0x04
2398#define IOPB_RES_ADDR_5 0x05
2399#define IOPB_RAM_DATA 0x06
2400#define IOPB_RES_ADDR_7 0x07
2401#define IOPB_FLAG_REG 0x08
2402#define IOPB_RES_ADDR_9 0x09
2403#define IOPB_RISC_CSR 0x0A
2404#define IOPB_RES_ADDR_B 0x0B
2405#define IOPB_RES_ADDR_C 0x0C
2406#define IOPB_RES_ADDR_D 0x0D
2407#define IOPB_SOFT_OVER_WR 0x0E
2408#define IOPB_RES_ADDR_F 0x0F
2409#define IOPB_MEM_CFG 0x10
2410#define IOPB_RES_ADDR_11 0x11
2411#define IOPB_GPIO_DATA 0x12
2412#define IOPB_RES_ADDR_13 0x13
2413#define IOPB_FLASH_PAGE 0x14
2414#define IOPB_RES_ADDR_15 0x15
2415#define IOPB_GPIO_CNTL 0x16
2416#define IOPB_RES_ADDR_17 0x17
2417#define IOPB_FLASH_DATA 0x18
2418#define IOPB_RES_ADDR_19 0x19
2419#define IOPB_RES_ADDR_1A 0x1A
2420#define IOPB_RES_ADDR_1B 0x1B
2421#define IOPB_RES_ADDR_1C 0x1C
2422#define IOPB_RES_ADDR_1D 0x1D
2423#define IOPB_RES_ADDR_1E 0x1E
2424#define IOPB_RES_ADDR_1F 0x1F
2425#define IOPB_DMA_CFG0 0x20
2426#define IOPB_DMA_CFG1 0x21
2427#define IOPB_TICKLE 0x22
2428#define IOPB_DMA_REG_WR 0x23
2429#define IOPB_SDMA_STATUS 0x24
2430#define IOPB_SCSI_BYTE_CNT 0x25
2431#define IOPB_HOST_BYTE_CNT 0x26
2432#define IOPB_BYTE_LEFT_TO_XFER 0x27
2433#define IOPB_BYTE_TO_XFER_0 0x28
2434#define IOPB_BYTE_TO_XFER_1 0x29
2435#define IOPB_BYTE_TO_XFER_2 0x2A
2436#define IOPB_BYTE_TO_XFER_3 0x2B
2437#define IOPB_ACC_GRP 0x2C
2438#define IOPB_RES_ADDR_2D 0x2D
2439#define IOPB_DEV_ID 0x2E
2440#define IOPB_RES_ADDR_2F 0x2F
2441#define IOPB_SCSI_DATA 0x30
2442#define IOPB_RES_ADDR_31 0x31
2443#define IOPB_RES_ADDR_32 0x32
2444#define IOPB_SCSI_DATA_HSHK 0x33
2445#define IOPB_SCSI_CTRL 0x34
2446#define IOPB_RES_ADDR_35 0x35
2447#define IOPB_RES_ADDR_36 0x36
2448#define IOPB_RES_ADDR_37 0x37
2449#define IOPB_RAM_BIST 0x38
2450#define IOPB_PLL_TEST 0x39
2451#define IOPB_PCI_INT_CFG 0x3A
2452#define IOPB_RES_ADDR_3B 0x3B
2453#define IOPB_RFIFO_CNT 0x3C
2454#define IOPB_RES_ADDR_3D 0x3D
2455#define IOPB_RES_ADDR_3E 0x3E
2456#define IOPB_RES_ADDR_3F 0x3F
2457
2458/*
2459 * Word I/O register address from base of 'iop_base'.
2460 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002461#define IOPW_CHIP_ID_0 0x00 /* CID0 */
2462#define IOPW_CTRL_REG 0x02 /* CC */
2463#define IOPW_RAM_ADDR 0x04 /* LA */
2464#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002466#define IOPW_RISC_CSR 0x0A /* CSR */
2467#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
2468#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002470#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002472#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002474#define IOPW_EE_CMD 0x1A /* EC */
2475#define IOPW_EE_DATA 0x1C /* ED */
2476#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002478#define IOPW_Q_BASE 0x22 /* QB */
2479#define IOPW_QP 0x24 /* QP */
2480#define IOPW_IX 0x26 /* IX */
2481#define IOPW_SP 0x28 /* SP */
2482#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483#define IOPW_RES_ADDR_2C 0x2C
2484#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002485#define IOPW_SCSI_DATA 0x30 /* SD */
2486#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
2487#define IOPW_SCSI_CTRL 0x34 /* SC */
2488#define IOPW_HSHK_CFG 0x36 /* HCFG */
2489#define IOPW_SXFR_STATUS 0x36 /* SXS */
2490#define IOPW_SXFR_CNTL 0x38 /* SXL */
2491#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002493#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495/*
2496 * Doubleword I/O register address from base of 'iop_base'.
2497 */
2498#define IOPDW_RES_ADDR_0 0x00
2499#define IOPDW_RAM_DATA 0x04
2500#define IOPDW_RES_ADDR_8 0x08
2501#define IOPDW_RES_ADDR_C 0x0C
2502#define IOPDW_RES_ADDR_10 0x10
2503#define IOPDW_COMMA 0x14
2504#define IOPDW_COMMB 0x18
2505#define IOPDW_RES_ADDR_1C 0x1C
2506#define IOPDW_SDMA_ADDR0 0x20
2507#define IOPDW_SDMA_ADDR1 0x24
2508#define IOPDW_SDMA_COUNT 0x28
2509#define IOPDW_SDMA_ERROR 0x2C
2510#define IOPDW_RDMA_ADDR0 0x30
2511#define IOPDW_RDMA_ADDR1 0x34
2512#define IOPDW_RDMA_COUNT 0x38
2513#define IOPDW_RDMA_ERROR 0x3C
2514
2515#define ADV_CHIP_ID_BYTE 0x25
2516#define ADV_CHIP_ID_WORD 0x04C1
2517
2518#define ADV_SC_SCSI_BUS_RESET 0x2000
2519
2520#define ADV_INTR_ENABLE_HOST_INTR 0x01
2521#define ADV_INTR_ENABLE_SEL_INTR 0x02
2522#define ADV_INTR_ENABLE_DPR_INTR 0x04
2523#define ADV_INTR_ENABLE_RTA_INTR 0x08
2524#define ADV_INTR_ENABLE_RMA_INTR 0x10
2525#define ADV_INTR_ENABLE_RST_INTR 0x20
2526#define ADV_INTR_ENABLE_DPE_INTR 0x40
2527#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
2528
2529#define ADV_INTR_STATUS_INTRA 0x01
2530#define ADV_INTR_STATUS_INTRB 0x02
2531#define ADV_INTR_STATUS_INTRC 0x04
2532
2533#define ADV_RISC_CSR_STOP (0x0000)
2534#define ADV_RISC_TEST_COND (0x2000)
2535#define ADV_RISC_CSR_RUN (0x4000)
2536#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
2537
2538#define ADV_CTRL_REG_HOST_INTR 0x0100
2539#define ADV_CTRL_REG_SEL_INTR 0x0200
2540#define ADV_CTRL_REG_DPR_INTR 0x0400
2541#define ADV_CTRL_REG_RTA_INTR 0x0800
2542#define ADV_CTRL_REG_RMA_INTR 0x1000
2543#define ADV_CTRL_REG_RES_BIT14 0x2000
2544#define ADV_CTRL_REG_DPE_INTR 0x4000
2545#define ADV_CTRL_REG_POWER_DONE 0x8000
2546#define ADV_CTRL_REG_ANY_INTR 0xFF00
2547
2548#define ADV_CTRL_REG_CMD_RESET 0x00C6
2549#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
2550#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
2551#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
2552#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
2553
2554#define ADV_TICKLE_NOP 0x00
2555#define ADV_TICKLE_A 0x01
2556#define ADV_TICKLE_B 0x02
2557#define ADV_TICKLE_C 0x03
2558
2559#define ADV_SCSI_CTRL_RSTOUT 0x2000
2560
2561#define AdvIsIntPending(port) \
2562 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
2563
2564/*
2565 * SCSI_CFG0 Register bit definitions
2566 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002567#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
2568#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
2569#define EVEN_PARITY 0x1000 /* Select Even Parity */
2570#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
2571#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
2572#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
2573#define SCAM_EN 0x0080 /* Enable SCAM selection */
2574#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
2575#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
2576#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
2577#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
2579/*
2580 * SCSI_CFG1 Register bit definitions
2581 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002582#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
2583#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
2584#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
2585#define FILTER_SEL 0x0C00 /* Filter Period Selection */
2586#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
2587#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
2588#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
2589#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
2590#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
2591#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
2592#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
2593#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
2594#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
2595#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
2596#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
2598/*
2599 * Addendum for ASC-38C0800 Chip
2600 *
2601 * The ASC-38C1600 Chip uses the same definitions except that the
2602 * bus mode override bits [12:10] have been moved to byte register
2603 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
2604 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
2605 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
2606 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
2607 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
2608 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002609#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
2610#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
2611#define HVD 0x1000 /* HVD Device Detect */
2612#define LVD 0x0800 /* LVD Device Detect */
2613#define SE 0x0400 /* SE Device Detect */
2614#define TERM_LVD 0x00C0 /* LVD Termination Bits */
2615#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
2616#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
2617#define TERM_SE 0x0030 /* SE Termination Bits */
2618#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
2619#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
2620#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
2621#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
2622#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
2623#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
2624#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
2625#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
2627#define CABLE_ILLEGAL_A 0x7
2628 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
2629
2630#define CABLE_ILLEGAL_B 0xB
2631 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
2632
2633/*
2634 * MEM_CFG Register bit definitions
2635 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002636#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
2637#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
2638#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
2639#define RAM_SZ_2KB 0x00 /* 2 KB */
2640#define RAM_SZ_4KB 0x04 /* 4 KB */
2641#define RAM_SZ_8KB 0x08 /* 8 KB */
2642#define RAM_SZ_16KB 0x0C /* 16 KB */
2643#define RAM_SZ_32KB 0x10 /* 32 KB */
2644#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
2646/*
2647 * DMA_CFG0 Register bit definitions
2648 *
2649 * This register is only accessible to the host.
2650 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002651#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
2652#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
2653#define FIFO_THRESH_16B 0x00 /* 16 bytes */
2654#define FIFO_THRESH_32B 0x20 /* 32 bytes */
2655#define FIFO_THRESH_48B 0x30 /* 48 bytes */
2656#define FIFO_THRESH_64B 0x40 /* 64 bytes */
2657#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
2658#define FIFO_THRESH_96B 0x60 /* 96 bytes */
2659#define FIFO_THRESH_112B 0x70 /* 112 bytes */
2660#define START_CTL 0x0C /* DMA start conditions */
2661#define START_CTL_TH 0x00 /* Wait threshold level (default) */
2662#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
2663#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
2664#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
2665#define READ_CMD 0x03 /* Memory Read Method */
2666#define READ_CMD_MR 0x00 /* Memory Read */
2667#define READ_CMD_MRL 0x02 /* Memory Read Long */
2668#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
2670/*
2671 * ASC-38C0800 RAM BIST Register bit definitions
2672 */
2673#define RAM_TEST_MODE 0x80
2674#define PRE_TEST_MODE 0x40
2675#define NORMAL_MODE 0x00
2676#define RAM_TEST_DONE 0x10
2677#define RAM_TEST_STATUS 0x0F
2678#define RAM_TEST_HOST_ERROR 0x08
2679#define RAM_TEST_INTRAM_ERROR 0x04
2680#define RAM_TEST_RISC_ERROR 0x02
2681#define RAM_TEST_SCSI_ERROR 0x01
2682#define RAM_TEST_SUCCESS 0x00
2683#define PRE_TEST_VALUE 0x05
2684#define NORMAL_VALUE 0x00
2685
2686/*
2687 * ASC38C1600 Definitions
2688 *
2689 * IOPB_PCI_INT_CFG Bit Field Definitions
2690 */
2691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002692#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
2694/*
2695 * Bit 1 can be set to change the interrupt for the Function to operate in
2696 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
2697 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
2698 * mode, otherwise the operating mode is undefined.
2699 */
2700#define TOTEMPOLE 0x02
2701
2702/*
2703 * Bit 0 can be used to change the Int Pin for the Function. The value is
2704 * 0 by default for both Functions with Function 0 using INT A and Function
2705 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
2706 * INT A is used.
2707 *
2708 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
2709 * value specified in the PCI Configuration Space.
2710 */
2711#define INTAB 0x01
2712
2713/* a_advlib.h */
2714
2715/*
2716 * Adv Library Status Definitions
2717 */
2718#define ADV_TRUE 1
2719#define ADV_FALSE 0
2720#define ADV_NOERROR 1
2721#define ADV_SUCCESS 1
2722#define ADV_BUSY 0
2723#define ADV_ERROR (-1)
2724
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725/*
2726 * ADV_DVC_VAR 'warn_code' values
2727 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002728#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
2729#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
2730#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
2731#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
2732#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002734#define ADV_MAX_TID 15 /* max. target identifier */
2735#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
2737/*
2738 * Error code values are set in ADV_DVC_VAR 'err_code'.
2739 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002740#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
2741#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
2742#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
2743#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
2744#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
2745#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
2746#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
2747#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
2748#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
2749#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
2750#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
2751#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
2752#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
2753#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755/*
2756 * Fixed locations of microcode operating variables.
2757 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002758#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
2759#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
2760#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
2761#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
2762#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
2763#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
2764#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
2765#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
2766#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
2767#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
2768#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
2769#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
2770#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771#define ASC_MC_CHIP_TYPE 0x009A
2772#define ASC_MC_INTRB_CODE 0x009B
2773#define ASC_MC_WDTR_ABLE 0x009C
2774#define ASC_MC_SDTR_ABLE 0x009E
2775#define ASC_MC_TAGQNG_ABLE 0x00A0
2776#define ASC_MC_DISC_ENABLE 0x00A2
2777#define ASC_MC_IDLE_CMD_STATUS 0x00A4
2778#define ASC_MC_IDLE_CMD 0x00A6
2779#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
2780#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
2781#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
2782#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
2783#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
2784#define ASC_MC_SDTR_DONE 0x00B6
2785#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
2786#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
2787#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002788#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002790#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791#define ASC_MC_ICQ 0x0160
2792#define ASC_MC_IRQ 0x0164
2793#define ASC_MC_PPR_ABLE 0x017A
2794
2795/*
2796 * BIOS LRAM variable absolute offsets.
2797 */
2798#define BIOS_CODESEG 0x54
2799#define BIOS_CODELEN 0x56
2800#define BIOS_SIGNATURE 0x58
2801#define BIOS_VERSION 0x5A
2802
2803/*
2804 * Microcode Control Flags
2805 *
2806 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
2807 * and handled by the microcode.
2808 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002809#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
2810#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811
2812/*
2813 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
2814 */
2815#define HSHK_CFG_WIDE_XFR 0x8000
2816#define HSHK_CFG_RATE 0x0F00
2817#define HSHK_CFG_OFFSET 0x001F
2818
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002819#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
2820#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
2821#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
2822#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002824#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2825#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2826#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2827#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2828#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002830#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2831#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2832#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2833#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2834#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835/*
2836 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2837 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2838 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002839#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2840#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841
2842/*
2843 * All fields here are accessed by the board microcode and need to be
2844 * little-endian.
2845 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002846typedef struct adv_carr_t {
2847 ADV_VADDR carr_va; /* Carrier Virtual Address */
2848 ADV_PADDR carr_pa; /* Carrier Physical Address */
2849 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2850 /*
2851 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2852 *
2853 * next_vpa [3:1] Reserved Bits
2854 * next_vpa [0] Done Flag set in Response Queue.
2855 */
2856 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857} ADV_CARR_T;
2858
2859/*
2860 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2861 */
2862#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2863
2864#define ASC_RQ_DONE 0x00000001
2865#define ASC_RQ_GOOD 0x00000002
2866#define ASC_CQ_STOPPER 0x00000000
2867
2868#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2869
2870#define ADV_CARRIER_NUM_PAGE_CROSSING \
2871 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2872 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2873
2874#define ADV_CARRIER_BUFSIZE \
2875 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2876
2877/*
2878 * ASC_SCSI_REQ_Q 'a_flag' definitions
2879 *
2880 * The Adv Library should limit use to the lower nibble (4 bits) of
2881 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2882 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002883#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2884#define ADV_SCSIQ_DONE 0x02 /* request done */
2885#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002887#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2888#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2889#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890
2891/*
2892 * Adapter temporary configuration structure
2893 *
2894 * This structure can be discarded after initialization. Don't add
2895 * fields here needed after initialization.
2896 *
2897 * Field naming convention:
2898 *
2899 * *_enable indicates the field enables or disables a feature. The
2900 * value of the field is never reset.
2901 */
2902typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002903 ushort disc_enable; /* enable disconnection */
2904 uchar chip_version; /* chip version */
2905 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2906 ushort lib_version; /* Adv Library version number */
2907 ushort control_flag; /* Microcode Control Flag */
2908 ushort mcode_date; /* Microcode date */
2909 ushort mcode_version; /* Microcode version */
2910 ushort pci_slot_info; /* high byte device/function number */
2911 /* bits 7-3 device num., bits 2-0 function num. */
2912 /* low byte bus num. */
2913 ushort serial1; /* EEPROM serial number word 1 */
2914 ushort serial2; /* EEPROM serial number word 2 */
2915 ushort serial3; /* EEPROM serial number word 3 */
2916 struct device *dev; /* pointer to the pci dev structure for this board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917} ADV_DVC_CFG;
2918
2919struct adv_dvc_var;
2920struct adv_scsi_req_q;
2921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002922typedef void (*ADV_ISR_CALLBACK)
2923 (struct adv_dvc_var *, struct adv_scsi_req_q *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002925typedef void (*ADV_ASYNC_CALLBACK)
2926 (struct adv_dvc_var *, uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927
2928/*
2929 * Adapter operation variable structure.
2930 *
2931 * One structure is required per host adapter.
2932 *
2933 * Field naming convention:
2934 *
2935 * *_able indicates both whether a feature should be enabled or disabled
2936 * and whether a device isi capable of the feature. At initialization
2937 * this field may be set, but later if a device is found to be incapable
2938 * of the feature, the field is cleared.
2939 */
2940typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002941 AdvPortAddr iop_base; /* I/O port address */
2942 ushort err_code; /* fatal error code */
2943 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
2944 ADV_ISR_CALLBACK isr_callback;
2945 ADV_ASYNC_CALLBACK async_callback;
2946 ushort wdtr_able; /* try WDTR for a device */
2947 ushort sdtr_able; /* try SDTR for a device */
2948 ushort ultra_able; /* try SDTR Ultra speed for a device */
2949 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2950 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2951 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2952 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2953 ushort tagqng_able; /* try tagged queuing with a device */
2954 ushort ppr_able; /* PPR message capable per TID bitmask. */
2955 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2956 ushort start_motor; /* start motor command allowed */
2957 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2958 uchar chip_no; /* should be assigned by caller */
2959 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2960 uchar irq_no; /* IRQ number */
2961 ushort no_scam; /* scam_tolerant of EEPROM */
2962 struct asc_board *drv_ptr; /* driver pointer to private structure */
2963 uchar chip_scsi_id; /* chip SCSI target ID */
2964 uchar chip_type;
2965 uchar bist_err_code;
2966 ADV_CARR_T *carrier_buf;
2967 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2968 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2969 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2970 ushort carr_pending_cnt; /* Count of pending carriers. */
2971 /*
2972 * Note: The following fields will not be used after initialization. The
2973 * driver may discard the buffer after initialization is done.
2974 */
2975 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976} ADV_DVC_VAR;
2977
2978#define NO_OF_SG_PER_BLOCK 15
2979
2980typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002981 uchar reserved1;
2982 uchar reserved2;
2983 uchar reserved3;
2984 uchar sg_cnt; /* Valid entries in block. */
2985 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
2986 struct {
2987 ADV_PADDR sg_addr; /* SG element address. */
2988 ADV_DCNT sg_count; /* SG element count. */
2989 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990} ADV_SG_BLOCK;
2991
2992/*
2993 * ADV_SCSI_REQ_Q - microcode request structure
2994 *
2995 * All fields in this structure up to byte 60 are used by the microcode.
2996 * The microcode makes assumptions about the size and ordering of fields
2997 * in this structure. Do not change the structure definition here without
2998 * coordinating the change with the microcode.
2999 *
3000 * All fields accessed by microcode must be maintained in little_endian
3001 * order.
3002 */
3003typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003004 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
3005 uchar target_cmd;
3006 uchar target_id; /* Device target identifier. */
3007 uchar target_lun; /* Device target logical unit number. */
3008 ADV_PADDR data_addr; /* Data buffer physical address. */
3009 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
3010 ADV_PADDR sense_addr;
3011 ADV_PADDR carr_pa;
3012 uchar mflag;
3013 uchar sense_len;
3014 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
3015 uchar scsi_cntl;
3016 uchar done_status; /* Completion status. */
3017 uchar scsi_status; /* SCSI status byte. */
3018 uchar host_status; /* Ucode host status. */
3019 uchar sg_working_ix;
3020 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
3021 ADV_PADDR sg_real_addr; /* SG list physical address. */
3022 ADV_PADDR scsiq_rptr;
3023 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
3024 ADV_VADDR scsiq_ptr;
3025 ADV_VADDR carr_va;
3026 /*
3027 * End of microcode structure - 60 bytes. The rest of the structure
3028 * is used by the Adv Library and ignored by the microcode.
3029 */
3030 ADV_VADDR srb_ptr;
3031 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
3032 char *vdata_addr; /* Data buffer virtual address. */
3033 uchar a_flag;
3034 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035} ADV_SCSI_REQ_Q;
3036
3037/*
3038 * Microcode idle loop commands
3039 */
3040#define IDLE_CMD_COMPLETED 0
3041#define IDLE_CMD_STOP_CHIP 0x0001
3042#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
3043#define IDLE_CMD_SEND_INT 0x0004
3044#define IDLE_CMD_ABORT 0x0008
3045#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003046#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
3047#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048#define IDLE_CMD_SCSIREQ 0x0080
3049
3050#define IDLE_CMD_STATUS_SUCCESS 0x0001
3051#define IDLE_CMD_STATUS_FAILURE 0x0002
3052
3053/*
3054 * AdvSendIdleCmd() flag definitions.
3055 */
3056#define ADV_NOWAIT 0x01
3057
3058/*
3059 * Wait loop time out values.
3060 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003061#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
3062#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
3063#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
3064#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
3065#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003067#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
3068#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
3069#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
3070#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003072#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073
3074/*
3075 * Device drivers must define the following functions.
3076 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003077static inline ulong DvcEnterCritical(void);
3078static inline void DvcLeaveCritical(ulong);
3079static void DvcSleepMilliSecond(ADV_DCNT);
3080static uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
3081static void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
3082static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
3083 uchar *, ASC_SDCNT *, int);
3084static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
3086/*
3087 * Adv Library functions available to drivers.
3088 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003089static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3090static int AdvISR(ADV_DVC_VAR *);
3091static int AdvInitGetConfig(ADV_DVC_VAR *);
3092static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
3093static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
3094static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
3095static int AdvResetChipAndSB(ADV_DVC_VAR *);
3096static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
3098/*
3099 * Internal Adv Library functions.
3100 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003101static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
3102static void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3103static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
3104static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
3105static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
3106static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3107static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3108static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3109static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3110static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
3111static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
3112static void AdvWaitEEPCmd(AdvPortAddr);
3113static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114
3115/*
3116 * PCI Bus Definitions
3117 */
3118#define AscPCICmdRegBits_BusMastering 0x0007
3119#define AscPCICmdRegBits_ParErrRespCtrl 0x0040
3120
3121/* Read byte from a register. */
3122#define AdvReadByteRegister(iop_base, reg_off) \
3123 (ADV_MEM_READB((iop_base) + (reg_off)))
3124
3125/* Write byte to a register. */
3126#define AdvWriteByteRegister(iop_base, reg_off, byte) \
3127 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
3128
3129/* Read word (2 bytes) from a register. */
3130#define AdvReadWordRegister(iop_base, reg_off) \
3131 (ADV_MEM_READW((iop_base) + (reg_off)))
3132
3133/* Write word (2 bytes) to a register. */
3134#define AdvWriteWordRegister(iop_base, reg_off, word) \
3135 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
3136
3137/* Write dword (4 bytes) to a register. */
3138#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
3139 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
3140
3141/* Read byte from LRAM. */
3142#define AdvReadByteLram(iop_base, addr, byte) \
3143do { \
3144 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3145 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
3146} while (0)
3147
3148/* Write byte to LRAM. */
3149#define AdvWriteByteLram(iop_base, addr, byte) \
3150 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3151 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
3152
3153/* Read word (2 bytes) from LRAM. */
3154#define AdvReadWordLram(iop_base, addr, word) \
3155do { \
3156 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3157 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
3158} while (0)
3159
3160/* Write word (2 bytes) to LRAM. */
3161#define AdvWriteWordLram(iop_base, addr, word) \
3162 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3163 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3164
3165/* Write little-endian double word (4 bytes) to LRAM */
3166/* Because of unspecified C language ordering don't use auto-increment. */
3167#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
3168 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3169 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3170 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
3171 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3172 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3173 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
3174
3175/* Read word (2 bytes) from LRAM assuming that the address is already set. */
3176#define AdvReadWordAutoIncLram(iop_base) \
3177 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
3178
3179/* Write word (2 bytes) to LRAM assuming that the address is already set. */
3180#define AdvWriteWordAutoIncLram(iop_base, word) \
3181 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3182
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183/*
3184 * Define macro to check for Condor signature.
3185 *
3186 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
3187 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
3188 */
3189#define AdvFindSignature(iop_base) \
3190 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
3191 ADV_CHIP_ID_BYTE) && \
3192 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
3193 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
3194
3195/*
3196 * Define macro to Return the version number of the chip at 'iop_base'.
3197 *
3198 * The second parameter 'bus_type' is currently unused.
3199 */
3200#define AdvGetChipVersion(iop_base, bus_type) \
3201 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
3202
3203/*
3204 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
3205 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
3206 *
3207 * If the request has not yet been sent to the device it will simply be
3208 * aborted from RISC memory. If the request is disconnected it will be
3209 * aborted on reselection by sending an Abort Message to the target ID.
3210 *
3211 * Return value:
3212 * ADV_TRUE(1) - Queue was successfully aborted.
3213 * ADV_FALSE(0) - Queue was not found on the active queue list.
3214 */
3215#define AdvAbortQueue(asc_dvc, scsiq) \
3216 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
3217 (ADV_DCNT) (scsiq))
3218
3219/*
3220 * Send a Bus Device Reset Message to the specified target ID.
3221 *
3222 * All outstanding commands will be purged if sending the
3223 * Bus Device Reset Message is successful.
3224 *
3225 * Return Value:
3226 * ADV_TRUE(1) - All requests on the target are purged.
3227 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
3228 * are not purged.
3229 */
3230#define AdvResetDevice(asc_dvc, target_id) \
3231 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
3232 (ADV_DCNT) (target_id))
3233
3234/*
3235 * SCSI Wide Type definition.
3236 */
3237#define ADV_SCSI_BIT_ID_TYPE ushort
3238
3239/*
3240 * AdvInitScsiTarget() 'cntl_flag' options.
3241 */
3242#define ADV_SCAN_LUN 0x01
3243#define ADV_CAPINFO_NOLUN 0x02
3244
3245/*
3246 * Convert target id to target id bit mask.
3247 */
3248#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
3249
3250/*
3251 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
3252 */
3253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003254#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255#define QD_NO_ERROR 0x01
3256#define QD_ABORTED_BY_HOST 0x02
3257#define QD_WITH_ERROR 0x04
3258
3259#define QHSTA_NO_ERROR 0x00
3260#define QHSTA_M_SEL_TIMEOUT 0x11
3261#define QHSTA_M_DATA_OVER_RUN 0x12
3262#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
3263#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003264#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
3265#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
3266#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
3267#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
3268#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
3269#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
3270#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003272#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
3273#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
3274#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
3275#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
3276#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
3277#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
3278#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
3279#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280#define QHSTA_M_WTM_TIMEOUT 0x41
3281#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
3282#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
3283#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003284#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
3285#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
3286#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
3288/*
3289 * Default EEPROM Configuration structure defined in a_init.c.
3290 */
3291static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
3292static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
3293static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
3294
3295/*
3296 * DvcGetPhyAddr() flag arguments
3297 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003298#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
3299#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
3300#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
3301#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
3302#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
3303#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
3305/* Return the address that is aligned at the next doubleword >= to 'addr'. */
3306#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
3307#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
3308#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
3309
3310/*
3311 * Total contiguous memory needed for driver SG blocks.
3312 *
3313 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
3314 * number of scatter-gather elements the driver supports in a
3315 * single request.
3316 */
3317
3318#define ADV_SG_LIST_MAX_BYTE_SIZE \
3319 (sizeof(ADV_SG_BLOCK) * \
3320 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
3321
3322/*
3323 * Inquiry data structure and bitfield macros
3324 *
3325 * Using bitfields to access the subchar data isn't portable across
3326 * endianness, so instead mask and shift. Only quantities of more
3327 * than 1 bit are shifted, since the others are just tested for true
3328 * or false.
3329 */
3330
3331#define ADV_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f)
3332#define ADV_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5)
3333#define ADV_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f)
3334#define ADV_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80)
3335#define ADV_INQ_ANSI_VER(inq) ((inq)->ver & 0x07)
3336#define ADV_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3)
3337#define ADV_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6)
3338#define ADV_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f)
3339#define ADV_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40)
3340#define ADV_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80)
3341#define ADV_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01)
3342#define ADV_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02)
3343#define ADV_INQ_LINK_CMD(inq) ((inq)->flags & 0x08)
3344#define ADV_INQ_SYNC(inq) ((inq)->flags & 0x10)
3345#define ADV_INQ_WIDE16(inq) ((inq)->flags & 0x20)
3346#define ADV_INQ_WIDE32(inq) ((inq)->flags & 0x40)
3347#define ADV_INQ_REL_ADDR(inq) ((inq)->flags & 0x80)
3348#define ADV_INQ_INFO_UNIT(inq) ((inq)->info & 0x01)
3349#define ADV_INQ_QUICK_ARB(inq) ((inq)->info & 0x02)
3350#define ADV_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2)
3351
3352typedef struct {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003353 uchar periph; /* peripheral device type [0:4] */
3354 /* peripheral qualifier [5:7] */
3355 uchar devtype; /* device type modifier (for SCSI I) [0:6] */
3356 /* RMB - removable medium bit [7] */
3357 uchar ver; /* ANSI approved version [0:2] */
3358 /* ECMA version [3:5] */
3359 /* ISO version [6:7] */
3360 uchar byte3; /* response data format [0:3] */
3361 /* 0 SCSI 1 */
3362 /* 1 CCS */
3363 /* 2 SCSI-2 */
3364 /* 3-F reserved */
3365 /* reserved [4:5] */
3366 /* terminate I/O process bit (see 5.6.22) [6] */
3367 /* asynch. event notification (processor) [7] */
3368 uchar add_len; /* additional length */
3369 uchar res1; /* reserved */
3370 uchar res2; /* reserved */
3371 uchar flags; /* soft reset implemented [0] */
3372 /* command queuing [1] */
3373 /* reserved [2] */
3374 /* linked command for this logical unit [3] */
3375 /* synchronous data transfer [4] */
3376 /* wide bus 16 bit data transfer [5] */
3377 /* wide bus 32 bit data transfer [6] */
3378 /* relative addressing mode [7] */
3379 uchar vendor_id[8]; /* vendor identification */
3380 uchar product_id[16]; /* product identification */
3381 uchar product_rev_level[4]; /* product revision level */
3382 uchar vendor_specific[20]; /* vendor specific */
3383 uchar info; /* information unit supported [0] */
3384 /* quick arbitrate supported [1] */
3385 /* clocking field [2:3] */
3386 /* reserved [4:7] */
3387 uchar res3; /* reserved */
3388} ADV_SCSI_INQUIRY; /* 58 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389
3390/*
3391 * --- Driver Constants and Macros
3392 */
3393
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394/* Reference Scsi_Host hostdata */
3395#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
3396
3397/* asc_board_t flags */
3398#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003399#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400#define ASC_SELECT_QUEUE_DEPTHS 0x08
3401
3402#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
3403#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
3404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003405#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003407#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
3409#ifdef CONFIG_PROC_FS
3410/* /proc/scsi/advansys/[0...] related definitions */
3411#define ASC_PRTBUF_SIZE 2048
3412#define ASC_PRTLINE_SIZE 160
3413
3414#define ASC_PRT_NEXT() \
3415 if (cp) { \
3416 totlen += len; \
3417 leftlen -= len; \
3418 if (leftlen == 0) { \
3419 return totlen; \
3420 } \
3421 cp += len; \
3422 }
3423#endif /* CONFIG_PROC_FS */
3424
3425/* Asc Library return codes */
3426#define ASC_TRUE 1
3427#define ASC_FALSE 0
3428#define ASC_NOERROR 1
3429#define ASC_BUSY 0
3430#define ASC_ERROR (-1)
3431
3432/* struct scsi_cmnd function return codes */
3433#define STATUS_BYTE(byte) (byte)
3434#define MSG_BYTE(byte) ((byte) << 8)
3435#define HOST_BYTE(byte) ((byte) << 16)
3436#define DRIVER_BYTE(byte) ((byte) << 24)
3437
3438/*
3439 * The following definitions and macros are OS independent interfaces to
3440 * the queue functions:
3441 * REQ - SCSI request structure
3442 * REQP - pointer to SCSI request structure
3443 * REQPTID(reqp) - reqp's target id
3444 * REQPNEXT(reqp) - reqp's next pointer
3445 * REQPNEXTP(reqp) - pointer to reqp's next pointer
3446 * REQPTIME(reqp) - reqp's time stamp value
3447 * REQTIMESTAMP() - system time stamp value
3448 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003449typedef struct scsi_cmnd REQ, *REQP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450#define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
3451#define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
3452#define REQPTID(reqp) ((reqp)->device->id)
3453#define REQPTIME(reqp) ((reqp)->SCp.this_residual)
3454#define REQTIMESTAMP() (jiffies)
3455
3456#define REQTIMESTAT(function, ascq, reqp, tid) \
3457{ \
3458 /*
3459 * If the request time stamp is less than the system time stamp, then \
3460 * maybe the system time stamp wrapped. Set the request time to zero.\
3461 */ \
3462 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
3463 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
3464 } else { \
3465 /* Indicate an error occurred with the assertion. */ \
3466 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
3467 REQPTIME(reqp) = 0; \
3468 } \
3469 /* Handle first minimum time case without external initialization. */ \
3470 if (((ascq)->q_tot_cnt[tid] == 1) || \
3471 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
3472 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
3473 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
3474 (function), (tid), (ascq)->q_min_tim[tid]); \
3475 } \
3476 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
3477 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
3478 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
3479 (function), tid, (ascq)->q_max_tim[tid]); \
3480 } \
3481 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
3482 /* Reset the time stamp field. */ \
3483 REQPTIME(reqp) = 0; \
3484}
3485
3486/* asc_enqueue() flags */
3487#define ASC_FRONT 1
3488#define ASC_BACK 2
3489
3490/* asc_dequeue_list() argument */
3491#define ASC_TID_ALL (-1)
3492
3493/* Return non-zero, if the queue is empty. */
3494#define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
3495
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003497#define ASC_STATS(shost, counter)
3498#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003500#define ASC_STATS(shost, counter) \
3501 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003503#define ASC_STATS_ADD(shost, counter, count) \
3504 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505#endif /* ADVANSYS_STATS */
3506
3507#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
3508
3509/* If the result wraps when calculating tenths, return 0. */
3510#define ASC_TENTHS(num, den) \
3511 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
3512 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
3513
3514/*
3515 * Display a message to the console.
3516 */
3517#define ASC_PRINT(s) \
3518 { \
3519 printk("advansys: "); \
3520 printk(s); \
3521 }
3522
3523#define ASC_PRINT1(s, a1) \
3524 { \
3525 printk("advansys: "); \
3526 printk((s), (a1)); \
3527 }
3528
3529#define ASC_PRINT2(s, a1, a2) \
3530 { \
3531 printk("advansys: "); \
3532 printk((s), (a1), (a2)); \
3533 }
3534
3535#define ASC_PRINT3(s, a1, a2, a3) \
3536 { \
3537 printk("advansys: "); \
3538 printk((s), (a1), (a2), (a3)); \
3539 }
3540
3541#define ASC_PRINT4(s, a1, a2, a3, a4) \
3542 { \
3543 printk("advansys: "); \
3544 printk((s), (a1), (a2), (a3), (a4)); \
3545 }
3546
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547#ifndef ADVANSYS_DEBUG
3548
3549#define ASC_DBG(lvl, s)
3550#define ASC_DBG1(lvl, s, a1)
3551#define ASC_DBG2(lvl, s, a1, a2)
3552#define ASC_DBG3(lvl, s, a1, a2, a3)
3553#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
3554#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
3555#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
3556#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
3557#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3558#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
3559#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3560#define ASC_DBG_PRT_HEX(lvl, name, start, length)
3561#define ASC_DBG_PRT_CDB(lvl, cdb, len)
3562#define ASC_DBG_PRT_SENSE(lvl, sense, len)
3563#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
3564
3565#else /* ADVANSYS_DEBUG */
3566
3567/*
3568 * Debugging Message Levels:
3569 * 0: Errors Only
3570 * 1: High-Level Tracing
3571 * 2-N: Verbose Tracing
3572 */
3573
3574#define ASC_DBG(lvl, s) \
3575 { \
3576 if (asc_dbglvl >= (lvl)) { \
3577 printk(s); \
3578 } \
3579 }
3580
3581#define ASC_DBG1(lvl, s, a1) \
3582 { \
3583 if (asc_dbglvl >= (lvl)) { \
3584 printk((s), (a1)); \
3585 } \
3586 }
3587
3588#define ASC_DBG2(lvl, s, a1, a2) \
3589 { \
3590 if (asc_dbglvl >= (lvl)) { \
3591 printk((s), (a1), (a2)); \
3592 } \
3593 }
3594
3595#define ASC_DBG3(lvl, s, a1, a2, a3) \
3596 { \
3597 if (asc_dbglvl >= (lvl)) { \
3598 printk((s), (a1), (a2), (a3)); \
3599 } \
3600 }
3601
3602#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
3603 { \
3604 if (asc_dbglvl >= (lvl)) { \
3605 printk((s), (a1), (a2), (a3), (a4)); \
3606 } \
3607 }
3608
3609#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
3610 { \
3611 if (asc_dbglvl >= (lvl)) { \
3612 asc_prt_scsi_host(s); \
3613 } \
3614 }
3615
3616#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
3617 { \
3618 if (asc_dbglvl >= (lvl)) { \
3619 asc_prt_scsi_cmnd(s); \
3620 } \
3621 }
3622
3623#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
3624 { \
3625 if (asc_dbglvl >= (lvl)) { \
3626 asc_prt_asc_scsi_q(scsiqp); \
3627 } \
3628 }
3629
3630#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
3631 { \
3632 if (asc_dbglvl >= (lvl)) { \
3633 asc_prt_asc_qdone_info(qdone); \
3634 } \
3635 }
3636
3637#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
3638 { \
3639 if (asc_dbglvl >= (lvl)) { \
3640 asc_prt_adv_scsi_req_q(scsiqp); \
3641 } \
3642 }
3643
3644#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
3645 { \
3646 if (asc_dbglvl >= (lvl)) { \
3647 asc_prt_hex((name), (start), (length)); \
3648 } \
3649 }
3650
3651#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
3652 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
3653
3654#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
3655 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
3656
3657#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
3658 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
3659#endif /* ADVANSYS_DEBUG */
3660
3661#ifndef ADVANSYS_ASSERT
3662#define ASC_ASSERT(a)
3663#else /* ADVANSYS_ASSERT */
3664
3665#define ASC_ASSERT(a) \
3666 { \
3667 if (!(a)) { \
3668 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
3669 __FILE__, __LINE__); \
3670 } \
3671 }
3672
3673#endif /* ADVANSYS_ASSERT */
3674
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675/*
3676 * --- Driver Structures
3677 */
3678
3679#ifdef ADVANSYS_STATS
3680
3681/* Per board statistics structure */
3682struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003683 /* Driver Entrypoint Statistics */
3684 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
3685 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
3686 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
3687 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
3688 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
3689 ADV_DCNT done; /* # calls to request's scsi_done function */
3690 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
3691 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
3692 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
3693 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
3694 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
3695 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
3696 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
3697 ADV_DCNT exe_unknown; /* # unknown returns. */
3698 /* Data Transfer Statistics */
3699 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
3700 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
3701 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
3702 ADV_DCNT sg_elem; /* # scatter-gather elements */
3703 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704};
3705#endif /* ADVANSYS_STATS */
3706
3707/*
3708 * Request queuing structure
3709 */
3710typedef struct asc_queue {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003711 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
3712 REQP q_first[ADV_MAX_TID + 1]; /* first queued request */
3713 REQP q_last[ADV_MAX_TID + 1]; /* last queued request */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003715 short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */
3716 short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */
3717 ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */
3718 ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */
3719 ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */
3720 ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */
3721#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722} asc_queue_t;
3723
3724/*
3725 * Adv Library Request Structures
3726 *
3727 * The following two structures are used to process Wide Board requests.
3728 *
3729 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
3730 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
3731 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
3732 * Mid-Level SCSI request structure.
3733 *
3734 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
3735 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
3736 * up to 255 scatter-gather elements may be used per request or
3737 * ADV_SCSI_REQ_Q.
3738 *
3739 * Both structures must be 32 byte aligned.
3740 */
3741typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003742 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
3743 uchar align[32]; /* Sgblock structure padding. */
3744 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745} adv_sgblk_t;
3746
3747typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003748 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
3749 uchar align[32]; /* Request structure padding. */
3750 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
3751 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
3752 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753} adv_req_t;
3754
3755/*
3756 * Structure allocated for each board.
3757 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003758 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 * of the 'Scsi_Host' structure starting at the 'hostdata'
3760 * field. It is guaranteed to be allocated from DMA-able memory.
3761 */
3762typedef struct asc_board {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003763 int id; /* Board Id */
3764 uint flags; /* Board flags */
3765 union {
3766 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
3767 ADV_DVC_VAR adv_dvc_var; /* Wide board */
3768 } dvc_var;
3769 union {
3770 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
3771 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
3772 } dvc_cfg;
3773 ushort asc_n_io_port; /* Number I/O ports. */
3774 asc_queue_t active; /* Active command queue */
3775 asc_queue_t waiting; /* Waiting command queue */
3776 asc_queue_t done; /* Done command queue */
3777 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
3778 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
3779 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
3780 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
3781 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
3782 union {
3783 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
3784 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
3785 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
3786 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
3787 } eep_config;
3788 ulong last_reset; /* Saved last reset time */
3789 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003790 /* /proc/scsi/advansys/[0...] */
3791 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003793 struct asc_stats asc_stats; /* Board statistics */
3794#endif /* ADVANSYS_STATS */
3795 /*
3796 * The following fields are used only for Narrow Boards.
3797 */
3798 /* The following three structures must be in DMA-able memory. */
3799 ASC_SCSI_REQ_Q scsireqq;
3800 ASC_CAP_INFO cap_info;
3801 ASC_SCSI_INQUIRY inquiry;
3802 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
3803 /*
3804 * The following fields are used only for Wide Boards.
3805 */
3806 void __iomem *ioremap_addr; /* I/O Memory remap address. */
3807 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06003808 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003809 adv_req_t *orig_reqp; /* adv_req_t memory block. */
3810 adv_req_t *adv_reqp; /* Request structures. */
3811 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
3812 ushort bios_signature; /* BIOS Signature. */
3813 ushort bios_version; /* BIOS Version. */
3814 ushort bios_codeseg; /* BIOS Code Segment. */
3815 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816} asc_board_t;
3817
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06003819static int asc_board_count;
3820
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003822static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823
3824/*
3825 * Global structures required to issue a command.
3826 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003827static ASC_SCSI_Q asc_scsi_q = { {0} };
3828static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003831static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832#endif /* ADVANSYS_DEBUG */
3833
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834/*
3835 * --- Driver Function Prototypes
3836 *
3837 * advansys.h contains function prototypes for functions global to Linux.
3838 */
3839
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003840static int advansys_slave_configure(struct scsi_device *);
3841static void asc_scsi_done_list(struct scsi_cmnd *);
3842static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
3843static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
3844static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
3845static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
3846static void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
3847static void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3848static void adv_async_callback(ADV_DVC_VAR *, uchar);
3849static void asc_enqueue(asc_queue_t *, REQP, int);
3850static REQP asc_dequeue(asc_queue_t *, int);
3851static REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
3852static int asc_rmqueue(asc_queue_t *, REQP);
3853static void asc_execute_queue(asc_queue_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003855static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
3856static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
3857static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
3858static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
3859static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
3860static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
3861static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
3862static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
3863static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
3864static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865#endif /* CONFIG_PROC_FS */
3866
3867/* Declaration for Asc Library internal functions referenced by driver. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003868static int AscFindSignature(PortAddr);
3869static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
3871/* Statistics function prototypes. */
3872#ifdef ADVANSYS_STATS
3873#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003874static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
3875static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876#endif /* CONFIG_PROC_FS */
3877#endif /* ADVANSYS_STATS */
3878
3879/* Debug function prototypes. */
3880#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003881static void asc_prt_scsi_host(struct Scsi_Host *);
3882static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
3883static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
3884static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
3885static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
3886static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
3887static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
3888static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
3889static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
3890static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
3891static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892#endif /* ADVANSYS_DEBUG */
3893
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894#ifdef CONFIG_PROC_FS
3895/*
Matthew Wilcoxc304ec92007-07-30 09:18:45 -06003896 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 *
3898 * *buffer: I/O buffer
3899 * **start: if inout == FALSE pointer into buffer where user read should start
3900 * offset: current offset into a /proc/scsi/advansys/[0...] file
3901 * length: length of buffer
3902 * hostno: Scsi_Host host_no
3903 * inout: TRUE - user is writing; FALSE - user is reading
3904 *
3905 * Return the number of bytes read from or written to a
3906 * /proc/scsi/advansys/[0...] file.
3907 *
3908 * Note: This function uses the per board buffer 'prtbuf' which is
3909 * allocated when the board is initialized in advansys_detect(). The
3910 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
3911 * used to write to the buffer. The way asc_proc_copy() is written
3912 * if 'prtbuf' is too small it will not be overwritten. Instead the
3913 * user just won't get all the available statistics.
3914 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003915static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003917 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003919 asc_board_t *boardp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003920 char *cp;
3921 int cplen;
3922 int cnt;
3923 int totcnt;
3924 int leftlen;
3925 char *curbuf;
3926 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003928 int tgt_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929#endif /* ADVANSYS_STATS */
3930
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003931 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003933 /*
3934 * User write not supported.
3935 */
3936 if (inout == TRUE) {
3937 return (-ENOSYS);
3938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003940 /*
3941 * User read of /proc/scsi/advansys/[0...] file.
3942 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943
Matthew Wilcox2a437952007-07-26 11:00:51 -04003944 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003946 /* Copy read data starting at the beginning of the buffer. */
3947 *start = buffer;
3948 curbuf = buffer;
3949 advoffset = 0;
3950 totcnt = 0;
3951 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003953 /*
3954 * Get board configuration information.
3955 *
3956 * advansys_info() returns the board string from its own static buffer.
3957 */
Matthew Wilcox2a437952007-07-26 11:00:51 -04003958 cp = (char *)advansys_info(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003959 strcat(cp, "\n");
3960 cplen = strlen(cp);
3961 /* Copy board information. */
3962 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3963 totcnt += cnt;
3964 leftlen -= cnt;
3965 if (leftlen == 0) {
3966 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3967 return totcnt;
3968 }
3969 advoffset += cplen;
3970 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003972 /*
3973 * Display Wide Board BIOS Information.
3974 */
3975 if (ASC_WIDE_BOARD(boardp)) {
3976 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003977 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003978 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3979 cnt =
3980 asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
3981 cplen);
3982 totcnt += cnt;
3983 leftlen -= cnt;
3984 if (leftlen == 0) {
3985 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3986 return totcnt;
3987 }
3988 advoffset += cplen;
3989 curbuf += cnt;
3990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003992 /*
3993 * Display driver information for each device attached to the board.
3994 */
3995 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003996 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003997 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3998 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3999 totcnt += cnt;
4000 leftlen -= cnt;
4001 if (leftlen == 0) {
4002 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4003 return totcnt;
4004 }
4005 advoffset += cplen;
4006 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004008 /*
4009 * Display EEPROM configuration for the board.
4010 */
4011 cp = boardp->prtbuf;
4012 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04004013 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004014 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04004015 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004016 }
4017 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4018 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4019 totcnt += cnt;
4020 leftlen -= cnt;
4021 if (leftlen == 0) {
4022 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4023 return totcnt;
4024 }
4025 advoffset += cplen;
4026 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004028 /*
4029 * Display driver configuration and information for the board.
4030 */
4031 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04004032 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004033 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4034 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4035 totcnt += cnt;
4036 leftlen -= cnt;
4037 if (leftlen == 0) {
4038 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4039 return totcnt;
4040 }
4041 advoffset += cplen;
4042 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
4044#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004045 /*
4046 * Display driver statistics for the board.
4047 */
4048 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04004049 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004050 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
4051 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4052 totcnt += cnt;
4053 leftlen -= cnt;
4054 if (leftlen == 0) {
4055 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4056 return totcnt;
4057 }
4058 advoffset += cplen;
4059 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004061 /*
4062 * Display driver statistics for each target.
4063 */
4064 for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
4065 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04004066 cplen = asc_prt_target_stats(shost, tgt_id, cp,
4067 ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004068 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
4069 cnt =
4070 asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4071 cplen);
4072 totcnt += cnt;
4073 leftlen -= cnt;
4074 if (leftlen == 0) {
4075 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4076 return totcnt;
4077 }
4078 advoffset += cplen;
4079 curbuf += cnt;
4080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081#endif /* ADVANSYS_STATS */
4082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004083 /*
4084 * Display Asc Library dynamic configuration information
4085 * for the board.
4086 */
4087 cp = boardp->prtbuf;
4088 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04004089 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004090 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04004091 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004092 }
4093 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4094 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4095 totcnt += cnt;
4096 leftlen -= cnt;
4097 if (leftlen == 0) {
4098 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4099 return totcnt;
4100 }
4101 advoffset += cplen;
4102 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004104 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004106 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107}
4108#endif /* CONFIG_PROC_FS */
4109
4110/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 * advansys_info()
4112 *
4113 * Return suitable for printing on the console with the argument
4114 * adapter's configuration information.
4115 *
4116 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
4117 * otherwise the static 'info' array will be overrun.
4118 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004119static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004121 static char info[ASC_INFO_SIZE];
4122 asc_board_t *boardp;
4123 ASC_DVC_VAR *asc_dvc_varp;
4124 ADV_DVC_VAR *adv_dvc_varp;
4125 char *busname;
4126 int iolen;
4127 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004129 boardp = ASC_BOARDP(shost);
4130 if (ASC_NARROW_BOARD(boardp)) {
4131 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4132 ASC_DBG(1, "advansys_info: begin\n");
4133 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4134 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
4135 ASC_IS_ISAPNP) {
4136 busname = "ISA PnP";
4137 } else {
4138 busname = "ISA";
4139 }
4140 /* Don't reference 'shost->n_io_port'; It may be truncated. */
4141 sprintf(info,
4142 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
4143 ASC_VERSION, busname,
4144 (ulong)shost->io_port,
4145 (ulong)shost->io_port + boardp->asc_n_io_port -
4146 1, shost->irq, shost->dma_channel);
4147 } else {
4148 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
4149 busname = "VL";
4150 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
4151 busname = "EISA";
4152 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
4153 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
4154 == ASC_IS_PCI_ULTRA) {
4155 busname = "PCI Ultra";
4156 } else {
4157 busname = "PCI";
4158 }
4159 } else {
4160 busname = "?";
4161 ASC_PRINT2
4162 ("advansys_info: board %d: unknown bus type %d\n",
4163 boardp->id, asc_dvc_varp->bus_type);
4164 }
4165 /* Don't reference 'shost->n_io_port'; It may be truncated. */
4166 sprintf(info,
4167 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
4168 ASC_VERSION, busname,
4169 (ulong)shost->io_port,
4170 (ulong)shost->io_port + boardp->asc_n_io_port -
4171 1, shost->irq);
4172 }
4173 } else {
4174 /*
4175 * Wide Adapter Information
4176 *
4177 * Memory-mapped I/O is used instead of I/O space to access
4178 * the adapter, but display the I/O Port range. The Memory
4179 * I/O address is displayed through the driver /proc file.
4180 */
4181 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4182 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4183 iolen = ADV_3550_IOLEN;
4184 widename = "Ultra-Wide";
4185 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4186 iolen = ADV_38C0800_IOLEN;
4187 widename = "Ultra2-Wide";
4188 } else {
4189 iolen = ADV_38C1600_IOLEN;
4190 widename = "Ultra3-Wide";
4191 }
4192 sprintf(info,
4193 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
4194 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
4195 (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq);
4196 }
4197 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
4198 ASC_DBG(1, "advansys_info: end\n");
4199 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200}
4201
4202/*
4203 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
4204 *
4205 * This function always returns 0. Command return status is saved
4206 * in the 'scp' result field.
4207 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004208static int
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004209advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004211 struct Scsi_Host *shost;
4212 asc_board_t *boardp;
4213 ulong flags;
4214 struct scsi_cmnd *done_scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004216 shost = scp->device->host;
4217 boardp = ASC_BOARDP(shost);
4218 ASC_STATS(shost, queuecommand);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004220 /* host_lock taken by mid-level prior to call but need to protect */
4221 /* against own ISR */
4222 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004224 /*
4225 * Block new commands while handling a reset or abort request.
4226 */
4227 if (boardp->flags & ASC_HOST_IN_RESET) {
4228 ASC_DBG1(1,
4229 "advansys_queuecommand: scp 0x%lx blocked for reset request\n",
4230 (ulong)scp);
4231 scp->result = HOST_BYTE(DID_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004233 /*
4234 * Add blocked requests to the board's 'done' queue. The queued
4235 * requests will be completed at the end of the abort or reset
4236 * handling.
4237 */
4238 asc_enqueue(&boardp->done, scp, ASC_BACK);
4239 spin_unlock_irqrestore(&boardp->lock, flags);
4240 return 0;
4241 }
4242
4243 /*
4244 * Attempt to execute any waiting commands for the board.
4245 */
4246 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4247 ASC_DBG(1,
4248 "advansys_queuecommand: before asc_execute_queue() waiting\n");
4249 asc_execute_queue(&boardp->waiting);
4250 }
4251
4252 /*
4253 * Save the function pointer to Linux mid-level 'done' function
4254 * and attempt to execute the command.
4255 *
4256 * If ASC_NOERROR is returned the request has been added to the
4257 * board's 'active' queue and will be completed by the interrupt
4258 * handler.
4259 *
4260 * If ASC_BUSY is returned add the request to the board's per
4261 * target waiting list. This is the first time the request has
4262 * been tried. Add it to the back of the waiting list. It will be
4263 * retried later.
4264 *
4265 * If an error occurred, the request will have been placed on the
4266 * board's 'done' queue and must be completed before returning.
4267 */
4268 scp->scsi_done = done;
4269 switch (asc_execute_scsi_cmnd(scp)) {
4270 case ASC_NOERROR:
4271 break;
4272 case ASC_BUSY:
4273 asc_enqueue(&boardp->waiting, scp, ASC_BACK);
4274 break;
4275 case ASC_ERROR:
4276 default:
4277 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
4278 /* Interrupts could be enabled here. */
4279 asc_scsi_done_list(done_scp);
4280 break;
4281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004284 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285}
4286
4287/*
4288 * advansys_reset()
4289 *
4290 * Reset the bus associated with the command 'scp'.
4291 *
4292 * This function runs its own thread. Interrupts must be blocked but
4293 * sleeping is allowed and no locking other than for host structures is
4294 * required. Returns SUCCESS or FAILED.
4295 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004296static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004298 struct Scsi_Host *shost;
4299 asc_board_t *boardp;
4300 ASC_DVC_VAR *asc_dvc_varp;
4301 ADV_DVC_VAR *adv_dvc_varp;
4302 ulong flags;
4303 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4304 struct scsi_cmnd *tscp, *new_last_scp;
4305 int status;
4306 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004308 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
4310#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004311 if (scp->device->host != NULL) {
4312 ASC_STATS(scp->device->host, reset);
4313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314#endif /* ADVANSYS_STATS */
4315
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004316 if ((shost = scp->device->host) == NULL) {
4317 scp->result = HOST_BYTE(DID_ERROR);
4318 return FAILED;
4319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004321 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004323 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
4324 boardp->id);
4325 /*
4326 * Check for re-entrancy.
4327 */
4328 spin_lock_irqsave(&boardp->lock, flags);
4329 if (boardp->flags & ASC_HOST_IN_RESET) {
4330 spin_unlock_irqrestore(&boardp->lock, flags);
4331 return FAILED;
4332 }
4333 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004336 if (ASC_NARROW_BOARD(boardp)) {
4337 /*
4338 * Narrow Board
4339 */
4340 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004342 /*
4343 * Reset the chip and SCSI bus.
4344 */
4345 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
4346 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004348 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
4349 if (asc_dvc_varp->err_code) {
4350 ASC_PRINT2
4351 ("advansys_reset: board %d: SCSI bus reset error: 0x%x\n",
4352 boardp->id, asc_dvc_varp->err_code);
4353 ret = FAILED;
4354 } else if (status) {
4355 ASC_PRINT2
4356 ("advansys_reset: board %d: SCSI bus reset warning: 0x%x\n",
4357 boardp->id, status);
4358 } else {
4359 ASC_PRINT1
4360 ("advansys_reset: board %d: SCSI bus reset successful.\n",
4361 boardp->id);
4362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004364 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
4365 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004367 } else {
4368 /*
4369 * Wide Board
4370 *
4371 * If the suggest reset bus flags are set, then reset the bus.
4372 * Otherwise only reset the device.
4373 */
4374 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004376 /*
4377 * Reset the target's SCSI bus.
4378 */
4379 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
4380 switch (AdvResetChipAndSB(adv_dvc_varp)) {
4381 case ASC_TRUE:
4382 ASC_PRINT1
4383 ("advansys_reset: board %d: SCSI bus reset successful.\n",
4384 boardp->id);
4385 break;
4386 case ASC_FALSE:
4387 default:
4388 ASC_PRINT1
4389 ("advansys_reset: board %d: SCSI bus reset error.\n",
4390 boardp->id);
4391 ret = FAILED;
4392 break;
4393 }
4394 spin_lock_irqsave(&boardp->lock, flags);
4395 (void)AdvISR(adv_dvc_varp);
4396 }
4397 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004399 /*
4400 * Dequeue all board 'done' requests. A pointer to the last request
4401 * is returned in 'last_scp'.
4402 */
4403 done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004405 /*
4406 * Dequeue all board 'active' requests for all devices and set
4407 * the request status to DID_RESET. A pointer to the last request
4408 * is returned in 'last_scp'.
4409 */
4410 if (done_scp == NULL) {
4411 done_scp =
4412 asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL);
4413 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
4414 tscp->result = HOST_BYTE(DID_RESET);
4415 }
4416 } else {
4417 /* Append to 'done_scp' at the end with 'last_scp'. */
4418 ASC_ASSERT(last_scp != NULL);
4419 last_scp->host_scribble =
4420 (unsigned char *)asc_dequeue_list(&boardp->active,
4421 &new_last_scp,
4422 ASC_TID_ALL);
4423 if (new_last_scp != NULL) {
4424 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4425 for (tscp = REQPNEXT(last_scp); tscp;
4426 tscp = REQPNEXT(tscp)) {
4427 tscp->result = HOST_BYTE(DID_RESET);
4428 }
4429 last_scp = new_last_scp;
4430 }
4431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004433 /*
4434 * Dequeue all 'waiting' requests and set the request status
4435 * to DID_RESET.
4436 */
4437 if (done_scp == NULL) {
4438 done_scp =
4439 asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL);
4440 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
4441 tscp->result = HOST_BYTE(DID_RESET);
4442 }
4443 } else {
4444 /* Append to 'done_scp' at the end with 'last_scp'. */
4445 ASC_ASSERT(last_scp != NULL);
4446 last_scp->host_scribble =
4447 (unsigned char *)asc_dequeue_list(&boardp->waiting,
4448 &new_last_scp,
4449 ASC_TID_ALL);
4450 if (new_last_scp != NULL) {
4451 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4452 for (tscp = REQPNEXT(last_scp); tscp;
4453 tscp = REQPNEXT(tscp)) {
4454 tscp->result = HOST_BYTE(DID_RESET);
4455 }
4456 last_scp = new_last_scp;
4457 }
4458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004460 /* Save the time of the most recently completed reset. */
4461 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004463 /* Clear reset flag. */
4464 boardp->flags &= ~ASC_HOST_IN_RESET;
4465 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004467 /*
4468 * Complete all the 'done_scp' requests.
4469 */
4470 if (done_scp != NULL) {
4471 asc_scsi_done_list(done_scp);
4472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004474 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004476 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477}
4478
4479/*
4480 * advansys_biosparam()
4481 *
4482 * Translate disk drive geometry if the "BIOS greater than 1 GB"
4483 * support is enabled for a drive.
4484 *
4485 * ip (information pointer) is an int array with the following definition:
4486 * ip[0]: heads
4487 * ip[1]: sectors
4488 * ip[2]: cylinders
4489 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07004490static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004492 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004494 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004496 ASC_DBG(1, "advansys_biosparam: begin\n");
4497 ASC_STATS(sdev->host, biosparam);
4498 boardp = ASC_BOARDP(sdev->host);
4499 if (ASC_NARROW_BOARD(boardp)) {
4500 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
4501 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
4502 ip[0] = 255;
4503 ip[1] = 63;
4504 } else {
4505 ip[0] = 64;
4506 ip[1] = 32;
4507 }
4508 } else {
4509 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
4510 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
4511 ip[0] = 255;
4512 ip[1] = 63;
4513 } else {
4514 ip[0] = 64;
4515 ip[1] = 32;
4516 }
4517 }
4518 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
4519 ASC_DBG(1, "advansys_biosparam: end\n");
4520 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521}
4522
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06004523static struct scsi_host_template advansys_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004524 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004526 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004528 .name = "advansys",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004529 .info = advansys_info,
4530 .queuecommand = advansys_queuecommand,
4531 .eh_bus_reset_handler = advansys_reset,
4532 .bios_param = advansys_biosparam,
4533 .slave_configure = advansys_slave_configure,
4534 /*
4535 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06004536 * must be set. The flag will be cleared in advansys_board_found
4537 * for non-ISA adapters.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004538 */
4539 .unchecked_isa_dma = 1,
4540 /*
4541 * All adapters controlled by this driver are capable of large
4542 * scatter-gather lists. According to the mid-level SCSI documentation
4543 * this obviates any performance gain provided by setting
4544 * 'use_clustering'. But empirically while CPU utilization is increased
4545 * by enabling clustering, I/O throughput increases as well.
4546 */
4547 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550/*
4551 * --- Miscellaneous Driver Functions
4552 */
4553
4554/*
4555 * First-level interrupt handler.
4556 *
4557 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
4558 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
4559 * is not referenced. 'dev_id' could be used to identify an interrupt passed
4560 * to the AdvanSys driver which is for a device sharing an interrupt with
4561 * an AdvanSys adapter.
4562 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004563static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564{
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004565 unsigned long flags;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004566 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4567 struct scsi_cmnd *new_last_scp;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004568 struct Scsi_Host *shost = dev_id;
4569 asc_board_t *boardp = ASC_BOARDP(shost);
4570 irqreturn_t result = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004572 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
4573 spin_lock_irqsave(&boardp->lock, flags);
4574 if (ASC_NARROW_BOARD(boardp)) {
4575 /*
4576 * Narrow Board
4577 */
4578 if (AscIsIntPending(shost->io_port)) {
4579 result = IRQ_HANDLED;
4580 ASC_STATS(shost, interrupt);
4581 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
4582 AscISR(&boardp->dvc_var.asc_dvc_var);
4583 }
4584 } else {
4585 /*
4586 * Wide Board
4587 */
4588 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
4589 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
4590 result = IRQ_HANDLED;
4591 ASC_STATS(shost, interrupt);
4592 }
4593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004595 /*
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004596 * Start waiting requests and create a list of completed requests.
4597 *
4598 * If a reset request is being performed for the board, the reset
4599 * handler will complete pending requests after it has completed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004600 */
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004601 if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
4602 ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, "
4603 "last_scp 0x%p\n", done_scp, last_scp);
4604
4605 /* Start any waiting commands for the board. */
4606 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4607 ASC_DBG(1, "advansys_interrupt: before "
4608 "asc_execute_queue()\n");
4609 asc_execute_queue(&boardp->waiting);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004612 /*
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004613 * Add to the list of requests that must be completed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004614 *
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004615 * 'done_scp' will always be NULL on the first iteration of
4616 * this loop. 'last_scp' is set at the same time as 'done_scp'.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004617 */
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004618 if (done_scp == NULL) {
4619 done_scp = asc_dequeue_list(&boardp->done,
4620 &last_scp, ASC_TID_ALL);
4621 } else {
4622 ASC_ASSERT(last_scp != NULL);
4623 last_scp->host_scribble =
4624 (unsigned char *)asc_dequeue_list(&boardp->
4625 done,
4626 &new_last_scp,
4627 ASC_TID_ALL);
4628 if (new_last_scp != NULL) {
4629 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4630 last_scp = new_last_scp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004631 }
4632 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004633 }
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004634 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004636 /*
4637 * If interrupts were enabled on entry, then they
4638 * are now enabled here.
4639 *
4640 * Complete all requests on the done list.
4641 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004643 asc_scsi_done_list(done_scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004645 ASC_DBG(1, "advansys_interrupt: end\n");
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06004646 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647}
4648
4649/*
4650 * Set the number of commands to queue per device for the
4651 * specified host adapter.
4652 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004653static int advansys_slave_configure(struct scsi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004655 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004657 boardp = ASC_BOARDP(device->host);
4658 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
4659 /*
4660 * Save a pointer to the device and set its initial/maximum
4661 * queue depth. Only save the pointer for a lun0 dev though.
4662 */
4663 if (device->lun == 0)
4664 boardp->device[device->id] = device;
4665 if (device->tagged_supported) {
4666 if (ASC_NARROW_BOARD(boardp)) {
4667 scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
4668 boardp->dvc_var.asc_dvc_var.
4669 max_dvc_qng[device->id]);
4670 } else {
4671 scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
4672 boardp->dvc_var.adv_dvc_var.
4673 max_dvc_qng);
4674 }
4675 } else {
4676 scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun);
4677 }
4678 ASC_DBG4(1,
4679 "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n",
4680 (ulong)device, (ulong)boardp, device->id, device->queue_depth);
4681 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682}
4683
4684/*
4685 * Complete all requests on the singly linked list pointed
4686 * to by 'scp'.
4687 *
4688 * Interrupts can be enabled on entry.
4689 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004690static void asc_scsi_done_list(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004692 struct scsi_cmnd *tscp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004694 ASC_DBG(2, "asc_scsi_done_list: begin\n");
4695 while (scp != NULL) {
4696 asc_board_t *boardp;
4697 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004699 ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
4700 tscp = REQPNEXT(scp);
4701 scp->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004703 boardp = ASC_BOARDP(scp->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004705 if (ASC_NARROW_BOARD(boardp))
4706 dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
4707 else
4708 dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004710 if (scp->use_sg)
4711 dma_unmap_sg(dev,
4712 (struct scatterlist *)scp->request_buffer,
4713 scp->use_sg, scp->sc_data_direction);
4714 else if (scp->request_bufflen)
4715 dma_unmap_single(dev, scp->SCp.dma_handle,
4716 scp->request_bufflen,
4717 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004719 ASC_STATS(scp->device->host, done);
4720 ASC_ASSERT(scp->scsi_done != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004722 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004724 scp = tscp;
4725 }
4726 ASC_DBG(2, "asc_scsi_done_list: done\n");
4727 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728}
4729
4730/*
4731 * Execute a single 'Scsi_Cmnd'.
4732 *
4733 * The function 'done' is called when the request has been completed.
4734 *
4735 * Scsi_Cmnd:
4736 *
4737 * host - board controlling device
4738 * device - device to send command
4739 * target - target of device
4740 * lun - lun of device
4741 * cmd_len - length of SCSI CDB
4742 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
4743 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
4744 *
4745 * if (use_sg == 0) {
4746 * request_buffer - buffer address for request
4747 * request_bufflen - length of request buffer
4748 * } else {
4749 * request_buffer - pointer to scatterlist structure
4750 * }
4751 *
4752 * sense_buffer - sense command buffer
4753 *
4754 * result (4 bytes of an int):
4755 * Byte Meaning
4756 * 0 SCSI Status Byte Code
4757 * 1 SCSI One Byte Message Code
4758 * 2 Host Error Code
4759 * 3 Mid-Level Error Code
4760 *
4761 * host driver fields:
4762 * SCp - Scsi_Pointer used for command processing status
4763 * scsi_done - used to save caller's done function
4764 * host_scribble - used for pointer to another struct scsi_cmnd
4765 *
4766 * If this function returns ASC_NOERROR the request has been enqueued
4767 * on the board's 'active' queue and will be completed from the
4768 * interrupt handler.
4769 *
4770 * If this function returns ASC_NOERROR the request has been enqueued
4771 * on the board's 'done' queue and must be completed by the caller.
4772 *
4773 * If ASC_BUSY is returned the request will be enqueued by the
4774 * caller on the target's waiting queue and re-tried later.
4775 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004776static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004778 asc_board_t *boardp;
4779 ASC_DVC_VAR *asc_dvc_varp;
4780 ADV_DVC_VAR *adv_dvc_varp;
4781 ADV_SCSI_REQ_Q *adv_scsiqp;
4782 struct scsi_device *device;
4783 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004785 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
4786 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004788 boardp = ASC_BOARDP(scp->device->host);
4789 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004791 if (ASC_NARROW_BOARD(boardp)) {
4792 /*
4793 * Build and execute Narrow Board request.
4794 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004796 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004798 /*
4799 * Build Asc Library request structure using the
4800 * global structures 'asc_scsi_req' and 'asc_sg_head'.
4801 *
4802 * If an error is returned, then the request has been
4803 * queued on the board done queue. It will be completed
4804 * by the caller.
4805 *
4806 * asc_build_req() can not return ASC_BUSY.
4807 */
4808 if (asc_build_req(boardp, scp) == ASC_ERROR) {
4809 ASC_STATS(scp->device->host, build_error);
4810 return ASC_ERROR;
4811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004813 /*
4814 * Execute the command. If there is no error, add the command
4815 * to the active queue.
4816 */
4817 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
4818 case ASC_NOERROR:
4819 ASC_STATS(scp->device->host, exe_noerror);
4820 /*
4821 * Increment monotonically increasing per device successful
4822 * request counter. Wrapping doesn't matter.
4823 */
4824 boardp->reqcnt[scp->device->id]++;
4825 asc_enqueue(&boardp->active, scp, ASC_BACK);
4826 ASC_DBG(1,
4827 "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
4828 break;
4829 case ASC_BUSY:
4830 /*
4831 * Caller will enqueue request on the target's waiting queue
4832 * and retry later.
4833 */
4834 ASC_STATS(scp->device->host, exe_busy);
4835 break;
4836 case ASC_ERROR:
4837 ASC_PRINT2
4838 ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
4839 boardp->id, asc_dvc_varp->err_code);
4840 ASC_STATS(scp->device->host, exe_error);
4841 scp->result = HOST_BYTE(DID_ERROR);
4842 asc_enqueue(&boardp->done, scp, ASC_BACK);
4843 break;
4844 default:
4845 ASC_PRINT2
4846 ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n",
4847 boardp->id, asc_dvc_varp->err_code);
4848 ASC_STATS(scp->device->host, exe_unknown);
4849 scp->result = HOST_BYTE(DID_ERROR);
4850 asc_enqueue(&boardp->done, scp, ASC_BACK);
4851 break;
4852 }
4853 } else {
4854 /*
4855 * Build and execute Wide Board request.
4856 */
4857 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004859 /*
4860 * Build and get a pointer to an Adv Library request structure.
4861 *
4862 * If the request is successfully built then send it below,
4863 * otherwise return with an error.
4864 */
4865 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
4866 case ASC_NOERROR:
4867 ASC_DBG(3,
4868 "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
4869 break;
4870 case ASC_BUSY:
4871 ASC_DBG(1,
4872 "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
4873 /*
4874 * If busy is returned the request has not been enqueued.
4875 * It will be enqueued by the caller on the target's waiting
4876 * queue and retried later.
4877 *
4878 * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg'
4879 * count wide board busy conditions. They are updated in
4880 * adv_build_req and adv_get_sglist, respectively.
4881 */
4882 return ASC_BUSY;
4883 case ASC_ERROR:
4884 /*
4885 * If an error is returned, then the request has been
4886 * queued on the board done queue. It will be completed
4887 * by the caller.
4888 */
4889 default:
4890 ASC_DBG(1,
4891 "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
4892 ASC_STATS(scp->device->host, build_error);
4893 return ASC_ERROR;
4894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004896 /*
4897 * Execute the command. If there is no error, add the command
4898 * to the active queue.
4899 */
4900 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
4901 case ASC_NOERROR:
4902 ASC_STATS(scp->device->host, exe_noerror);
4903 /*
4904 * Increment monotonically increasing per device successful
4905 * request counter. Wrapping doesn't matter.
4906 */
4907 boardp->reqcnt[scp->device->id]++;
4908 asc_enqueue(&boardp->active, scp, ASC_BACK);
4909 ASC_DBG(1,
4910 "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
4911 break;
4912 case ASC_BUSY:
4913 /*
4914 * Caller will enqueue request on the target's waiting queue
4915 * and retry later.
4916 */
4917 ASC_STATS(scp->device->host, exe_busy);
4918 break;
4919 case ASC_ERROR:
4920 ASC_PRINT2
4921 ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
4922 boardp->id, adv_dvc_varp->err_code);
4923 ASC_STATS(scp->device->host, exe_error);
4924 scp->result = HOST_BYTE(DID_ERROR);
4925 asc_enqueue(&boardp->done, scp, ASC_BACK);
4926 break;
4927 default:
4928 ASC_PRINT2
4929 ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n",
4930 boardp->id, adv_dvc_varp->err_code);
4931 ASC_STATS(scp->device->host, exe_unknown);
4932 scp->result = HOST_BYTE(DID_ERROR);
4933 asc_enqueue(&boardp->done, scp, ASC_BACK);
4934 break;
4935 }
4936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004938 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
4939 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940}
4941
4942/*
4943 * Build a request structure for the Asc Library (Narrow Board).
4944 *
4945 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
4946 * used to build the request.
4947 *
4948 * If an error occurs, then queue the request on the board done
4949 * queue and return ASC_ERROR.
4950 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004951static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004953 struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004954
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004955 /*
4956 * Mutually exclusive access is required to 'asc_scsi_q' and
4957 * 'asc_sg_head' until after the request is started.
4958 */
4959 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004960
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004961 /*
4962 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
4963 */
4964 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004966 /*
4967 * Build the ASC_SCSI_Q request.
4968 *
4969 * For narrow boards a CDB length maximum of 12 bytes
4970 * is supported.
4971 */
4972 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
4973 ASC_PRINT3
4974 ("asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n",
4975 boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN);
4976 scp->result = HOST_BYTE(DID_ERROR);
4977 asc_enqueue(&boardp->done, scp, ASC_BACK);
4978 return ASC_ERROR;
4979 }
4980 asc_scsi_q.cdbptr = &scp->cmnd[0];
4981 asc_scsi_q.q2.cdb_len = scp->cmd_len;
4982 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
4983 asc_scsi_q.q1.target_lun = scp->device->lun;
4984 asc_scsi_q.q2.target_ix =
4985 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
4986 asc_scsi_q.q1.sense_addr =
4987 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4988 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004990 /*
4991 * If there are any outstanding requests for the current target,
4992 * then every 255th request send an ORDERED request. This heuristic
4993 * tries to retain the benefit of request sorting while preventing
4994 * request starvation. 255 is the max number of tags or pending commands
4995 * a device may have outstanding.
4996 *
4997 * The request count is incremented below for every successfully
4998 * started request.
4999 *
5000 */
5001 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
5002 (boardp->reqcnt[scp->device->id] % 255) == 0) {
5003 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
5004 } else {
5005 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
5006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005008 /*
5009 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
5010 * buffer command.
5011 */
5012 if (scp->use_sg == 0) {
5013 /*
5014 * CDB request of single contiguous buffer.
5015 */
5016 ASC_STATS(scp->device->host, cont_cnt);
5017 scp->SCp.dma_handle = scp->request_bufflen ?
5018 dma_map_single(dev, scp->request_buffer,
5019 scp->request_bufflen,
5020 scp->sc_data_direction) : 0;
5021 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
5022 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
5023 ASC_STATS_ADD(scp->device->host, cont_xfer,
5024 ASC_CEILING(scp->request_bufflen, 512));
5025 asc_scsi_q.q1.sg_queue_cnt = 0;
5026 asc_scsi_q.sg_head = NULL;
5027 } else {
5028 /*
5029 * CDB scatter-gather request list.
5030 */
5031 int sgcnt;
5032 int use_sg;
5033 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005035 slp = (struct scatterlist *)scp->request_buffer;
5036 use_sg =
5037 dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005039 if (use_sg > scp->device->host->sg_tablesize) {
5040 ASC_PRINT3
5041 ("asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
5042 boardp->id, use_sg,
5043 scp->device->host->sg_tablesize);
5044 dma_unmap_sg(dev, slp, scp->use_sg,
5045 scp->sc_data_direction);
5046 scp->result = HOST_BYTE(DID_ERROR);
5047 asc_enqueue(&boardp->done, scp, ASC_BACK);
5048 return ASC_ERROR;
5049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005051 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005053 /*
5054 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
5055 * structure to point to it.
5056 */
5057 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005059 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
5060 asc_scsi_q.sg_head = &asc_sg_head;
5061 asc_scsi_q.q1.data_cnt = 0;
5062 asc_scsi_q.q1.data_addr = 0;
5063 /* This is a byte value, otherwise it would need to be swapped. */
5064 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
5065 ASC_STATS_ADD(scp->device->host, sg_elem,
5066 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005068 /*
5069 * Convert scatter-gather list into ASC_SG_HEAD list.
5070 */
5071 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
5072 asc_sg_head.sg_list[sgcnt].addr =
5073 cpu_to_le32(sg_dma_address(slp));
5074 asc_sg_head.sg_list[sgcnt].bytes =
5075 cpu_to_le32(sg_dma_len(slp));
5076 ASC_STATS_ADD(scp->device->host, sg_xfer,
5077 ASC_CEILING(sg_dma_len(slp), 512));
5078 }
5079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005081 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
5082 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005084 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085}
5086
5087/*
5088 * Build a request structure for the Adv Library (Wide Board).
5089 *
5090 * If an adv_req_t can not be allocated to issue the request,
5091 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
5092 *
5093 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
5094 * microcode for DMA addresses or math operations are byte swapped
5095 * to little-endian order.
5096 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005097static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005099 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005101 adv_req_t *reqp;
5102 ADV_SCSI_REQ_Q *scsiqp;
5103 int i;
5104 int ret;
5105 struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005107 /*
5108 * Allocate an adv_req_t structure from the board to execute
5109 * the command.
5110 */
5111 if (boardp->adv_reqp == NULL) {
5112 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
5113 ASC_STATS(scp->device->host, adv_build_noreq);
5114 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005116 reqp = boardp->adv_reqp;
5117 boardp->adv_reqp = reqp->next_reqp;
5118 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005121 /*
5122 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
5123 */
5124 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005126 /*
5127 * Initialize the structure.
5128 */
5129 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005131 /*
5132 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
5133 */
5134 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005136 /*
5137 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
5138 */
5139 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005141 /*
5142 * Build the ADV_SCSI_REQ_Q request.
5143 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005145 /*
5146 * Set CDB length and copy it to the request structure.
5147 * For wide boards a CDB length maximum of 16 bytes
5148 * is supported.
5149 */
5150 if (scp->cmd_len > ADV_MAX_CDB_LEN) {
5151 ASC_PRINT3
5152 ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
5153 boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
5154 scp->result = HOST_BYTE(DID_ERROR);
5155 asc_enqueue(&boardp->done, scp, ASC_BACK);
5156 return ASC_ERROR;
5157 }
5158 scsiqp->cdb_len = scp->cmd_len;
5159 /* Copy first 12 CDB bytes to cdb[]. */
5160 for (i = 0; i < scp->cmd_len && i < 12; i++) {
5161 scsiqp->cdb[i] = scp->cmnd[i];
5162 }
5163 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
5164 for (; i < scp->cmd_len; i++) {
5165 scsiqp->cdb16[i - 12] = scp->cmnd[i];
5166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005168 scsiqp->target_id = scp->device->id;
5169 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005171 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
5172 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005174 /*
5175 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
5176 * buffer command.
5177 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005179 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
5180 scsiqp->vdata_addr = scp->request_buffer;
5181 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
5182
5183 if (scp->use_sg == 0) {
5184 /*
5185 * CDB request of single contiguous buffer.
5186 */
5187 reqp->sgblkp = NULL;
5188 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
5189 if (scp->request_bufflen) {
5190 scsiqp->vdata_addr = scp->request_buffer;
5191 scp->SCp.dma_handle =
5192 dma_map_single(dev, scp->request_buffer,
5193 scp->request_bufflen,
5194 scp->sc_data_direction);
5195 } else {
5196 scsiqp->vdata_addr = NULL;
5197 scp->SCp.dma_handle = 0;
5198 }
5199 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
5200 scsiqp->sg_list_ptr = NULL;
5201 scsiqp->sg_real_addr = 0;
5202 ASC_STATS(scp->device->host, cont_cnt);
5203 ASC_STATS_ADD(scp->device->host, cont_xfer,
5204 ASC_CEILING(scp->request_bufflen, 512));
5205 } else {
5206 /*
5207 * CDB scatter-gather request list.
5208 */
5209 struct scatterlist *slp;
5210 int use_sg;
5211
5212 slp = (struct scatterlist *)scp->request_buffer;
5213 use_sg =
5214 dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
5215
5216 if (use_sg > ADV_MAX_SG_LIST) {
5217 ASC_PRINT3
5218 ("adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
5219 boardp->id, use_sg,
5220 scp->device->host->sg_tablesize);
5221 dma_unmap_sg(dev, slp, scp->use_sg,
5222 scp->sc_data_direction);
5223 scp->result = HOST_BYTE(DID_ERROR);
5224 asc_enqueue(&boardp->done, scp, ASC_BACK);
5225
5226 /*
5227 * Free the 'adv_req_t' structure by adding it back to the
5228 * board free list.
5229 */
5230 reqp->next_reqp = boardp->adv_reqp;
5231 boardp->adv_reqp = reqp;
5232
5233 return ASC_ERROR;
5234 }
5235
5236 if ((ret =
5237 adv_get_sglist(boardp, reqp, scp,
5238 use_sg)) != ADV_SUCCESS) {
5239 /*
5240 * Free the adv_req_t structure by adding it back to the
5241 * board free list.
5242 */
5243 reqp->next_reqp = boardp->adv_reqp;
5244 boardp->adv_reqp = reqp;
5245
5246 return ret;
5247 }
5248
5249 ASC_STATS(scp->device->host, sg_cnt);
5250 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
5251 }
5252
5253 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
5254 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
5255
5256 *adv_scsiqpp = scsiqp;
5257
5258 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259}
5260
5261/*
5262 * Build scatter-gather list for Adv Library (Wide Board).
5263 *
5264 * Additional ADV_SG_BLOCK structures will need to be allocated
5265 * if the total number of scatter-gather elements exceeds
5266 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
5267 * assumed to be physically contiguous.
5268 *
5269 * Return:
5270 * ADV_SUCCESS(1) - SG List successfully created
5271 * ADV_ERROR(-1) - SG List creation failed
5272 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005273static int
5274adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
5275 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005277 adv_sgblk_t *sgblkp;
5278 ADV_SCSI_REQ_Q *scsiqp;
5279 struct scatterlist *slp;
5280 int sg_elem_cnt;
5281 ADV_SG_BLOCK *sg_block, *prev_sg_block;
5282 ADV_PADDR sg_block_paddr;
5283 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005285 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
5286 slp = (struct scatterlist *)scp->request_buffer;
5287 sg_elem_cnt = use_sg;
5288 prev_sg_block = NULL;
5289 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005291 do {
5292 /*
5293 * Allocate a 'adv_sgblk_t' structure from the board free
5294 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
5295 * (15) scatter-gather elements.
5296 */
5297 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
5298 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
5299 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005301 /*
5302 * Allocation failed. Free 'adv_sgblk_t' structures already
5303 * allocated for the request.
5304 */
5305 while ((sgblkp = reqp->sgblkp) != NULL) {
5306 /* Remove 'sgblkp' from the request list. */
5307 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005309 /* Add 'sgblkp' to the board free list. */
5310 sgblkp->next_sgblkp = boardp->adv_sgblkp;
5311 boardp->adv_sgblkp = sgblkp;
5312 }
5313 return ASC_BUSY;
5314 } else {
5315 /* Complete 'adv_sgblk_t' board allocation. */
5316 boardp->adv_sgblkp = sgblkp->next_sgblkp;
5317 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005319 /*
5320 * Get 8 byte aligned virtual and physical addresses for
5321 * the allocated ADV_SG_BLOCK structure.
5322 */
5323 sg_block =
5324 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
5325 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005327 /*
5328 * Check if this is the first 'adv_sgblk_t' for the request.
5329 */
5330 if (reqp->sgblkp == NULL) {
5331 /* Request's first scatter-gather block. */
5332 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005334 /*
5335 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
5336 * address pointers.
5337 */
5338 scsiqp->sg_list_ptr = sg_block;
5339 scsiqp->sg_real_addr =
5340 cpu_to_le32(sg_block_paddr);
5341 } else {
5342 /* Request's second or later scatter-gather block. */
5343 sgblkp->next_sgblkp = reqp->sgblkp;
5344 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005346 /*
5347 * Point the previous ADV_SG_BLOCK structure to
5348 * the newly allocated ADV_SG_BLOCK structure.
5349 */
5350 ASC_ASSERT(prev_sg_block != NULL);
5351 prev_sg_block->sg_ptr =
5352 cpu_to_le32(sg_block_paddr);
5353 }
5354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005356 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
5357 sg_block->sg_list[i].sg_addr =
5358 cpu_to_le32(sg_dma_address(slp));
5359 sg_block->sg_list[i].sg_count =
5360 cpu_to_le32(sg_dma_len(slp));
5361 ASC_STATS_ADD(scp->device->host, sg_xfer,
5362 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005364 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
5365 sg_block->sg_cnt = i + 1;
5366 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
5367 return ADV_SUCCESS;
5368 }
5369 slp++;
5370 }
5371 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
5372 prev_sg_block = sg_block;
5373 }
5374 while (1);
5375 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376}
5377
5378/*
5379 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
5380 *
5381 * Interrupt callback function for the Narrow SCSI Asc Library.
5382 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005383static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005385 asc_board_t *boardp;
5386 struct scsi_cmnd *scp;
5387 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005389 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
5390 (ulong)asc_dvc_varp, (ulong)qdonep);
5391 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005393 /*
5394 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
5395 * command that has been completed.
5396 */
5397 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
5398 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005400 if (scp == NULL) {
5401 ASC_PRINT("asc_isr_callback: scp is NULL\n");
5402 return;
5403 }
5404 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005406 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005407 ASC_STATS(shost, callback);
5408 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005410 /*
5411 * If the request isn't found on the active queue, it may
5412 * have been removed to handle a reset request.
5413 * Display a message and return.
5414 */
5415 boardp = ASC_BOARDP(shost);
5416 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
5417 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
5418 ASC_PRINT2
5419 ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n",
5420 boardp->id, (ulong)scp);
5421 return;
5422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005424 /*
5425 * 'qdonep' contains the command's ending status.
5426 */
5427 switch (qdonep->d3.done_stat) {
5428 case QD_NO_ERROR:
5429 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
5430 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005432 /*
5433 * If an INQUIRY command completed successfully, then call
5434 * the AscInquiryHandling() function to set-up the device.
5435 */
5436 if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 &&
5437 (scp->request_bufflen - qdonep->remain_bytes) >= 8) {
5438 AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7,
5439 (ASC_SCSI_INQUIRY *)scp->
5440 request_buffer);
5441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005442
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005443 /*
5444 * Check for an underrun condition.
5445 *
5446 * If there was no error and an underrun condition, then
5447 * then return the number of underrun bytes.
5448 */
5449 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
5450 qdonep->remain_bytes <= scp->request_bufflen) {
5451 ASC_DBG1(1,
5452 "asc_isr_callback: underrun condition %u bytes\n",
5453 (unsigned)qdonep->remain_bytes);
5454 scp->resid = qdonep->remain_bytes;
5455 }
5456 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005457
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005458 case QD_WITH_ERROR:
5459 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
5460 switch (qdonep->d3.host_stat) {
5461 case QHSTA_NO_ERROR:
5462 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
5463 ASC_DBG(2,
5464 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
5465 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
5466 sizeof(scp->sense_buffer));
5467 /*
5468 * Note: The 'status_byte()' macro used by target drivers
5469 * defined in scsi.h shifts the status byte returned by
5470 * host drivers right by 1 bit. This is why target drivers
5471 * also use right shifted status byte definitions. For
5472 * instance target drivers use CHECK_CONDITION, defined to
5473 * 0x1, instead of the SCSI defined check condition value
5474 * of 0x2. Host drivers are supposed to return the status
5475 * byte as it is defined by SCSI.
5476 */
5477 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
5478 STATUS_BYTE(qdonep->d3.scsi_stat);
5479 } else {
5480 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
5481 }
5482 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 default:
5485 /* QHSTA error occurred */
5486 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
5487 qdonep->d3.host_stat);
5488 scp->result = HOST_BYTE(DID_BAD_TARGET);
5489 break;
5490 }
5491 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005493 case QD_ABORTED_BY_HOST:
5494 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
5495 scp->result =
5496 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
5497 scsi_msg) |
5498 STATUS_BYTE(qdonep->d3.scsi_stat);
5499 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005501 default:
5502 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
5503 qdonep->d3.done_stat);
5504 scp->result =
5505 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
5506 scsi_msg) |
5507 STATUS_BYTE(qdonep->d3.scsi_stat);
5508 break;
5509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005511 /*
5512 * If the 'init_tidmask' bit isn't already set for the target and the
5513 * current request finished normally, then set the bit for the target
5514 * to indicate that a device is present.
5515 */
5516 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
5517 qdonep->d3.done_stat == QD_NO_ERROR &&
5518 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
5519 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
5520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005522 /*
5523 * Because interrupts may be enabled by the 'struct scsi_cmnd' done
5524 * function, add the command to the end of the board's done queue.
5525 * The done function for the command will be called from
5526 * advansys_interrupt().
5527 */
5528 asc_enqueue(&boardp->done, scp, ASC_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005530 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531}
5532
5533/*
5534 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
5535 *
5536 * Callback function for the Wide SCSI Adv Library.
5537 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005538static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005540 asc_board_t *boardp;
5541 adv_req_t *reqp;
5542 adv_sgblk_t *sgblkp;
5543 struct scsi_cmnd *scp;
5544 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005545 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005547 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
5548 (ulong)adv_dvc_varp, (ulong)scsiqp);
5549 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005551 /*
5552 * Get the adv_req_t structure for the command that has been
5553 * completed. The adv_req_t structure actually contains the
5554 * completed ADV_SCSI_REQ_Q structure.
5555 */
5556 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
5557 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
5558 if (reqp == NULL) {
5559 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
5560 return;
5561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005563 /*
5564 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
5565 * command that has been completed.
5566 *
5567 * Note: The adv_req_t request structure and adv_sgblk_t structure,
5568 * if any, are dropped, because a board structure pointer can not be
5569 * determined.
5570 */
5571 scp = reqp->cmndp;
5572 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
5573 if (scp == NULL) {
5574 ASC_PRINT
5575 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
5576 return;
5577 }
5578 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005580 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005581 ASC_STATS(shost, callback);
5582 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005584 /*
5585 * If the request isn't found on the active queue, it may have been
5586 * removed to handle a reset request. Display a message and return.
5587 *
5588 * Note: Because the structure may still be in use don't attempt
5589 * to free the adv_req_t and adv_sgblk_t, if any, structures.
5590 */
5591 boardp = ASC_BOARDP(shost);
5592 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
5593 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
5594 ASC_PRINT2
5595 ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n",
5596 boardp->id, (ulong)scp);
5597 return;
5598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005600 /*
5601 * 'done_status' contains the command's ending status.
5602 */
5603 switch (scsiqp->done_status) {
5604 case QD_NO_ERROR:
5605 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
5606 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005608 /*
5609 * Check for an underrun condition.
5610 *
5611 * If there was no error and an underrun condition, then
5612 * then return the number of underrun bytes.
5613 */
5614 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
5615 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
5616 resid_cnt <= scp->request_bufflen) {
5617 ASC_DBG1(1,
5618 "adv_isr_callback: underrun condition %lu bytes\n",
5619 (ulong)resid_cnt);
5620 scp->resid = resid_cnt;
5621 }
5622 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005624 case QD_WITH_ERROR:
5625 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
5626 switch (scsiqp->host_status) {
5627 case QHSTA_NO_ERROR:
5628 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
5629 ASC_DBG(2,
5630 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
5631 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
5632 sizeof(scp->sense_buffer));
5633 /*
5634 * Note: The 'status_byte()' macro used by target drivers
5635 * defined in scsi.h shifts the status byte returned by
5636 * host drivers right by 1 bit. This is why target drivers
5637 * also use right shifted status byte definitions. For
5638 * instance target drivers use CHECK_CONDITION, defined to
5639 * 0x1, instead of the SCSI defined check condition value
5640 * of 0x2. Host drivers are supposed to return the status
5641 * byte as it is defined by SCSI.
5642 */
5643 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
5644 STATUS_BYTE(scsiqp->scsi_status);
5645 } else {
5646 scp->result = STATUS_BYTE(scsiqp->scsi_status);
5647 }
5648 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005650 default:
5651 /* Some other QHSTA error occurred. */
5652 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
5653 scsiqp->host_status);
5654 scp->result = HOST_BYTE(DID_BAD_TARGET);
5655 break;
5656 }
5657 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005659 case QD_ABORTED_BY_HOST:
5660 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
5661 scp->result =
5662 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
5663 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005665 default:
5666 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
5667 scsiqp->done_status);
5668 scp->result =
5669 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
5670 break;
5671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005673 /*
5674 * If the 'init_tidmask' bit isn't already set for the target and the
5675 * current request finished normally, then set the bit for the target
5676 * to indicate that a device is present.
5677 */
5678 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
5679 scsiqp->done_status == QD_NO_ERROR &&
5680 scsiqp->host_status == QHSTA_NO_ERROR) {
5681 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
5682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005684 /*
5685 * Because interrupts may be enabled by the 'struct scsi_cmnd' done
5686 * function, add the command to the end of the board's done queue.
5687 * The done function for the command will be called from
5688 * advansys_interrupt().
5689 */
5690 asc_enqueue(&boardp->done, scp, ASC_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005692 /*
5693 * Free all 'adv_sgblk_t' structures allocated for the request.
5694 */
5695 while ((sgblkp = reqp->sgblkp) != NULL) {
5696 /* Remove 'sgblkp' from the request list. */
5697 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005699 /* Add 'sgblkp' to the board free list. */
5700 sgblkp->next_sgblkp = boardp->adv_sgblkp;
5701 boardp->adv_sgblkp = sgblkp;
5702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005704 /*
5705 * Free the adv_req_t structure used with the command by adding
5706 * it back to the board free list.
5707 */
5708 reqp->next_reqp = boardp->adv_reqp;
5709 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005711 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005713 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714}
5715
5716/*
5717 * adv_async_callback() - Adv Library asynchronous event callback function.
5718 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005719static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005721 switch (code) {
5722 case ADV_ASYNC_SCSI_BUS_RESET_DET:
5723 /*
5724 * The firmware detected a SCSI Bus reset.
5725 */
5726 ASC_DBG(0,
5727 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
5728 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005730 case ADV_ASYNC_RDMA_FAILURE:
5731 /*
5732 * Handle RDMA failure by resetting the SCSI Bus and
5733 * possibly the chip if it is unresponsive. Log the error
5734 * with a unique code.
5735 */
5736 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
5737 AdvResetChipAndSB(adv_dvc_varp);
5738 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005740 case ADV_HOST_SCSI_BUS_RESET:
5741 /*
5742 * Host generated SCSI bus reset occurred.
5743 */
5744 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
5745 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005746
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005747 default:
5748 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
5749 break;
5750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751}
5752
5753/*
5754 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
5755 * to indicate a command is queued for the device.
5756 *
5757 * 'flag' may be either ASC_FRONT or ASC_BACK.
5758 *
5759 * 'REQPNEXT(reqp)' returns reqp's next pointer.
5760 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005761static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005763 int tid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005765 ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n",
5766 (ulong)ascq, (ulong)reqp, flag);
5767 ASC_ASSERT(reqp != NULL);
5768 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
5769 tid = REQPTID(reqp);
5770 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
5771 if (flag == ASC_FRONT) {
5772 reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
5773 ascq->q_first[tid] = reqp;
5774 /* If the queue was empty, set the last pointer. */
5775 if (ascq->q_last[tid] == NULL) {
5776 ascq->q_last[tid] = reqp;
5777 }
5778 } else { /* ASC_BACK */
5779 if (ascq->q_last[tid] != NULL) {
5780 ascq->q_last[tid]->host_scribble =
5781 (unsigned char *)reqp;
5782 }
5783 ascq->q_last[tid] = reqp;
5784 reqp->host_scribble = NULL;
5785 /* If the queue was empty, set the first pointer. */
5786 if (ascq->q_first[tid] == NULL) {
5787 ascq->q_first[tid] = reqp;
5788 }
5789 }
5790 /* The queue has at least one entry, set its bit. */
5791 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005793 /* Maintain request queue statistics. */
5794 ascq->q_tot_cnt[tid]++;
5795 ascq->q_cur_cnt[tid]++;
5796 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
5797 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
5798 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
5799 tid, ascq->q_max_cnt[tid]);
5800 }
5801 REQPTIME(reqp) = REQTIMESTAMP();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005803 ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp);
5804 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805}
5806
5807/*
5808 * Return first queued 'REQP' on the specified queue for
5809 * the specified target device. Clear the 'tidmask' bit for
5810 * the device if no more commands are left queued for it.
5811 *
5812 * 'REQPNEXT(reqp)' returns reqp's next pointer.
5813 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005814static REQP asc_dequeue(asc_queue_t *ascq, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005816 REQP reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005818 ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
5819 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
5820 if ((reqp = ascq->q_first[tid]) != NULL) {
5821 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
5822 ascq->q_first[tid] = REQPNEXT(reqp);
5823 /* If the queue is empty, clear its bit and the last pointer. */
5824 if (ascq->q_first[tid] == NULL) {
5825 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
5826 ASC_ASSERT(ascq->q_last[tid] == reqp);
5827 ascq->q_last[tid] = NULL;
5828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005830 /* Maintain request queue statistics. */
5831 ascq->q_cur_cnt[tid]--;
5832 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
5833 REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005835 }
5836 ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp);
5837 return reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838}
5839
5840/*
5841 * Return a pointer to a singly linked list of all the requests queued
5842 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
5843 *
5844 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
5845 * the last request returned in the singly linked list.
5846 *
5847 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
5848 * then all queued requests are concatenated into one list and
5849 * returned.
5850 *
5851 * Note: If 'lastpp' is used to append a new list to the end of
5852 * an old list, only change the old list last pointer if '*lastpp'
5853 * (or the function return value) is not NULL, i.e. use a temporary
5854 * variable for 'lastpp' and check its value after the function return
5855 * before assigning it to the list last pointer.
5856 *
5857 * Unfortunately collecting queuing time statistics adds overhead to
5858 * the function that isn't inherent to the function's algorithm.
5859 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005860static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005861{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005862 REQP firstp, lastp;
5863 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005865 ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
5866 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005868 /*
5869 * If 'tid' is not ASC_TID_ALL, return requests only for
5870 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
5871 * requests for all tids.
5872 */
5873 if (tid != ASC_TID_ALL) {
5874 /* Return all requests for the specified 'tid'. */
5875 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
5876 /* List is empty; Set first and last return pointers to NULL. */
5877 firstp = lastp = NULL;
5878 } else {
5879 firstp = ascq->q_first[tid];
5880 lastp = ascq->q_last[tid];
5881 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
5882 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005884 {
5885 REQP reqp;
5886 ascq->q_cur_cnt[tid] = 0;
5887 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
5888 REQTIMESTAT("asc_dequeue_list", ascq,
5889 reqp, tid);
5890 }
5891 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005893 }
5894 } else {
5895 /* Return all requests for all tids. */
5896 firstp = lastp = NULL;
5897 for (i = 0; i <= ADV_MAX_TID; i++) {
5898 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
5899 if (firstp == NULL) {
5900 firstp = ascq->q_first[i];
5901 lastp = ascq->q_last[i];
5902 } else {
5903 ASC_ASSERT(lastp != NULL);
5904 lastp->host_scribble =
5905 (unsigned char *)ascq->q_first[i];
5906 lastp = ascq->q_last[i];
5907 }
5908 ascq->q_first[i] = ascq->q_last[i] = NULL;
5909 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005911 ascq->q_cur_cnt[i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005913 }
5914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005916 {
5917 REQP reqp;
5918 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
5919 REQTIMESTAT("asc_dequeue_list", ascq, reqp,
5920 reqp->device->id);
5921 }
5922 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005924 }
5925 if (lastpp) {
5926 *lastpp = lastp;
5927 }
5928 ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp);
5929 return firstp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930}
5931
5932/*
5933 * Remove the specified 'REQP' from the specified queue for
5934 * the specified target device. Clear the 'tidmask' bit for the
5935 * device if no more commands are left queued for it.
5936 *
5937 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
5938 *
5939 * Return ASC_TRUE if the command was found and removed,
5940 * otherwise return ASC_FALSE.
5941 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005942static int asc_rmqueue(asc_queue_t *ascq, REQP reqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005943{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005944 REQP currp, prevp;
5945 int tid;
5946 int ret = ASC_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005948 ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n",
5949 (ulong)ascq, (ulong)reqp);
5950 ASC_ASSERT(reqp != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005951
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005952 tid = REQPTID(reqp);
5953 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005955 /*
5956 * Handle the common case of 'reqp' being the first
5957 * entry on the queue.
5958 */
5959 if (reqp == ascq->q_first[tid]) {
5960 ret = ASC_TRUE;
5961 ascq->q_first[tid] = REQPNEXT(reqp);
5962 /* If the queue is now empty, clear its bit and the last pointer. */
5963 if (ascq->q_first[tid] == NULL) {
5964 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
5965 ASC_ASSERT(ascq->q_last[tid] == reqp);
5966 ascq->q_last[tid] = NULL;
5967 }
5968 } else if (ascq->q_first[tid] != NULL) {
5969 ASC_ASSERT(ascq->q_last[tid] != NULL);
5970 /*
5971 * Because the case of 'reqp' being the first entry has been
5972 * handled above and it is known the queue is not empty, if
5973 * 'reqp' is found on the queue it is guaranteed the queue will
5974 * not become empty and that 'q_first[tid]' will not be changed.
5975 *
5976 * Set 'prevp' to the first entry, 'currp' to the second entry,
5977 * and search for 'reqp'.
5978 */
5979 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
5980 currp; prevp = currp, currp = REQPNEXT(currp)) {
5981 if (currp == reqp) {
5982 ret = ASC_TRUE;
5983 prevp->host_scribble =
5984 (unsigned char *)REQPNEXT(currp);
5985 reqp->host_scribble = NULL;
5986 if (ascq->q_last[tid] == reqp) {
5987 ascq->q_last[tid] = prevp;
5988 }
5989 break;
5990 }
5991 }
5992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005994 /* Maintain request queue statistics. */
5995 if (ret == ASC_TRUE) {
5996 ascq->q_cur_cnt[tid]--;
5997 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
5998 }
5999 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006001 ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret);
6002 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003}
6004
6005/*
6006 * Execute as many queued requests as possible for the specified queue.
6007 *
6008 * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd.
6009 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006010static void asc_execute_queue(asc_queue_t *ascq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006012 ADV_SCSI_BIT_ID_TYPE scan_tidmask;
6013 REQP reqp;
6014 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006016 ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq);
6017 /*
6018 * Execute queued commands for devices attached to
6019 * the current board in round-robin fashion.
6020 */
6021 scan_tidmask = ascq->q_tidmask;
6022 do {
6023 for (i = 0; i <= ADV_MAX_TID; i++) {
6024 if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
6025 if ((reqp = asc_dequeue(ascq, i)) == NULL) {
6026 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
6027 } else
6028 if (asc_execute_scsi_cmnd
6029 ((struct scsi_cmnd *)reqp)
6030 == ASC_BUSY) {
6031 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
6032 /*
6033 * The request returned ASC_BUSY. Enqueue at the front of
6034 * target's waiting list to maintain correct ordering.
6035 */
6036 asc_enqueue(ascq, reqp, ASC_FRONT);
6037 }
6038 }
6039 }
6040 } while (scan_tidmask);
6041 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042}
6043
6044#ifdef CONFIG_PROC_FS
6045/*
6046 * asc_prt_board_devices()
6047 *
6048 * Print driver information for devices attached to the board.
6049 *
6050 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6051 * cf. asc_prt_line().
6052 *
6053 * Return the number of characters copied into 'cp'. No more than
6054 * 'cplen' characters will be copied to 'cp'.
6055 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006056static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006058 asc_board_t *boardp;
6059 int leftlen;
6060 int totlen;
6061 int len;
6062 int chip_scsi_id;
6063 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006065 boardp = ASC_BOARDP(shost);
6066 leftlen = cplen;
6067 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006069 len = asc_prt_line(cp, leftlen,
6070 "\nDevice Information for AdvanSys SCSI Host %d:\n",
6071 shost->host_no);
6072 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006074 if (ASC_NARROW_BOARD(boardp)) {
6075 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6076 } else {
6077 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006080 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
6081 ASC_PRT_NEXT();
6082 for (i = 0; i <= ADV_MAX_TID; i++) {
6083 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
6084 len = asc_prt_line(cp, leftlen, " %X,", i);
6085 ASC_PRT_NEXT();
6086 }
6087 }
6088 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
6089 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006091 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092}
6093
6094/*
6095 * Display Wide Board BIOS Information.
6096 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006097static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006099 asc_board_t *boardp;
6100 int leftlen;
6101 int totlen;
6102 int len;
6103 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006105 boardp = ASC_BOARDP(shost);
6106 leftlen = cplen;
6107 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006109 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
6110 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006112 /*
6113 * If the BIOS saved a valid signature, then fill in
6114 * the BIOS code segment base address.
6115 */
6116 if (boardp->bios_signature != 0x55AA) {
6117 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
6118 ASC_PRT_NEXT();
6119 len = asc_prt_line(cp, leftlen,
6120 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
6121 ASC_PRT_NEXT();
6122 len = asc_prt_line(cp, leftlen,
6123 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
6124 ASC_PRT_NEXT();
6125 } else {
6126 major = (boardp->bios_version >> 12) & 0xF;
6127 minor = (boardp->bios_version >> 8) & 0xF;
6128 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006130 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
6131 major, minor,
6132 letter >= 26 ? '?' : letter + 'A');
6133 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006135 /*
6136 * Current available ROM BIOS release is 3.1I for UW
6137 * and 3.2I for U2W. This code doesn't differentiate
6138 * UW and U2W boards.
6139 */
6140 if (major < 3 || (major <= 3 && minor < 1) ||
6141 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
6142 len = asc_prt_line(cp, leftlen,
6143 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
6144 ASC_PRT_NEXT();
6145 len = asc_prt_line(cp, leftlen,
6146 "ftp://ftp.connectcom.net/pub\n");
6147 ASC_PRT_NEXT();
6148 }
6149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006151 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152}
6153
6154/*
6155 * Add serial number to information bar if signature AAh
6156 * is found in at bit 15-9 (7 bits) of word 1.
6157 *
6158 * Serial Number consists fo 12 alpha-numeric digits.
6159 *
6160 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
6161 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
6162 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
6163 * 5 - Product revision (A-J) Word0: " "
6164 *
6165 * Signature Word1: 15-9 (7 bits)
6166 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
6167 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
6168 *
6169 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
6170 *
6171 * Note 1: Only production cards will have a serial number.
6172 *
6173 * Note 2: Signature is most significant 7 bits (0xFE).
6174 *
6175 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
6176 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006177static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006179 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006181 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
6182 return ASC_FALSE;
6183 } else {
6184 /*
6185 * First word - 6 digits.
6186 */
6187 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006189 /* Product type - 1st digit. */
6190 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
6191 /* Product type is P=Prototype */
6192 *cp += 0x8;
6193 }
6194 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006196 /* Manufacturing location - 2nd digit. */
6197 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006199 /* Product ID - 3rd, 4th digits. */
6200 num = w & 0x3FF;
6201 *cp++ = '0' + (num / 100);
6202 num %= 100;
6203 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006205 /* Product revision - 5th digit. */
6206 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006207
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006208 /*
6209 * Second word
6210 */
6211 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006213 /*
6214 * Year - 6th digit.
6215 *
6216 * If bit 15 of third word is set, then the
6217 * last digit of the year is greater than 7.
6218 */
6219 if (serialnum[2] & 0x8000) {
6220 *cp++ = '8' + ((w & 0x1C0) >> 6);
6221 } else {
6222 *cp++ = '0' + ((w & 0x1C0) >> 6);
6223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006225 /* Week of year - 7th, 8th digits. */
6226 num = w & 0x003F;
6227 *cp++ = '0' + num / 10;
6228 num %= 10;
6229 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006231 /*
6232 * Third word
6233 */
6234 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006235
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006236 /* Serial number - 9th digit. */
6237 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006239 /* 10th, 11th, 12th digits. */
6240 num = w % 1000;
6241 *cp++ = '0' + num / 100;
6242 num %= 100;
6243 *cp++ = '0' + num / 10;
6244 num %= 10;
6245 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006247 *cp = '\0'; /* Null Terminate the string. */
6248 return ASC_TRUE;
6249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250}
6251
6252/*
6253 * asc_prt_asc_board_eeprom()
6254 *
6255 * Print board EEPROM configuration.
6256 *
6257 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6258 * cf. asc_prt_line().
6259 *
6260 * Return the number of characters copied into 'cp'. No more than
6261 * 'cplen' characters will be copied to 'cp'.
6262 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006263static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006265 asc_board_t *boardp;
6266 ASC_DVC_VAR *asc_dvc_varp;
6267 int leftlen;
6268 int totlen;
6269 int len;
6270 ASCEEP_CONFIG *ep;
6271 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006273 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006275 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006277 boardp = ASC_BOARDP(shost);
6278 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6279 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006280
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006281 leftlen = cplen;
6282 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006284 len = asc_prt_line(cp, leftlen,
6285 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
6286 shost->host_no);
6287 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006289 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
6290 == ASC_TRUE) {
6291 len =
6292 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
6293 serialstr);
6294 ASC_PRT_NEXT();
6295 } else {
6296 if (ep->adapter_info[5] == 0xBB) {
6297 len = asc_prt_line(cp, leftlen,
6298 " Default Settings Used for EEPROM-less Adapter.\n");
6299 ASC_PRT_NEXT();
6300 } else {
6301 len = asc_prt_line(cp, leftlen,
6302 " Serial Number Signature Not Present.\n");
6303 ASC_PRT_NEXT();
6304 }
6305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006307 len = asc_prt_line(cp, leftlen,
6308 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6309 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
6310 ep->max_tag_qng);
6311 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006312
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006313 len = asc_prt_line(cp, leftlen,
6314 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
6315 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006317 len = asc_prt_line(cp, leftlen, " Target ID: ");
6318 ASC_PRT_NEXT();
6319 for (i = 0; i <= ASC_MAX_TID; i++) {
6320 len = asc_prt_line(cp, leftlen, " %d", i);
6321 ASC_PRT_NEXT();
6322 }
6323 len = asc_prt_line(cp, leftlen, "\n");
6324 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006325
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006326 len = asc_prt_line(cp, leftlen, " Disconnects: ");
6327 ASC_PRT_NEXT();
6328 for (i = 0; i <= ASC_MAX_TID; i++) {
6329 len = asc_prt_line(cp, leftlen, " %c",
6330 (ep->
6331 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6332 'N');
6333 ASC_PRT_NEXT();
6334 }
6335 len = asc_prt_line(cp, leftlen, "\n");
6336 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006338 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
6339 ASC_PRT_NEXT();
6340 for (i = 0; i <= ASC_MAX_TID; i++) {
6341 len = asc_prt_line(cp, leftlen, " %c",
6342 (ep->
6343 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6344 'N');
6345 ASC_PRT_NEXT();
6346 }
6347 len = asc_prt_line(cp, leftlen, "\n");
6348 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006349
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006350 len = asc_prt_line(cp, leftlen, " Start Motor: ");
6351 ASC_PRT_NEXT();
6352 for (i = 0; i <= ASC_MAX_TID; i++) {
6353 len = asc_prt_line(cp, leftlen, " %c",
6354 (ep->
6355 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6356 'N');
6357 ASC_PRT_NEXT();
6358 }
6359 len = asc_prt_line(cp, leftlen, "\n");
6360 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006362 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6363 ASC_PRT_NEXT();
6364 for (i = 0; i <= ASC_MAX_TID; i++) {
6365 len = asc_prt_line(cp, leftlen, " %c",
6366 (ep->
6367 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6368 'N');
6369 ASC_PRT_NEXT();
6370 }
6371 len = asc_prt_line(cp, leftlen, "\n");
6372 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006373
6374#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006375 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
6376 len = asc_prt_line(cp, leftlen,
6377 " Host ISA DMA speed: %d MB/S\n",
6378 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
6379 ASC_PRT_NEXT();
6380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006381#endif /* CONFIG_ISA */
6382
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006383 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006384}
6385
6386/*
6387 * asc_prt_adv_board_eeprom()
6388 *
6389 * Print board EEPROM configuration.
6390 *
6391 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6392 * cf. asc_prt_line().
6393 *
6394 * Return the number of characters copied into 'cp'. No more than
6395 * 'cplen' characters will be copied to 'cp'.
6396 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006397static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006398{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006399 asc_board_t *boardp;
6400 ADV_DVC_VAR *adv_dvc_varp;
6401 int leftlen;
6402 int totlen;
6403 int len;
6404 int i;
6405 char *termstr;
6406 uchar serialstr[13];
6407 ADVEEP_3550_CONFIG *ep_3550 = NULL;
6408 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
6409 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
6410 ushort word;
6411 ushort *wordp;
6412 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006414 boardp = ASC_BOARDP(shost);
6415 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6416 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6417 ep_3550 = &boardp->eep_config.adv_3550_eep;
6418 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6419 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
6420 } else {
6421 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
6422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006424 leftlen = cplen;
6425 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006427 len = asc_prt_line(cp, leftlen,
6428 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
6429 shost->host_no);
6430 ASC_PRT_NEXT();
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 wordp = &ep_3550->serial_number_word1;
6434 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6435 wordp = &ep_38C0800->serial_number_word1;
6436 } else {
6437 wordp = &ep_38C1600->serial_number_word1;
6438 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006440 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
6441 len =
6442 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
6443 serialstr);
6444 ASC_PRT_NEXT();
6445 } else {
6446 len = asc_prt_line(cp, leftlen,
6447 " Serial Number Signature Not Present.\n");
6448 ASC_PRT_NEXT();
6449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006450
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006451 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6452 len = asc_prt_line(cp, leftlen,
6453 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6454 ep_3550->adapter_scsi_id,
6455 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
6456 ASC_PRT_NEXT();
6457 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6458 len = asc_prt_line(cp, leftlen,
6459 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6460 ep_38C0800->adapter_scsi_id,
6461 ep_38C0800->max_host_qng,
6462 ep_38C0800->max_dvc_qng);
6463 ASC_PRT_NEXT();
6464 } else {
6465 len = asc_prt_line(cp, leftlen,
6466 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
6467 ep_38C1600->adapter_scsi_id,
6468 ep_38C1600->max_host_qng,
6469 ep_38C1600->max_dvc_qng);
6470 ASC_PRT_NEXT();
6471 }
6472 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6473 word = ep_3550->termination;
6474 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6475 word = ep_38C0800->termination_lvd;
6476 } else {
6477 word = ep_38C1600->termination_lvd;
6478 }
6479 switch (word) {
6480 case 1:
6481 termstr = "Low Off/High Off";
6482 break;
6483 case 2:
6484 termstr = "Low Off/High On";
6485 break;
6486 case 3:
6487 termstr = "Low On/High On";
6488 break;
6489 default:
6490 case 0:
6491 termstr = "Automatic";
6492 break;
6493 }
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 len = asc_prt_line(cp, leftlen,
6497 " termination: %u (%s), bios_ctrl: 0x%x\n",
6498 ep_3550->termination, termstr,
6499 ep_3550->bios_ctrl);
6500 ASC_PRT_NEXT();
6501 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6502 len = asc_prt_line(cp, leftlen,
6503 " termination: %u (%s), bios_ctrl: 0x%x\n",
6504 ep_38C0800->termination_lvd, termstr,
6505 ep_38C0800->bios_ctrl);
6506 ASC_PRT_NEXT();
6507 } else {
6508 len = asc_prt_line(cp, leftlen,
6509 " termination: %u (%s), bios_ctrl: 0x%x\n",
6510 ep_38C1600->termination_lvd, termstr,
6511 ep_38C1600->bios_ctrl);
6512 ASC_PRT_NEXT();
6513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006514
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006515 len = asc_prt_line(cp, leftlen, " Target ID: ");
6516 ASC_PRT_NEXT();
6517 for (i = 0; i <= ADV_MAX_TID; i++) {
6518 len = asc_prt_line(cp, leftlen, " %X", i);
6519 ASC_PRT_NEXT();
6520 }
6521 len = asc_prt_line(cp, leftlen, "\n");
6522 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006523
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006524 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6525 word = ep_3550->disc_enable;
6526 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6527 word = ep_38C0800->disc_enable;
6528 } else {
6529 word = ep_38C1600->disc_enable;
6530 }
6531 len = asc_prt_line(cp, leftlen, " Disconnects: ");
6532 ASC_PRT_NEXT();
6533 for (i = 0; i <= ADV_MAX_TID; i++) {
6534 len = asc_prt_line(cp, leftlen, " %c",
6535 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6536 ASC_PRT_NEXT();
6537 }
6538 len = asc_prt_line(cp, leftlen, "\n");
6539 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006540
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006541 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6542 word = ep_3550->tagqng_able;
6543 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6544 word = ep_38C0800->tagqng_able;
6545 } else {
6546 word = ep_38C1600->tagqng_able;
6547 }
6548 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
6549 ASC_PRT_NEXT();
6550 for (i = 0; i <= ADV_MAX_TID; i++) {
6551 len = asc_prt_line(cp, leftlen, " %c",
6552 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6553 ASC_PRT_NEXT();
6554 }
6555 len = asc_prt_line(cp, leftlen, "\n");
6556 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006557
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006558 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6559 word = ep_3550->start_motor;
6560 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6561 word = ep_38C0800->start_motor;
6562 } else {
6563 word = ep_38C1600->start_motor;
6564 }
6565 len = asc_prt_line(cp, leftlen, " Start Motor: ");
6566 ASC_PRT_NEXT();
6567 for (i = 0; i <= ADV_MAX_TID; i++) {
6568 len = asc_prt_line(cp, leftlen, " %c",
6569 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6570 ASC_PRT_NEXT();
6571 }
6572 len = asc_prt_line(cp, leftlen, "\n");
6573 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006574
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006575 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6576 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6577 ASC_PRT_NEXT();
6578 for (i = 0; i <= ADV_MAX_TID; i++) {
6579 len = asc_prt_line(cp, leftlen, " %c",
6580 (ep_3550->
6581 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
6582 'Y' : 'N');
6583 ASC_PRT_NEXT();
6584 }
6585 len = asc_prt_line(cp, leftlen, "\n");
6586 ASC_PRT_NEXT();
6587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006588
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006589 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6590 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
6591 ASC_PRT_NEXT();
6592 for (i = 0; i <= ADV_MAX_TID; i++) {
6593 len = asc_prt_line(cp, leftlen, " %c",
6594 (ep_3550->
6595 ultra_able & ADV_TID_TO_TIDMASK(i))
6596 ? 'Y' : 'N');
6597 ASC_PRT_NEXT();
6598 }
6599 len = asc_prt_line(cp, leftlen, "\n");
6600 ASC_PRT_NEXT();
6601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006602
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006603 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
6604 word = ep_3550->wdtr_able;
6605 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
6606 word = ep_38C0800->wdtr_able;
6607 } else {
6608 word = ep_38C1600->wdtr_able;
6609 }
6610 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
6611 ASC_PRT_NEXT();
6612 for (i = 0; i <= ADV_MAX_TID; i++) {
6613 len = asc_prt_line(cp, leftlen, " %c",
6614 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
6615 ASC_PRT_NEXT();
6616 }
6617 len = asc_prt_line(cp, leftlen, "\n");
6618 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006619
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006620 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
6621 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
6622 len = asc_prt_line(cp, leftlen,
6623 " Synchronous Transfer Speed (Mhz):\n ");
6624 ASC_PRT_NEXT();
6625 for (i = 0; i <= ADV_MAX_TID; i++) {
6626 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006627
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006628 if (i == 0) {
6629 sdtr_speed = adv_dvc_varp->sdtr_speed1;
6630 } else if (i == 4) {
6631 sdtr_speed = adv_dvc_varp->sdtr_speed2;
6632 } else if (i == 8) {
6633 sdtr_speed = adv_dvc_varp->sdtr_speed3;
6634 } else if (i == 12) {
6635 sdtr_speed = adv_dvc_varp->sdtr_speed4;
6636 }
6637 switch (sdtr_speed & ADV_MAX_TID) {
6638 case 0:
6639 speed_str = "Off";
6640 break;
6641 case 1:
6642 speed_str = " 5";
6643 break;
6644 case 2:
6645 speed_str = " 10";
6646 break;
6647 case 3:
6648 speed_str = " 20";
6649 break;
6650 case 4:
6651 speed_str = " 40";
6652 break;
6653 case 5:
6654 speed_str = " 80";
6655 break;
6656 default:
6657 speed_str = "Unk";
6658 break;
6659 }
6660 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
6661 ASC_PRT_NEXT();
6662 if (i == 7) {
6663 len = asc_prt_line(cp, leftlen, "\n ");
6664 ASC_PRT_NEXT();
6665 }
6666 sdtr_speed >>= 4;
6667 }
6668 len = asc_prt_line(cp, leftlen, "\n");
6669 ASC_PRT_NEXT();
6670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006672 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006673}
6674
6675/*
6676 * asc_prt_driver_conf()
6677 *
6678 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6679 * cf. asc_prt_line().
6680 *
6681 * Return the number of characters copied into 'cp'. No more than
6682 * 'cplen' characters will be copied to 'cp'.
6683 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006684static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006686 asc_board_t *boardp;
6687 int leftlen;
6688 int totlen;
6689 int len;
6690 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006692 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006693
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006694 leftlen = cplen;
6695 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006697 len = asc_prt_line(cp, leftlen,
6698 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
6699 shost->host_no);
6700 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006702 len = asc_prt_line(cp, leftlen,
6703 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
6704 shost->host_busy, shost->last_reset, shost->max_id,
6705 shost->max_lun, shost->max_channel);
6706 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006708 len = asc_prt_line(cp, leftlen,
6709 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
6710 shost->unique_id, shost->can_queue, shost->this_id,
6711 shost->sg_tablesize, shost->cmd_per_lun);
6712 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006713
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006714 len = asc_prt_line(cp, leftlen,
6715 " unchecked_isa_dma %d, use_clustering %d\n",
6716 shost->unchecked_isa_dma, shost->use_clustering);
6717 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006719 len = asc_prt_line(cp, leftlen,
6720 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
6721 boardp->flags, boardp->last_reset, jiffies,
6722 boardp->asc_n_io_port);
6723 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006724
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006725 /* 'shost->n_io_port' may be truncated because it is only one byte. */
6726 len = asc_prt_line(cp, leftlen,
6727 " io_port 0x%x, n_io_port 0x%x\n",
6728 shost->io_port, shost->n_io_port);
6729 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006731 if (ASC_NARROW_BOARD(boardp)) {
6732 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6733 } else {
6734 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6735 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006737 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006738}
6739
6740/*
6741 * asc_prt_asc_board_info()
6742 *
6743 * Print dynamic board configuration information.
6744 *
6745 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6746 * cf. asc_prt_line().
6747 *
6748 * Return the number of characters copied into 'cp'. No more than
6749 * 'cplen' characters will be copied to 'cp'.
6750 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006751static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006752{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006753 asc_board_t *boardp;
6754 int chip_scsi_id;
6755 int leftlen;
6756 int totlen;
6757 int len;
6758 ASC_DVC_VAR *v;
6759 ASC_DVC_CFG *c;
6760 int i;
6761 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006762
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006763 boardp = ASC_BOARDP(shost);
6764 v = &boardp->dvc_var.asc_dvc_var;
6765 c = &boardp->dvc_cfg.asc_dvc_cfg;
6766 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006768 leftlen = cplen;
6769 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006770
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006771 len = asc_prt_line(cp, leftlen,
6772 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
6773 shost->host_no);
6774 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006775
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006776 len = asc_prt_line(cp, leftlen,
6777 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
6778 c->chip_version, c->lib_version, c->lib_serial_no,
6779 c->mcode_date);
6780 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006781
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006782 len = asc_prt_line(cp, leftlen,
6783 " mcode_version 0x%x, err_code %u\n",
6784 c->mcode_version, v->err_code);
6785 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006786
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006787 /* Current number of commands waiting for the host. */
6788 len = asc_prt_line(cp, leftlen,
6789 " Total Command Pending: %d\n", v->cur_total_qng);
6790 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006792 len = asc_prt_line(cp, leftlen, " Command Queuing:");
6793 ASC_PRT_NEXT();
6794 for (i = 0; i <= ASC_MAX_TID; i++) {
6795 if ((chip_scsi_id == i) ||
6796 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6797 continue;
6798 }
6799 len = asc_prt_line(cp, leftlen, " %X:%c",
6800 i,
6801 (v->
6802 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
6803 'Y' : 'N');
6804 ASC_PRT_NEXT();
6805 }
6806 len = asc_prt_line(cp, leftlen, "\n");
6807 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006808
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006809 /* Current number of commands waiting for a device. */
6810 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
6811 ASC_PRT_NEXT();
6812 for (i = 0; i <= ASC_MAX_TID; i++) {
6813 if ((chip_scsi_id == i) ||
6814 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6815 continue;
6816 }
6817 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
6818 ASC_PRT_NEXT();
6819 }
6820 len = asc_prt_line(cp, leftlen, "\n");
6821 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006823 /* Current limit on number of commands that can be sent to a device. */
6824 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
6825 ASC_PRT_NEXT();
6826 for (i = 0; i <= ASC_MAX_TID; i++) {
6827 if ((chip_scsi_id == i) ||
6828 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6829 continue;
6830 }
6831 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
6832 ASC_PRT_NEXT();
6833 }
6834 len = asc_prt_line(cp, leftlen, "\n");
6835 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006837 /* Indicate whether the device has returned queue full status. */
6838 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
6839 ASC_PRT_NEXT();
6840 for (i = 0; i <= ASC_MAX_TID; i++) {
6841 if ((chip_scsi_id == i) ||
6842 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6843 continue;
6844 }
6845 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
6846 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
6847 i, boardp->queue_full_cnt[i]);
6848 } else {
6849 len = asc_prt_line(cp, leftlen, " %X:N", i);
6850 }
6851 ASC_PRT_NEXT();
6852 }
6853 len = asc_prt_line(cp, leftlen, "\n");
6854 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006855
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006856 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
6857 ASC_PRT_NEXT();
6858 for (i = 0; i <= ASC_MAX_TID; i++) {
6859 if ((chip_scsi_id == i) ||
6860 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6861 continue;
6862 }
6863 len = asc_prt_line(cp, leftlen, " %X:%c",
6864 i,
6865 (v->
6866 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6867 'N');
6868 ASC_PRT_NEXT();
6869 }
6870 len = asc_prt_line(cp, leftlen, "\n");
6871 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006872
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006873 for (i = 0; i <= ASC_MAX_TID; i++) {
6874 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006875
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006876 if ((chip_scsi_id == i) ||
6877 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
6878 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
6879 continue;
6880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006882 len = asc_prt_line(cp, leftlen, " %X:", i);
6883 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006884
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006885 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
6886 len = asc_prt_line(cp, leftlen, " Asynchronous");
6887 ASC_PRT_NEXT();
6888 } else {
6889 syn_period_ix =
6890 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
6891 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006892
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006893 len = asc_prt_line(cp, leftlen,
6894 " Transfer Period Factor: %d (%d.%d Mhz),",
6895 v->sdtr_period_tbl[syn_period_ix],
6896 250 /
6897 v->sdtr_period_tbl[syn_period_ix],
6898 ASC_TENTHS(250,
6899 v->
6900 sdtr_period_tbl
6901 [syn_period_ix]));
6902 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006903
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006904 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
6905 boardp->
6906 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
6907 ASC_PRT_NEXT();
6908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006910 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
6911 len = asc_prt_line(cp, leftlen, "*\n");
6912 renegotiate = 1;
6913 } else {
6914 len = asc_prt_line(cp, leftlen, "\n");
6915 }
6916 ASC_PRT_NEXT();
6917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006918
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006919 if (renegotiate) {
6920 len = asc_prt_line(cp, leftlen,
6921 " * = Re-negotiation pending before next command.\n");
6922 ASC_PRT_NEXT();
6923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006925 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006926}
6927
6928/*
6929 * asc_prt_adv_board_info()
6930 *
6931 * Print dynamic board configuration information.
6932 *
6933 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6934 * cf. asc_prt_line().
6935 *
6936 * Return the number of characters copied into 'cp'. No more than
6937 * 'cplen' characters will be copied to 'cp'.
6938 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006939static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006940{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006941 asc_board_t *boardp;
6942 int leftlen;
6943 int totlen;
6944 int len;
6945 int i;
6946 ADV_DVC_VAR *v;
6947 ADV_DVC_CFG *c;
6948 AdvPortAddr iop_base;
6949 ushort chip_scsi_id;
6950 ushort lramword;
6951 uchar lrambyte;
6952 ushort tagqng_able;
6953 ushort sdtr_able, wdtr_able;
6954 ushort wdtr_done, sdtr_done;
6955 ushort period = 0;
6956 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006958 boardp = ASC_BOARDP(shost);
6959 v = &boardp->dvc_var.adv_dvc_var;
6960 c = &boardp->dvc_cfg.adv_dvc_cfg;
6961 iop_base = v->iop_base;
6962 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006964 leftlen = cplen;
6965 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006967 len = asc_prt_line(cp, leftlen,
6968 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
6969 shost->host_no);
6970 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006972 len = asc_prt_line(cp, leftlen,
6973 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
6974 v->iop_base,
6975 AdvReadWordRegister(iop_base,
6976 IOPW_SCSI_CFG1) & CABLE_DETECT,
6977 v->err_code);
6978 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006979
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006980 len = asc_prt_line(cp, leftlen,
6981 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
6982 c->chip_version, c->lib_version, c->mcode_date,
6983 c->mcode_version);
6984 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006985
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006986 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6987 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
6988 ASC_PRT_NEXT();
6989 for (i = 0; i <= ADV_MAX_TID; i++) {
6990 if ((chip_scsi_id == i) ||
6991 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6992 continue;
6993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006995 len = asc_prt_line(cp, leftlen, " %X:%c",
6996 i,
6997 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6998 'N');
6999 ASC_PRT_NEXT();
7000 }
7001 len = asc_prt_line(cp, leftlen, "\n");
7002 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007003
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007004 len = asc_prt_line(cp, leftlen, " Queue Limit:");
7005 ASC_PRT_NEXT();
7006 for (i = 0; i <= ADV_MAX_TID; i++) {
7007 if ((chip_scsi_id == i) ||
7008 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7009 continue;
7010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007011
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007012 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
7013 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007015 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
7016 ASC_PRT_NEXT();
7017 }
7018 len = asc_prt_line(cp, leftlen, "\n");
7019 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007020
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007021 len = asc_prt_line(cp, leftlen, " Command Pending:");
7022 ASC_PRT_NEXT();
7023 for (i = 0; i <= ADV_MAX_TID; i++) {
7024 if ((chip_scsi_id == i) ||
7025 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7026 continue;
7027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007028
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007029 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
7030 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007032 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
7033 ASC_PRT_NEXT();
7034 }
7035 len = asc_prt_line(cp, leftlen, "\n");
7036 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007038 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7039 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
7040 ASC_PRT_NEXT();
7041 for (i = 0; i <= ADV_MAX_TID; i++) {
7042 if ((chip_scsi_id == i) ||
7043 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7044 continue;
7045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007047 len = asc_prt_line(cp, leftlen, " %X:%c",
7048 i,
7049 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7050 'N');
7051 ASC_PRT_NEXT();
7052 }
7053 len = asc_prt_line(cp, leftlen, "\n");
7054 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007055
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007056 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
7057 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
7058 ASC_PRT_NEXT();
7059 for (i = 0; i <= ADV_MAX_TID; i++) {
7060 if ((chip_scsi_id == i) ||
7061 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7062 continue;
7063 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007065 AdvReadWordLram(iop_base,
7066 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
7067 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007069 len = asc_prt_line(cp, leftlen, " %X:%d",
7070 i, (lramword & 0x8000) ? 16 : 8);
7071 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007073 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
7074 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7075 len = asc_prt_line(cp, leftlen, "*");
7076 ASC_PRT_NEXT();
7077 renegotiate = 1;
7078 }
7079 }
7080 len = asc_prt_line(cp, leftlen, "\n");
7081 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007083 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7084 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
7085 ASC_PRT_NEXT();
7086 for (i = 0; i <= ADV_MAX_TID; i++) {
7087 if ((chip_scsi_id == i) ||
7088 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
7089 continue;
7090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007092 len = asc_prt_line(cp, leftlen, " %X:%c",
7093 i,
7094 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
7095 'N');
7096 ASC_PRT_NEXT();
7097 }
7098 len = asc_prt_line(cp, leftlen, "\n");
7099 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007101 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
7102 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007104 AdvReadWordLram(iop_base,
7105 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
7106 lramword);
7107 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007109 if ((chip_scsi_id == i) ||
7110 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
7111 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
7112 continue;
7113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007115 len = asc_prt_line(cp, leftlen, " %X:", i);
7116 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007118 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
7119 len = asc_prt_line(cp, leftlen, " Asynchronous");
7120 ASC_PRT_NEXT();
7121 } else {
7122 len =
7123 asc_prt_line(cp, leftlen,
7124 " Transfer Period Factor: ");
7125 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007127 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
7128 len =
7129 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
7130 ASC_PRT_NEXT();
7131 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
7132 len =
7133 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
7134 ASC_PRT_NEXT();
7135 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007137 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007138
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007139 if (period == 0) { /* Should never happen. */
7140 len =
7141 asc_prt_line(cp, leftlen,
7142 "%d (? Mhz), ");
7143 ASC_PRT_NEXT();
7144 } else {
7145 len = asc_prt_line(cp, leftlen,
7146 "%d (%d.%d Mhz),",
7147 period, 250 / period,
7148 ASC_TENTHS(250,
7149 period));
7150 ASC_PRT_NEXT();
7151 }
7152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007154 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
7155 lramword & 0x1F);
7156 ASC_PRT_NEXT();
7157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007158
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007159 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
7160 len = asc_prt_line(cp, leftlen, "*\n");
7161 renegotiate = 1;
7162 } else {
7163 len = asc_prt_line(cp, leftlen, "\n");
7164 }
7165 ASC_PRT_NEXT();
7166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007168 if (renegotiate) {
7169 len = asc_prt_line(cp, leftlen,
7170 " * = Re-negotiation pending before next command.\n");
7171 ASC_PRT_NEXT();
7172 }
7173
7174 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175}
7176
7177/*
7178 * asc_proc_copy()
7179 *
7180 * Copy proc information to a read buffer taking into account the current
7181 * read offset in the file and the remaining space in the read buffer.
7182 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007183static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07007184asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007185 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007186{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007187 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007189 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
7190 (unsigned)offset, (unsigned)advoffset, cplen);
7191 if (offset <= advoffset) {
7192 /* Read offset below current offset, copy everything. */
7193 cnt = min(cplen, leftlen);
7194 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
7195 (ulong)curbuf, (ulong)cp, cnt);
7196 memcpy(curbuf, cp, cnt);
7197 } else if (offset < advoffset + cplen) {
7198 /* Read offset within current range, partial copy. */
7199 cnt = (advoffset + cplen) - offset;
7200 cp = (cp + cplen) - cnt;
7201 cnt = min(cnt, leftlen);
7202 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
7203 (ulong)curbuf, (ulong)cp, cnt);
7204 memcpy(curbuf, cp, cnt);
7205 }
7206 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007207}
7208
7209/*
7210 * asc_prt_line()
7211 *
7212 * If 'cp' is NULL print to the console, otherwise print to a buffer.
7213 *
7214 * Return 0 if printing to the console, otherwise return the number of
7215 * bytes written to the buffer.
7216 *
7217 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
7218 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
7219 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007220static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007221{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007222 va_list args;
7223 int ret;
7224 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007225
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007226 va_start(args, fmt);
7227 ret = vsprintf(s, fmt, args);
7228 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
7229 if (buf == NULL) {
7230 (void)printk(s);
7231 ret = 0;
7232 } else {
7233 ret = min(buflen, ret);
7234 memcpy(buf, s, ret);
7235 }
7236 va_end(args);
7237 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007238}
7239#endif /* CONFIG_PROC_FS */
7240
Linus Torvalds1da177e2005-04-16 15:20:36 -07007241/*
7242 * --- Functions Required by the Asc Library
7243 */
7244
7245/*
7246 * Delay for 'n' milliseconds. Don't use the 'jiffies'
7247 * global variable which is incremented once every 5 ms
7248 * from a timer interrupt, because this function may be
7249 * called when interrupts are disabled.
7250 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007251static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007252{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007253 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
7254 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255}
7256
7257/*
7258 * Currently and inline noop but leave as a placeholder.
7259 * Leave DvcEnterCritical() as a noop placeholder.
7260 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007261static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007263 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264}
7265
7266/*
7267 * Critical sections are all protected by the board spinlock.
7268 * Leave DvcLeaveCritical() as a noop placeholder.
7269 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007270static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007271{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007272 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007273}
7274
7275/*
7276 * void
7277 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
7278 *
7279 * Calling/Exit State:
7280 * none
7281 *
7282 * Description:
7283 * Output an ASC_SCSI_Q structure to the chip
7284 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007285static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07007286DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
7287{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007288 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007290 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
7291 AscSetChipLramAddr(iop_base, s_addr);
7292 for (i = 0; i < 2 * words; i += 2) {
7293 if (i == 4 || i == 20) {
7294 continue;
7295 }
7296 outpw(iop_base + IOP_RAM_DATA,
7297 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
7298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299}
7300
7301/*
7302 * void
7303 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
7304 *
7305 * Calling/Exit State:
7306 * none
7307 *
7308 * Description:
7309 * Input an ASC_QDONE_INFO structure from the chip
7310 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007311static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07007312DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
7313{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007314 int i;
7315 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007316
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007317 AscSetChipLramAddr(iop_base, s_addr);
7318 for (i = 0; i < 2 * words; i += 2) {
7319 if (i == 10) {
7320 continue;
7321 }
7322 word = inpw(iop_base + IOP_RAM_DATA);
7323 inbuf[i] = word & 0xff;
7324 inbuf[i + 1] = (word >> 8) & 0xff;
7325 }
7326 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007327}
7328
7329/*
7330 * Read a PCI configuration byte.
7331 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007332static uchar __devinit DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007333{
7334#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007335 uchar byte_data;
7336 pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
7337 return byte_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007338#else /* !defined(CONFIG_PCI) */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007339 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007340#endif /* !defined(CONFIG_PCI) */
7341}
7342
7343/*
7344 * Write a PCI configuration byte.
7345 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007346static void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007347DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007348{
7349#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007350 pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007351#endif /* CONFIG_PCI */
7352}
7353
7354/*
7355 * Return the BIOS address of the adapter at the specified
7356 * I/O port and with the specified bus type.
7357 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007358static ushort __devinit AscGetChipBiosAddress(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007359{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007360 ushort cfg_lsw;
7361 ushort bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007362
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007363 /*
7364 * The PCI BIOS is re-located by the motherboard BIOS. Because
7365 * of this the driver can not determine where a PCI BIOS is
7366 * loaded and executes.
7367 */
7368 if (bus_type & ASC_IS_PCI) {
7369 return (0);
7370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 if ((bus_type & ASC_IS_EISA) != 0) {
7373 cfg_lsw = AscGetEisaChipCfg(iop_base);
7374 cfg_lsw &= 0x000F;
7375 bios_addr = (ushort)(ASC_BIOS_MIN_ADDR +
7376 (cfg_lsw * ASC_BIOS_BANK_SIZE));
7377 return (bios_addr);
7378 } /* if */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007379#endif /* CONFIG_ISA */
7380
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007381 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007382
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007383 /*
7384 * ISA PnP uses the top bit as the 32K BIOS flag
7385 */
7386 if (bus_type == ASC_IS_ISAPNP) {
7387 cfg_lsw &= 0x7FFF;
7388 }
7389 /* if */
7390 bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
7391 ASC_BIOS_MIN_ADDR);
7392 return (bios_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007393}
7394
Linus Torvalds1da177e2005-04-16 15:20:36 -07007395/*
7396 * --- Functions Required by the Adv Library
7397 */
7398
7399/*
7400 * DvcGetPhyAddr()
7401 *
7402 * Return the physical address of 'vaddr' and set '*lenp' to the
7403 * number of physically contiguous bytes that follow 'vaddr'.
7404 * 'flag' indicates the type of structure whose physical address
7405 * is being translated.
7406 *
7407 * Note: Because Linux currently doesn't page the kernel and all
7408 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
7409 */
7410ADV_PADDR
7411DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007412 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007414 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007415
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007416 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007417
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007418 ASC_DBG4(4,
7419 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
7420 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
7421 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007422
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007423 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007424}
7425
7426/*
7427 * Read a PCI configuration byte.
7428 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007429static uchar __devinit DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007430{
7431#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007432 uchar byte_data;
7433 pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
7434 return byte_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007435#else /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007436 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007437#endif /* CONFIG_PCI */
7438}
7439
7440/*
7441 * Write a PCI configuration byte.
7442 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007443static void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007444DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007445{
7446#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007447 pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448#else /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007449 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007450#endif /* CONFIG_PCI */
7451}
7452
7453/*
7454 * --- Tracing and Debugging Functions
7455 */
7456
7457#ifdef ADVANSYS_STATS
7458#ifdef CONFIG_PROC_FS
7459/*
7460 * asc_prt_board_stats()
7461 *
7462 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7463 * cf. asc_prt_line().
7464 *
7465 * Return the number of characters copied into 'cp'. No more than
7466 * 'cplen' characters will be copied to 'cp'.
7467 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007468static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007469{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007470 int leftlen;
7471 int totlen;
7472 int len;
7473 struct asc_stats *s;
7474 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007475
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007476 leftlen = cplen;
7477 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007478
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007479 boardp = ASC_BOARDP(shost);
7480 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007481
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007482 len = asc_prt_line(cp, leftlen,
7483 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
7484 shost->host_no);
7485 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007486
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007487 len = asc_prt_line(cp, leftlen,
7488 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
7489 s->queuecommand, s->reset, s->biosparam,
7490 s->interrupt);
7491 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007492
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007493 len = asc_prt_line(cp, leftlen,
7494 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
7495 s->callback, s->done, s->build_error,
7496 s->adv_build_noreq, s->adv_build_nosg);
7497 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007498
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007499 len = asc_prt_line(cp, leftlen,
7500 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
7501 s->exe_noerror, s->exe_busy, s->exe_error,
7502 s->exe_unknown);
7503 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007504
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007505 /*
7506 * Display data transfer statistics.
7507 */
7508 if (s->cont_cnt > 0) {
7509 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
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, "cont_xfer %lu.%01lu kb ",
7513 s->cont_xfer / 2,
7514 ASC_TENTHS(s->cont_xfer, 2));
7515 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007516
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007517 /* Contiguous transfer average size */
7518 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
7519 (s->cont_xfer / 2) / s->cont_cnt,
7520 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
7521 ASC_PRT_NEXT();
7522 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007524 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007525
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007526 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
7527 s->sg_cnt, s->sg_elem);
7528 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007529
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007530 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
7531 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
7532 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007533
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007534 /* Scatter gather transfer statistics */
7535 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
7536 s->sg_elem / s->sg_cnt,
7537 ASC_TENTHS(s->sg_elem, s->sg_cnt));
7538 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007540 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
7541 (s->sg_xfer / 2) / s->sg_elem,
7542 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
7543 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007545 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
7546 (s->sg_xfer / 2) / s->sg_cnt,
7547 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
7548 ASC_PRT_NEXT();
7549 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007550
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007551 /*
7552 * Display request queuing statistics.
7553 */
7554 len = asc_prt_line(cp, leftlen,
7555 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
7556 HZ);
7557 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007558
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007559 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007560}
7561
7562/*
7563 * asc_prt_target_stats()
7564 *
7565 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
7566 * cf. asc_prt_line().
7567 *
7568 * This is separated from asc_prt_board_stats because a full set
7569 * of targets will overflow ASC_PRTBUF_SIZE.
7570 *
7571 * Return the number of characters copied into 'cp'. No more than
7572 * 'cplen' characters will be copied to 'cp'.
7573 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007574static int
7575asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007576{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007577 int leftlen;
7578 int totlen;
7579 int len;
7580 struct asc_stats *s;
7581 ushort chip_scsi_id;
7582 asc_board_t *boardp;
7583 asc_queue_t *active;
7584 asc_queue_t *waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007585
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007586 leftlen = cplen;
7587 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007588
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007589 boardp = ASC_BOARDP(shost);
7590 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007591
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007592 active = &ASC_BOARDP(shost)->active;
7593 waiting = &ASC_BOARDP(shost)->waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007594
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007595 if (ASC_NARROW_BOARD(boardp)) {
7596 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
7597 } else {
7598 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
7599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007600
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007601 if ((chip_scsi_id == tgt_id) ||
7602 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) {
7603 return 0;
7604 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007605
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007606 do {
7607 if (active->q_tot_cnt[tgt_id] > 0
7608 || waiting->q_tot_cnt[tgt_id] > 0) {
7609 len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id);
7610 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007612 len = asc_prt_line(cp, leftlen,
7613 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
7614 active->q_cur_cnt[tgt_id],
7615 active->q_max_cnt[tgt_id],
7616 active->q_tot_cnt[tgt_id],
7617 active->q_min_tim[tgt_id],
7618 active->q_max_tim[tgt_id],
7619 (active->q_tot_cnt[tgt_id] ==
7620 0) ? 0 : (active->
7621 q_tot_tim[tgt_id] /
7622 active->
7623 q_tot_cnt[tgt_id]),
7624 (active->q_tot_cnt[tgt_id] ==
7625 0) ? 0 : ASC_TENTHS(active->
7626 q_tot_tim
7627 [tgt_id],
7628 active->
7629 q_tot_cnt
7630 [tgt_id]));
7631 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07007632
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007633 len = asc_prt_line(cp, leftlen,
7634 " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
7635 waiting->q_cur_cnt[tgt_id],
7636 waiting->q_max_cnt[tgt_id],
7637 waiting->q_tot_cnt[tgt_id],
7638 waiting->q_min_tim[tgt_id],
7639 waiting->q_max_tim[tgt_id],
7640 (waiting->q_tot_cnt[tgt_id] ==
7641 0) ? 0 : (waiting->
7642 q_tot_tim[tgt_id] /
7643 waiting->
7644 q_tot_cnt[tgt_id]),
7645 (waiting->q_tot_cnt[tgt_id] ==
7646 0) ? 0 : ASC_TENTHS(waiting->
7647 q_tot_tim
7648 [tgt_id],
7649 waiting->
7650 q_tot_cnt
7651 [tgt_id]));
7652 ASC_PRT_NEXT();
7653 }
7654 } while (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007655
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007656 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007657}
7658#endif /* CONFIG_PROC_FS */
7659#endif /* ADVANSYS_STATS */
7660
7661#ifdef ADVANSYS_DEBUG
7662/*
7663 * asc_prt_scsi_host()
7664 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007665static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007666{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007667 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007669 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007671 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
7672 printk(" host_busy %u, host_no %d, last_reset %d,\n",
7673 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007675 printk(" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n",
7676 (ulong)s->base, (ulong)s->io_port, s->n_io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007677
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007678 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
7679 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007680
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007681 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
7682 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007683
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007684 if (ASC_NARROW_BOARD(boardp)) {
7685 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
7686 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
7687 } else {
7688 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
7689 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
7690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007691}
7692
7693/*
7694 * asc_prt_scsi_cmnd()
7695 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007696static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007697{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007698 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007699
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007700 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
7701 (ulong)s->device->host, (ulong)s->device, s->device->id,
7702 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007703
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007704 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007705
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007706 printk("sc_data_direction %u, resid %d\n",
7707 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007708
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007709 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007711 printk(" serial_number 0x%x, retries %d, allowed %d\n",
7712 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007713
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007714 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007716 printk
7717 (" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
7718 (ulong)s->scsi_done, (ulong)s->done, (ulong)s->host_scribble,
7719 s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007721 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007722}
7723
7724/*
7725 * asc_prt_asc_dvc_var()
7726 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007727static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007728{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007729 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007731 printk
7732 (" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n",
7733 h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007735 printk
7736 (" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n",
7737 h->bus_type, (ulong)h->isr_callback, (ulong)h->exe_callback,
7738 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007739
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007740 printk
7741 (" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n",
7742 (unsigned)h->sdtr_done, (unsigned)h->use_tagged_qng,
7743 (unsigned)h->unit_not_ready, (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007745 printk
7746 (" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n",
7747 (unsigned)h->queue_full_or_busy, (unsigned)h->start_motor,
7748 (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007749
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007750 printk
7751 (" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n",
7752 (unsigned)h->is_in_int, (unsigned)h->max_total_qng,
7753 (unsigned)h->cur_total_qng, (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007754
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007755 printk
7756 (" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n",
7757 (unsigned)h->last_q_shortage, (unsigned)h->init_state,
7758 (unsigned)h->no_scam, (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007759
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007760 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007761}
7762
7763/*
7764 * asc_prt_asc_dvc_cfg()
7765 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007766static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007767{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007768 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007770 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
7771 h->can_tagged_qng, h->cmd_qng_enabled);
7772 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
7773 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007774
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007775 printk
7776 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
7777 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
7778 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007779
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007780 printk
7781 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
7782 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
7783 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007785 printk(" mcode_version %d, overrun_buf 0x%lx\n",
7786 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007787}
7788
7789/*
7790 * asc_prt_asc_scsi_q()
7791 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007792static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007793{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007794 ASC_SG_HEAD *sgp;
7795 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007796
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007797 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007799 printk
7800 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
7801 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
7802 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007803
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007804 printk
7805 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
7806 (ulong)le32_to_cpu(q->q1.data_addr),
7807 (ulong)le32_to_cpu(q->q1.data_cnt),
7808 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007809
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007810 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
7811 (ulong)q->cdbptr, q->q2.cdb_len,
7812 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007813
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007814 if (q->sg_head) {
7815 sgp = q->sg_head;
7816 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
7817 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
7818 sgp->queue_cnt);
7819 for (i = 0; i < sgp->entry_cnt; i++) {
7820 printk(" [%u]: addr 0x%lx, bytes %lu\n",
7821 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
7822 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
7823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007824
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007826}
7827
7828/*
7829 * asc_prt_asc_qdone_info()
7830 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007831static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007832{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007833 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
7834 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
7835 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
7836 q->d2.tag_code);
7837 printk
7838 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
7839 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007840}
7841
7842/*
7843 * asc_prt_adv_dvc_var()
7844 *
7845 * Display an ADV_DVC_VAR structure.
7846 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007847static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007848{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007849 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007850
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007851 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
7852 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007853
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007854 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
7855 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
7856 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007858 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
7859 (unsigned)h->start_motor,
7860 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007861
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007862 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
7863 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
7864 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007866 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
7867 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007869 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
7870 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007871
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007872 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
7873 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007874}
7875
7876/*
7877 * asc_prt_adv_dvc_cfg()
7878 *
7879 * Display an ADV_DVC_CFG structure.
7880 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007881static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007882{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007883 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007884
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007885 printk(" disc_enable 0x%x, termination 0x%x\n",
7886 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007888 printk(" chip_version 0x%x, mcode_date 0x%x\n",
7889 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007890
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007891 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
7892 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007893
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007894 printk(" control_flag 0x%x, pci_slot_info 0x%x\n",
7895 h->control_flag, h->pci_slot_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007896}
7897
7898/*
7899 * asc_prt_adv_scsi_req_q()
7900 *
7901 * Display an ADV_SCSI_REQ_Q structure.
7902 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007903static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007904{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007905 int sg_blk_cnt;
7906 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007907
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007908 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007910 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
7911 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007912
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007913 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
7914 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007916 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
7917 (ulong)le32_to_cpu(q->data_cnt),
7918 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007920 printk
7921 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
7922 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007923
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007924 printk(" sg_working_ix 0x%x, target_cmd %u\n",
7925 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007926
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007927 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
7928 (ulong)le32_to_cpu(q->scsiq_rptr),
7929 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007930
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007931 /* Display the request's ADV_SG_BLOCK structures. */
7932 if (q->sg_list_ptr != NULL) {
7933 sg_blk_cnt = 0;
7934 while (1) {
7935 /*
7936 * 'sg_ptr' is a physical address. Convert it to a virtual
7937 * address by indexing 'sg_blk_cnt' into the virtual address
7938 * array 'sg_list_ptr'.
7939 *
7940 * XXX - Assumes all SG physical blocks are virtually contiguous.
7941 */
7942 sg_ptr =
7943 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
7944 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
7945 if (sg_ptr->sg_ptr == 0) {
7946 break;
7947 }
7948 sg_blk_cnt++;
7949 }
7950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007951}
7952
7953/*
7954 * asc_prt_adv_sgblock()
7955 *
7956 * Display an ADV_SG_BLOCK structure.
7957 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007958static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007959{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007960 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007961
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007962 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
7963 (ulong)b, sgblockno);
7964 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
7965 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
7966 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
7967 if (b->sg_ptr != 0) {
7968 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
7969 }
7970 for (i = 0; i < b->sg_cnt; i++) {
7971 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
7972 i, (ulong)b->sg_list[i].sg_addr,
7973 (ulong)b->sg_list[i].sg_count);
7974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007975}
7976
7977/*
7978 * asc_prt_hex()
7979 *
7980 * Print hexadecimal output in 4 byte groupings 32 bytes
7981 * or 8 double-words per line.
7982 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007983static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007984{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007985 int i;
7986 int j;
7987 int k;
7988 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007990 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007992 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007994 /* Display a maximum of 8 double-words per line. */
7995 if ((k = (l - i) / 4) >= 8) {
7996 k = 8;
7997 m = 0;
7998 } else {
7999 m = (l - i) % 4;
8000 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008002 for (j = 0; j < k; j++) {
8003 printk(" %2.2X%2.2X%2.2X%2.2X",
8004 (unsigned)s[i + (j * 4)],
8005 (unsigned)s[i + (j * 4) + 1],
8006 (unsigned)s[i + (j * 4) + 2],
8007 (unsigned)s[i + (j * 4) + 3]);
8008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008009
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008010 switch (m) {
8011 case 0:
8012 default:
8013 break;
8014 case 1:
8015 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
8016 break;
8017 case 2:
8018 printk(" %2.2X%2.2X",
8019 (unsigned)s[i + (j * 4)],
8020 (unsigned)s[i + (j * 4) + 1]);
8021 break;
8022 case 3:
8023 printk(" %2.2X%2.2X%2.2X",
8024 (unsigned)s[i + (j * 4) + 1],
8025 (unsigned)s[i + (j * 4) + 2],
8026 (unsigned)s[i + (j * 4) + 3]);
8027 break;
8028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008030 printk("\n");
8031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008032}
8033#endif /* ADVANSYS_DEBUG */
8034
8035/*
8036 * --- Asc Library Functions
8037 */
8038
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008039static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008040{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008041 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008043 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
8044 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
8045 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008046}
8047
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008048static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008049{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008050 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008051
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008052 if (AscGetChipScsiID(iop_base) == new_host_id) {
8053 return (new_host_id);
8054 }
8055 cfg_lsw = AscGetChipCfgLsw(iop_base);
8056 cfg_lsw &= 0xF8FF;
8057 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
8058 AscSetChipCfgLsw(iop_base, cfg_lsw);
8059 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008060}
8061
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008062static uchar __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008063{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008064 uchar sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008066 AscSetBank(iop_base, 1);
8067 sc = inp(iop_base + IOP_REG_SC);
8068 AscSetBank(iop_base, 0);
8069 return (sc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008070}
8071
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008072static uchar __devinit AscGetChipVersion(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008073{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008074 if ((bus_type & ASC_IS_EISA) != 0) {
8075 PortAddr eisa_iop;
8076 uchar revision;
8077 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
8078 (PortAddr) ASC_EISA_REV_IOP_MASK;
8079 revision = inp(eisa_iop);
8080 return ((uchar)((ASC_CHIP_MIN_VER_EISA - 1) + revision));
8081 }
8082 return (AscGetChipVerNo(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008083}
8084
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008085static ushort __devinit AscGetChipBusType(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008086{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008087 ushort chip_ver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008089 chip_ver = AscGetChipVerNo(iop_base);
8090 if ((chip_ver >= ASC_CHIP_MIN_VER_VL)
8091 && (chip_ver <= ASC_CHIP_MAX_VER_VL)
8092 ) {
8093 if (((iop_base & 0x0C30) == 0x0C30)
8094 || ((iop_base & 0x0C50) == 0x0C50)
8095 ) {
8096 return (ASC_IS_EISA);
8097 }
8098 return (ASC_IS_VL);
8099 }
8100 if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
8101 (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
8102 if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
8103 return (ASC_IS_ISAPNP);
8104 }
8105 return (ASC_IS_ISA);
8106 } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
8107 (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
8108 return (ASC_IS_PCI);
8109 }
8110 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008111}
8112
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008113static ASC_DCNT
8114AscLoadMicroCode(PortAddr iop_base,
8115 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008116{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008117 ASC_DCNT chksum;
8118 ushort mcode_word_size;
8119 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008120
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008121 /* Write the microcode buffer starting at LRAM address 0. */
8122 mcode_word_size = (ushort)(mcode_size >> 1);
8123 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
8124 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008125
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008126 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
8127 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
8128 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
8129 (ushort)ASC_CODE_SEC_BEG,
8130 (ushort)((mcode_size -
8131 s_addr - (ushort)
8132 ASC_CODE_SEC_BEG) /
8133 2));
8134 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
8135 (ulong)mcode_chksum);
8136 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
8137 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
8138 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008139}
8140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008141static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008142{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008143 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008144
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008145 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
8146 iop_base, AscGetChipSignatureByte(iop_base));
8147 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
8148 ASC_DBG2(1,
8149 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
8150 iop_base, AscGetChipSignatureWord(iop_base));
8151 sig_word = AscGetChipSignatureWord(iop_base);
8152 if ((sig_word == (ushort)ASC_1000_ID0W) ||
8153 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
8154 return (1);
8155 }
8156 }
8157 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008158}
8159
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008160static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008161{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008162 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
8163 AscSetChipStatus(iop_base, 0);
8164 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008165}
8166
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008167static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008168{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008169 ushort cfg_lsw;
8170 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008171
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008172 if ((bus_type & ASC_IS_EISA) != 0) {
8173 cfg_lsw = AscGetEisaChipCfg(iop_base);
8174 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
8175 if ((chip_irq == 13) || (chip_irq > 15)) {
8176 return (0);
8177 }
8178 return (chip_irq);
8179 }
8180 if ((bus_type & ASC_IS_VL) != 0) {
8181 cfg_lsw = AscGetChipCfgLsw(iop_base);
8182 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
8183 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
8184 return (0);
8185 }
8186 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
8187 }
8188 cfg_lsw = AscGetChipCfgLsw(iop_base);
8189 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
8190 if (chip_irq == 3)
8191 chip_irq += (uchar)2;
8192 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008193}
8194
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008195static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008196AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008197{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008198 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008200 if ((bus_type & ASC_IS_VL) != 0) {
8201 if (irq_no != 0) {
8202 if ((irq_no < ASC_MIN_IRQ_NO)
8203 || (irq_no > ASC_MAX_IRQ_NO)) {
8204 irq_no = 0;
8205 } else {
8206 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
8207 }
8208 }
8209 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
8210 cfg_lsw |= (ushort)0x0010;
8211 AscSetChipCfgLsw(iop_base, cfg_lsw);
8212 AscToggleIRQAct(iop_base);
8213 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
8214 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
8215 AscSetChipCfgLsw(iop_base, cfg_lsw);
8216 AscToggleIRQAct(iop_base);
8217 return (AscGetChipIRQ(iop_base, bus_type));
8218 }
8219 if ((bus_type & (ASC_IS_ISA)) != 0) {
8220 if (irq_no == 15)
8221 irq_no -= (uchar)2;
8222 irq_no -= (uchar)ASC_MIN_IRQ_NO;
8223 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
8224 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
8225 AscSetChipCfgLsw(iop_base, cfg_lsw);
8226 return (AscGetChipIRQ(iop_base, bus_type));
8227 }
8228 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008229}
8230
8231#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008232static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008233{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008234 if (dma_channel < 4) {
8235 outp(0x000B, (ushort)(0xC0 | dma_channel));
8236 outp(0x000A, dma_channel);
8237 } else if (dma_channel < 8) {
8238 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
8239 outp(0x00D4, (ushort)(dma_channel - 4));
8240 }
8241 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008242}
8243#endif /* CONFIG_ISA */
8244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008245static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008246{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008247 EXT_MSG ext_msg;
8248 EXT_MSG out_msg;
8249 ushort halt_q_addr;
8250 int sdtr_accept;
8251 ushort int_halt_code;
8252 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8253 ASC_SCSI_BIT_ID_TYPE target_id;
8254 PortAddr iop_base;
8255 uchar tag_code;
8256 uchar q_status;
8257 uchar halt_qp;
8258 uchar sdtr_data;
8259 uchar target_ix;
8260 uchar q_cntl, tid_no;
8261 uchar cur_dvc_qng;
8262 uchar asyn_sdtr;
8263 uchar scsi_status;
8264 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008265
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008266 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
8267 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008268
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008269 iop_base = asc_dvc->iop_base;
8270 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008272 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8273 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8274 target_ix = AscReadLramByte(iop_base,
8275 (ushort)(halt_q_addr +
8276 (ushort)ASC_SCSIQ_B_TARGET_IX));
8277 q_cntl =
8278 AscReadLramByte(iop_base,
8279 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8280 tid_no = ASC_TIX_TO_TID(target_ix);
8281 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8282 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8283 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8284 } else {
8285 asyn_sdtr = 0;
8286 }
8287 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8288 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8289 AscSetChipSDTR(iop_base, 0, tid_no);
8290 boardp->sdtr_data[tid_no] = 0;
8291 }
8292 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8293 return (0);
8294 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8295 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8296 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8297 boardp->sdtr_data[tid_no] = asyn_sdtr;
8298 }
8299 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8300 return (0);
8301 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008303 AscMemWordCopyPtrFromLram(iop_base,
8304 ASCV_MSGIN_BEG,
8305 (uchar *)&ext_msg,
8306 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008307
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008308 if (ext_msg.msg_type == MS_EXTEND &&
8309 ext_msg.msg_req == MS_SDTR_CODE &&
8310 ext_msg.msg_len == MS_SDTR_LEN) {
8311 sdtr_accept = TRUE;
8312 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008313
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008314 sdtr_accept = FALSE;
8315 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8316 }
8317 if ((ext_msg.xfer_period <
8318 asc_dvc->sdtr_period_tbl[asc_dvc->
8319 host_init_sdtr_index])
8320 || (ext_msg.xfer_period >
8321 asc_dvc->sdtr_period_tbl[asc_dvc->
8322 max_sdtr_index])) {
8323 sdtr_accept = FALSE;
8324 ext_msg.xfer_period =
8325 asc_dvc->sdtr_period_tbl[asc_dvc->
8326 host_init_sdtr_index];
8327 }
8328 if (sdtr_accept) {
8329 sdtr_data =
8330 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8331 ext_msg.req_ack_offset);
8332 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008333
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008334 q_cntl |= QC_MSG_OUT;
8335 asc_dvc->init_sdtr &= ~target_id;
8336 asc_dvc->sdtr_done &= ~target_id;
8337 AscSetChipSDTR(iop_base, asyn_sdtr,
8338 tid_no);
8339 boardp->sdtr_data[tid_no] = asyn_sdtr;
8340 }
8341 }
8342 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008343
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008344 q_cntl &= ~QC_MSG_OUT;
8345 asc_dvc->init_sdtr &= ~target_id;
8346 asc_dvc->sdtr_done &= ~target_id;
8347 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8348 } else {
8349 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008351 q_cntl &= ~QC_MSG_OUT;
8352 asc_dvc->sdtr_done |= target_id;
8353 asc_dvc->init_sdtr |= target_id;
8354 asc_dvc->pci_fix_asyn_xfer &=
8355 ~target_id;
8356 sdtr_data =
8357 AscCalSDTRData(asc_dvc,
8358 ext_msg.xfer_period,
8359 ext_msg.
8360 req_ack_offset);
8361 AscSetChipSDTR(iop_base, sdtr_data,
8362 tid_no);
8363 boardp->sdtr_data[tid_no] = sdtr_data;
8364 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008366 q_cntl |= QC_MSG_OUT;
8367 AscMsgOutSDTR(asc_dvc,
8368 ext_msg.xfer_period,
8369 ext_msg.req_ack_offset);
8370 asc_dvc->pci_fix_asyn_xfer &=
8371 ~target_id;
8372 sdtr_data =
8373 AscCalSDTRData(asc_dvc,
8374 ext_msg.xfer_period,
8375 ext_msg.
8376 req_ack_offset);
8377 AscSetChipSDTR(iop_base, sdtr_data,
8378 tid_no);
8379 boardp->sdtr_data[tid_no] = sdtr_data;
8380 asc_dvc->sdtr_done |= target_id;
8381 asc_dvc->init_sdtr |= target_id;
8382 }
8383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008384
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008385 AscWriteLramByte(iop_base,
8386 (ushort)(halt_q_addr +
8387 (ushort)ASC_SCSIQ_B_CNTL),
8388 q_cntl);
8389 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8390 return (0);
8391 } else if (ext_msg.msg_type == MS_EXTEND &&
8392 ext_msg.msg_req == MS_WDTR_CODE &&
8393 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008394
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008395 ext_msg.wdtr_width = 0;
8396 AscMemWordCopyPtrToLram(iop_base,
8397 ASCV_MSGOUT_BEG,
8398 (uchar *)&ext_msg,
8399 sizeof(EXT_MSG) >> 1);
8400 q_cntl |= QC_MSG_OUT;
8401 AscWriteLramByte(iop_base,
8402 (ushort)(halt_q_addr +
8403 (ushort)ASC_SCSIQ_B_CNTL),
8404 q_cntl);
8405 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8406 return (0);
8407 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008408
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008409 ext_msg.msg_type = MESSAGE_REJECT;
8410 AscMemWordCopyPtrToLram(iop_base,
8411 ASCV_MSGOUT_BEG,
8412 (uchar *)&ext_msg,
8413 sizeof(EXT_MSG) >> 1);
8414 q_cntl |= QC_MSG_OUT;
8415 AscWriteLramByte(iop_base,
8416 (ushort)(halt_q_addr +
8417 (ushort)ASC_SCSIQ_B_CNTL),
8418 q_cntl);
8419 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8420 return (0);
8421 }
8422 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008424 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008425
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008426 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008428 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008430 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8431 q_cntl |= QC_MSG_OUT;
8432 AscMsgOutSDTR(asc_dvc,
8433 asc_dvc->
8434 sdtr_period_tbl[(sdtr_data >> 4) &
8435 (uchar)(asc_dvc->
8436 max_sdtr_index -
8437 1)],
8438 (uchar)(sdtr_data & (uchar)
8439 ASC_SYN_MAX_OFFSET));
8440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008441
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008442 AscWriteLramByte(iop_base,
8443 (ushort)(halt_q_addr +
8444 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008446 tag_code = AscReadLramByte(iop_base,
8447 (ushort)(halt_q_addr + (ushort)
8448 ASC_SCSIQ_B_TAG_CODE));
8449 tag_code &= 0xDC;
8450 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
8451 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
8452 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008453
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008454 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
8455 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008456
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008457 }
8458 AscWriteLramByte(iop_base,
8459 (ushort)(halt_q_addr +
8460 (ushort)ASC_SCSIQ_B_TAG_CODE),
8461 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008463 q_status = AscReadLramByte(iop_base,
8464 (ushort)(halt_q_addr + (ushort)
8465 ASC_SCSIQ_B_STATUS));
8466 q_status |= (QS_READY | QS_BUSY);
8467 AscWriteLramByte(iop_base,
8468 (ushort)(halt_q_addr +
8469 (ushort)ASC_SCSIQ_B_STATUS),
8470 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008471
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008472 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
8473 scsi_busy &= ~target_id;
8474 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008475
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008476 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8477 return (0);
8478 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008479
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008480 AscMemWordCopyPtrFromLram(iop_base,
8481 ASCV_MSGOUT_BEG,
8482 (uchar *)&out_msg,
8483 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008485 if ((out_msg.msg_type == MS_EXTEND) &&
8486 (out_msg.msg_len == MS_SDTR_LEN) &&
8487 (out_msg.msg_req == MS_SDTR_CODE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008488
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008489 asc_dvc->init_sdtr &= ~target_id;
8490 asc_dvc->sdtr_done &= ~target_id;
8491 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8492 boardp->sdtr_data[tid_no] = asyn_sdtr;
8493 }
8494 q_cntl &= ~QC_MSG_OUT;
8495 AscWriteLramByte(iop_base,
8496 (ushort)(halt_q_addr +
8497 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8498 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8499 return (0);
8500 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008501
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008502 scsi_status = AscReadLramByte(iop_base,
8503 (ushort)((ushort)halt_q_addr +
8504 (ushort)
8505 ASC_SCSIQ_SCSI_STATUS));
8506 cur_dvc_qng =
8507 AscReadLramByte(iop_base,
8508 (ushort)((ushort)ASC_QADR_BEG +
8509 (ushort)target_ix));
8510 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008511
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008512 scsi_busy = AscReadLramByte(iop_base,
8513 (ushort)ASCV_SCSIBUSY_B);
8514 scsi_busy |= target_id;
8515 AscWriteLramByte(iop_base,
8516 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8517 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008518
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008519 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
8520 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
8521 cur_dvc_qng -= 1;
8522 asc_dvc->max_dvc_qng[tid_no] =
8523 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008524
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008525 AscWriteLramByte(iop_base,
8526 (ushort)((ushort)
8527 ASCV_MAX_DVC_QNG_BEG
8528 + (ushort)
8529 tid_no),
8530 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008531
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008532 /*
8533 * Set the device queue depth to the number of
8534 * active requests when the QUEUE FULL condition
8535 * was encountered.
8536 */
8537 boardp->queue_full |= target_id;
8538 boardp->queue_full_cnt[tid_no] =
8539 cur_dvc_qng;
8540 }
8541 }
8542 }
8543 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8544 return (0);
8545 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008546#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008547 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
8548 uchar q_no;
8549 ushort q_addr;
8550 uchar sg_wk_q_no;
8551 uchar first_sg_wk_q_no;
8552 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
8553 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
8554 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
8555 ushort sg_list_dwords;
8556 ushort sg_entry_cnt;
8557 uchar next_qp;
8558 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008559
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008560 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
8561 if (q_no == ASC_QLINK_END) {
8562 return (0);
8563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008564
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008565 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008566
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008567 /*
8568 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
8569 * structure pointer using a macro provided by the driver.
8570 * The ASC_SCSI_REQ pointer provides a pointer to the
8571 * host ASC_SG_HEAD structure.
8572 */
8573 /* Read request's SRB pointer. */
8574 scsiq = (ASC_SCSI_Q *)
8575 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
8576 (ushort)
8577 (q_addr +
8578 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008580 /*
8581 * Get request's first and working SG queue.
8582 */
8583 sg_wk_q_no = AscReadLramByte(iop_base,
8584 (ushort)(q_addr +
8585 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008587 first_sg_wk_q_no = AscReadLramByte(iop_base,
8588 (ushort)(q_addr +
8589 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008590
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008591 /*
8592 * Reset request's working SG queue back to the
8593 * first SG queue.
8594 */
8595 AscWriteLramByte(iop_base,
8596 (ushort)(q_addr +
8597 (ushort)ASC_SCSIQ_B_SG_WK_QP),
8598 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008599
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008600 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008602 /*
8603 * Set sg_entry_cnt to the number of SG elements
8604 * that will be completed on this interrupt.
8605 *
8606 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
8607 * SG elements. The data_cnt and data_addr fields which
8608 * add 1 to the SG element capacity are not used when
8609 * restarting SG handling after a halt.
8610 */
8611 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
8612 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008613
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008614 /*
8615 * Keep track of remaining number of SG elements that will
8616 * need to be handled on the next interrupt.
8617 */
8618 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
8619 } else {
8620 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
8621 scsiq->remain_sg_entry_cnt = 0;
8622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008623
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008624 /*
8625 * Copy SG elements into the list of allocated SG queues.
8626 *
8627 * Last index completed is saved in scsiq->next_sg_index.
8628 */
8629 next_qp = first_sg_wk_q_no;
8630 q_addr = ASC_QNO_TO_QADDR(next_qp);
8631 scsi_sg_q.sg_head_qp = q_no;
8632 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
8633 for (i = 0; i < sg_head->queue_cnt; i++) {
8634 scsi_sg_q.seq_no = i + 1;
8635 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
8636 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
8637 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8638 /*
8639 * After very first SG queue RISC FW uses next
8640 * SG queue first element then checks sg_list_cnt
8641 * against zero and then decrements, so set
8642 * sg_list_cnt 1 less than number of SG elements
8643 * in each SG queue.
8644 */
8645 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
8646 scsi_sg_q.sg_cur_list_cnt =
8647 ASC_SG_LIST_PER_Q - 1;
8648 } else {
8649 /*
8650 * This is the last SG queue in the list of
8651 * allocated SG queues. If there are more
8652 * SG elements than will fit in the allocated
8653 * queues, then set the QCSG_SG_XFER_MORE flag.
8654 */
8655 if (scsiq->remain_sg_entry_cnt != 0) {
8656 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8657 } else {
8658 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
8659 }
8660 /* equals sg_entry_cnt * 2 */
8661 sg_list_dwords = sg_entry_cnt << 1;
8662 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
8663 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
8664 sg_entry_cnt = 0;
8665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008667 scsi_sg_q.q_no = next_qp;
8668 AscMemWordCopyPtrToLram(iop_base,
8669 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8670 (uchar *)&scsi_sg_q,
8671 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008672
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008673 AscMemDWordCopyPtrToLram(iop_base,
8674 q_addr + ASC_SGQ_LIST_BEG,
8675 (uchar *)&sg_head->
8676 sg_list[scsiq->next_sg_index],
8677 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008679 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008680
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008681 /*
8682 * If the just completed SG queue contained the
8683 * last SG element, then no more SG queues need
8684 * to be written.
8685 */
8686 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
8687 break;
8688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008689
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008690 next_qp = AscReadLramByte(iop_base,
8691 (ushort)(q_addr +
8692 ASC_SCSIQ_B_FWD));
8693 q_addr = ASC_QNO_TO_QADDR(next_qp);
8694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008696 /*
8697 * Clear the halt condition so the RISC will be restarted
8698 * after the return.
8699 */
8700 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8701 return (0);
8702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008703#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008704 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008705}
8706
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008707static uchar
8708_AscCopyLramScsiDoneQ(PortAddr iop_base,
8709 ushort q_addr,
8710 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008711{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008712 ushort _val;
8713 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008714
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008715 DvcGetQinfo(iop_base,
8716 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
8717 (uchar *)scsiq,
8718 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008720 _val = AscReadLramWord(iop_base,
8721 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
8722 scsiq->q_status = (uchar)_val;
8723 scsiq->q_no = (uchar)(_val >> 8);
8724 _val = AscReadLramWord(iop_base,
8725 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8726 scsiq->cntl = (uchar)_val;
8727 sg_queue_cnt = (uchar)(_val >> 8);
8728 _val = AscReadLramWord(iop_base,
8729 (ushort)(q_addr +
8730 (ushort)ASC_SCSIQ_B_SENSE_LEN));
8731 scsiq->sense_len = (uchar)_val;
8732 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008733
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008734 /*
8735 * Read high word of remain bytes from alternate location.
8736 */
8737 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
8738 (ushort)(q_addr +
8739 (ushort)
8740 ASC_SCSIQ_W_ALT_DC1)))
8741 << 16);
8742 /*
8743 * Read low word of remain bytes from original location.
8744 */
8745 scsiq->remain_bytes += AscReadLramWord(iop_base,
8746 (ushort)(q_addr + (ushort)
8747 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008749 scsiq->remain_bytes &= max_dma_count;
8750 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008751}
8752
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008753static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008754{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008755 uchar next_qp;
8756 uchar n_q_used;
8757 uchar sg_list_qp;
8758 uchar sg_queue_cnt;
8759 uchar q_cnt;
8760 uchar done_q_tail;
8761 uchar tid_no;
8762 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8763 ASC_SCSI_BIT_ID_TYPE target_id;
8764 PortAddr iop_base;
8765 ushort q_addr;
8766 ushort sg_q_addr;
8767 uchar cur_target_qng;
8768 ASC_QDONE_INFO scsiq_buf;
8769 ASC_QDONE_INFO *scsiq;
8770 int false_overrun;
8771 ASC_ISR_CALLBACK asc_isr_callback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008772
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008773 iop_base = asc_dvc->iop_base;
8774 asc_isr_callback = asc_dvc->isr_callback;
8775 n_q_used = 1;
8776 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
8777 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
8778 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
8779 next_qp = AscReadLramByte(iop_base,
8780 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
8781 if (next_qp != ASC_QLINK_END) {
8782 AscPutVarDoneQTail(iop_base, next_qp);
8783 q_addr = ASC_QNO_TO_QADDR(next_qp);
8784 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
8785 asc_dvc->max_dma_count);
8786 AscWriteLramByte(iop_base,
8787 (ushort)(q_addr +
8788 (ushort)ASC_SCSIQ_B_STATUS),
8789 (uchar)(scsiq->
8790 q_status & (uchar)~(QS_READY |
8791 QS_ABORTED)));
8792 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
8793 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
8794 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
8795 sg_q_addr = q_addr;
8796 sg_list_qp = next_qp;
8797 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
8798 sg_list_qp = AscReadLramByte(iop_base,
8799 (ushort)(sg_q_addr
8800 + (ushort)
8801 ASC_SCSIQ_B_FWD));
8802 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
8803 if (sg_list_qp == ASC_QLINK_END) {
8804 AscSetLibErrorCode(asc_dvc,
8805 ASCQ_ERR_SG_Q_LINKS);
8806 scsiq->d3.done_stat = QD_WITH_ERROR;
8807 scsiq->d3.host_stat =
8808 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
8809 goto FATAL_ERR_QDONE;
8810 }
8811 AscWriteLramByte(iop_base,
8812 (ushort)(sg_q_addr + (ushort)
8813 ASC_SCSIQ_B_STATUS),
8814 QS_FREE);
8815 }
8816 n_q_used = sg_queue_cnt + 1;
8817 AscPutVarDoneQTail(iop_base, sg_list_qp);
8818 }
8819 if (asc_dvc->queue_full_or_busy & target_id) {
8820 cur_target_qng = AscReadLramByte(iop_base,
8821 (ushort)((ushort)
8822 ASC_QADR_BEG
8823 + (ushort)
8824 scsiq->d2.
8825 target_ix));
8826 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
8827 scsi_busy = AscReadLramByte(iop_base, (ushort)
8828 ASCV_SCSIBUSY_B);
8829 scsi_busy &= ~target_id;
8830 AscWriteLramByte(iop_base,
8831 (ushort)ASCV_SCSIBUSY_B,
8832 scsi_busy);
8833 asc_dvc->queue_full_or_busy &= ~target_id;
8834 }
8835 }
8836 if (asc_dvc->cur_total_qng >= n_q_used) {
8837 asc_dvc->cur_total_qng -= n_q_used;
8838 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
8839 asc_dvc->cur_dvc_qng[tid_no]--;
8840 }
8841 } else {
8842 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
8843 scsiq->d3.done_stat = QD_WITH_ERROR;
8844 goto FATAL_ERR_QDONE;
8845 }
8846 if ((scsiq->d2.srb_ptr == 0UL) ||
8847 ((scsiq->q_status & QS_ABORTED) != 0)) {
8848 return (0x11);
8849 } else if (scsiq->q_status == QS_DONE) {
8850 false_overrun = FALSE;
8851 if (scsiq->extra_bytes != 0) {
8852 scsiq->remain_bytes +=
8853 (ADV_DCNT)scsiq->extra_bytes;
8854 }
8855 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
8856 if (scsiq->d3.host_stat ==
8857 QHSTA_M_DATA_OVER_RUN) {
8858 if ((scsiq->
8859 cntl & (QC_DATA_IN | QC_DATA_OUT))
8860 == 0) {
8861 scsiq->d3.done_stat =
8862 QD_NO_ERROR;
8863 scsiq->d3.host_stat =
8864 QHSTA_NO_ERROR;
8865 } else if (false_overrun) {
8866 scsiq->d3.done_stat =
8867 QD_NO_ERROR;
8868 scsiq->d3.host_stat =
8869 QHSTA_NO_ERROR;
8870 }
8871 } else if (scsiq->d3.host_stat ==
8872 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
8873 AscStopChip(iop_base);
8874 AscSetChipControl(iop_base,
8875 (uchar)(CC_SCSI_RESET
8876 | CC_HALT));
8877 DvcDelayNanoSecond(asc_dvc, 60000);
8878 AscSetChipControl(iop_base, CC_HALT);
8879 AscSetChipStatus(iop_base,
8880 CIW_CLR_SCSI_RESET_INT);
8881 AscSetChipStatus(iop_base, 0);
8882 AscSetChipControl(iop_base, 0);
8883 }
8884 }
8885 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
8886 (*asc_isr_callback) (asc_dvc, scsiq);
8887 } else {
8888 if ((AscReadLramByte(iop_base,
8889 (ushort)(q_addr + (ushort)
8890 ASC_SCSIQ_CDB_BEG))
8891 == START_STOP)) {
8892 asc_dvc->unit_not_ready &= ~target_id;
8893 if (scsiq->d3.done_stat != QD_NO_ERROR) {
8894 asc_dvc->start_motor &=
8895 ~target_id;
8896 }
8897 }
8898 }
8899 return (1);
8900 } else {
8901 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
8902 FATAL_ERR_QDONE:
8903 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
8904 (*asc_isr_callback) (asc_dvc, scsiq);
8905 }
8906 return (0x80);
8907 }
8908 }
8909 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008910}
8911
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008912static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008913{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008914 ASC_CS_TYPE chipstat;
8915 PortAddr iop_base;
8916 ushort saved_ram_addr;
8917 uchar ctrl_reg;
8918 uchar saved_ctrl_reg;
8919 int int_pending;
8920 int status;
8921 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008922
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008923 iop_base = asc_dvc->iop_base;
8924 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008926 if (AscIsIntPending(iop_base) == 0) {
8927 return int_pending;
8928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008930 if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
8931 || (asc_dvc->isr_callback == 0)
8932 ) {
8933 return (ERR);
8934 }
8935 if (asc_dvc->in_critical_cnt != 0) {
8936 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
8937 return (ERR);
8938 }
8939 if (asc_dvc->is_in_int) {
8940 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
8941 return (ERR);
8942 }
8943 asc_dvc->is_in_int = TRUE;
8944 ctrl_reg = AscGetChipControl(iop_base);
8945 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
8946 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
8947 chipstat = AscGetChipStatus(iop_base);
8948 if (chipstat & CSW_SCSI_RESET_LATCH) {
8949 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
8950 int i = 10;
8951 int_pending = TRUE;
8952 asc_dvc->sdtr_done = 0;
8953 saved_ctrl_reg &= (uchar)(~CC_HALT);
8954 while ((AscGetChipStatus(iop_base) &
8955 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
8956 DvcSleepMilliSecond(100);
8957 }
8958 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
8959 AscSetChipControl(iop_base, CC_HALT);
8960 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
8961 AscSetChipStatus(iop_base, 0);
8962 chipstat = AscGetChipStatus(iop_base);
8963 }
8964 }
8965 saved_ram_addr = AscGetChipLramAddr(iop_base);
8966 host_flag = AscReadLramByte(iop_base,
8967 ASCV_HOST_FLAG_B) &
8968 (uchar)(~ASC_HOST_FLAG_IN_ISR);
8969 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8970 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
8971 if ((chipstat & CSW_INT_PENDING)
8972 || (int_pending)
8973 ) {
8974 AscAckInterrupt(iop_base);
8975 int_pending = TRUE;
8976 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
8977 if (AscIsrChipHalted(asc_dvc) == ERR) {
8978 goto ISR_REPORT_QDONE_FATAL_ERROR;
8979 } else {
8980 saved_ctrl_reg &= (uchar)(~CC_HALT);
8981 }
8982 } else {
8983 ISR_REPORT_QDONE_FATAL_ERROR:
8984 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
8985 while (((status =
8986 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
8987 }
8988 } else {
8989 do {
8990 if ((status =
8991 AscIsrQDone(asc_dvc)) == 1) {
8992 break;
8993 }
8994 } while (status == 0x11);
8995 }
8996 if ((status & 0x80) != 0)
8997 int_pending = ERR;
8998 }
8999 }
9000 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9001 AscSetChipLramAddr(iop_base, saved_ram_addr);
9002 AscSetChipControl(iop_base, saved_ctrl_reg);
9003 asc_dvc->is_in_int = FALSE;
9004 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009005}
9006
9007/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009008static uchar _asc_mcode_buf[] = {
9009 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9010 0x00, 0x00, 0x00, 0x00,
9011 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
9012 0x00, 0x00, 0x00, 0x00,
9013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9014 0x00, 0x00, 0x00, 0x00,
9015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9016 0x00, 0x00, 0x00, 0x00,
9017 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00,
9018 0x00, 0xFF, 0x00, 0x00,
9019 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
9020 0x00, 0x00, 0x00, 0x00,
9021 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
9022 0x00, 0x00, 0x00, 0x00,
9023 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88,
9024 0x00, 0x00, 0x00, 0x00,
9025 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73,
9026 0x03, 0x23, 0x36, 0x40,
9027 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
9028 0xC2, 0x00, 0x92, 0x80,
9029 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60,
9030 0xB6, 0x00, 0x92, 0x80,
9031 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00,
9032 0x92, 0x80, 0x80, 0x62,
9033 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
9034 0xCD, 0x04, 0x4D, 0x00,
9035 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01,
9036 0xE6, 0x84, 0xD2, 0xC1,
9037 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97,
9038 0xC6, 0x81, 0xC2, 0x88,
9039 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
9040 0x84, 0x97, 0x07, 0xA6,
9041 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE,
9042 0xC2, 0x88, 0xCE, 0x00,
9043 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01,
9044 0x80, 0x63, 0x07, 0xA6,
9045 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
9046 0x34, 0x01, 0x00, 0x33,
9047 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23,
9048 0x68, 0x98, 0x4D, 0x04,
9049 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23,
9050 0xF8, 0x88, 0xFB, 0x23,
9051 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
9052 0x00, 0x33, 0x0A, 0x00,
9053 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00,
9054 0xC2, 0x88, 0xCD, 0x04,
9055 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81,
9056 0x06, 0xAB, 0x82, 0x01,
9057 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
9058 0x3C, 0x01, 0x00, 0x05,
9059 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01,
9060 0x15, 0x23, 0xA1, 0x01,
9061 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00,
9062 0x06, 0x61, 0x00, 0xA0,
9063 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
9064 0xC2, 0x88, 0x06, 0x23,
9065 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01,
9066 0x57, 0x60, 0x00, 0xA0,
9067 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73,
9068 0x4B, 0x00, 0x06, 0x61,
9069 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
9070 0x4F, 0x00, 0x84, 0x97,
9071 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97,
9072 0x48, 0x04, 0x84, 0x80,
9073 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00,
9074 0x81, 0x73, 0x06, 0x29,
9075 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
9076 0x04, 0x98, 0xF0, 0x80,
9077 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6,
9078 0x34, 0x02, 0x03, 0xA6,
9079 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96,
9080 0x46, 0x82, 0xFE, 0x95,
9081 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
9082 0x07, 0xA6, 0x5A, 0x02,
9083 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95,
9084 0x48, 0x82, 0x60, 0x96,
9085 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84,
9086 0x04, 0x01, 0x0C, 0xDC,
9087 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
9088 0x6F, 0x00, 0xA5, 0x01,
9089 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01,
9090 0x02, 0xA6, 0xAA, 0x02,
9091 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04,
9092 0x01, 0xA6, 0xB4, 0x02,
9093 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
9094 0x80, 0x63, 0x00, 0x43,
9095 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23,
9096 0x04, 0x61, 0x84, 0x01,
9097 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F,
9098 0x00, 0x00, 0xEA, 0x82,
9099 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
9100 0x00, 0x33, 0x1F, 0x00,
9101 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98,
9102 0xB6, 0x2D, 0x01, 0xA6,
9103 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6,
9104 0x10, 0x03, 0x03, 0xA6,
9105 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
9106 0x7C, 0x95, 0xEE, 0x82,
9107 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4,
9108 0x04, 0x01, 0x2D, 0xC8,
9109 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01,
9110 0x05, 0x05, 0x86, 0x98,
9111 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
9112 0x3C, 0x04, 0x06, 0xA6,
9113 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88,
9114 0x7C, 0x95, 0x32, 0x83,
9115 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05,
9116 0xEB, 0x04, 0x00, 0x33,
9117 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
9118 0xFF, 0xA2, 0x7A, 0x03,
9119 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01,
9120 0x00, 0xA2, 0x9A, 0x03,
9121 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
9122 0x01, 0xA6, 0x96, 0x03,
9123 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
9124 0xA4, 0x03, 0x00, 0xA6,
9125 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03,
9126 0x07, 0xA6, 0xB2, 0x03,
9127 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88,
9128 0xA8, 0x98, 0x80, 0x42,
9129 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
9130 0xC0, 0x83, 0x00, 0x33,
9131 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
9132 0xA0, 0x01, 0x12, 0x23,
9133 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B,
9134 0x80, 0x67, 0x05, 0x23,
9135 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
9136 0x06, 0xA6, 0x0A, 0x04,
9137 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96,
9138 0xF4, 0x83, 0x20, 0x84,
9139 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
9140 0x83, 0x03, 0x80, 0x63,
9141 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
9142 0x38, 0x04, 0x00, 0x33,
9143 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84,
9144 0x1D, 0x01, 0x06, 0xCC,
9145 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62,
9146 0xA2, 0x0D, 0x80, 0x63,
9147 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
9148 0x80, 0x63, 0xA3, 0x01,
9149 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0,
9150 0x76, 0x04, 0xE0, 0x00,
9151 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00,
9152 0x00, 0x33, 0x1E, 0x00,
9153 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
9154 0x08, 0x23, 0x22, 0xA3,
9155 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3,
9156 0xC4, 0x04, 0x42, 0x23,
9157 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23,
9158 0xF8, 0x88, 0x04, 0x98,
9159 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
9160 0x81, 0x62, 0xE8, 0x81,
9161 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98,
9162 0x00, 0x33, 0x00, 0x81,
9163 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23,
9164 0xF8, 0x88, 0x04, 0x23,
9165 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
9166 0xF4, 0x04, 0x00, 0x33,
9167 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01,
9168 0x04, 0x23, 0xA0, 0x01,
9169 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00,
9170 0x00, 0xA3, 0x22, 0x05,
9171 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
9172 0x46, 0x97, 0xCD, 0x04,
9173 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23,
9174 0x82, 0x01, 0x34, 0x85,
9175 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05,
9176 0x1D, 0x01, 0x04, 0xD6,
9177 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
9178 0x49, 0x00, 0x81, 0x01,
9179 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01,
9180 0x49, 0x04, 0x80, 0x01,
9181 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04,
9182 0x01, 0x23, 0xEA, 0x00,
9183 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
9184 0x07, 0xA4, 0xF8, 0x05,
9185 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00,
9186 0xC2, 0x88, 0x04, 0xA0,
9187 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61,
9188 0x00, 0xA2, 0xA4, 0x05,
9189 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
9190 0x62, 0x97, 0x04, 0x85,
9191 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05,
9192 0xF4, 0x85, 0x03, 0xA0,
9193 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63,
9194 0xCC, 0x86, 0x07, 0xA0,
9195 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
9196 0x80, 0x67, 0x80, 0x63,
9197 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23,
9198 0xF8, 0x88, 0x07, 0x23,
9199 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00,
9200 0x00, 0x63, 0x4A, 0x00,
9201 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
9202 0x07, 0x41, 0x83, 0x03,
9203 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88,
9204 0x1D, 0x01, 0x01, 0xD6,
9205 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00,
9206 0x07, 0xA6, 0x7C, 0x05,
9207 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
9208 0x52, 0x00, 0x06, 0x61,
9209 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41,
9210 0x00, 0x63, 0x1D, 0x01,
9211 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23,
9212 0x07, 0x41, 0x00, 0x63,
9213 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
9214 0xDF, 0x00, 0x06, 0xA6,
9215 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33,
9216 0x00, 0x40, 0xC0, 0x20,
9217 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63,
9218 0x06, 0xA6, 0x94, 0x06,
9219 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
9220 0x40, 0x0E, 0x80, 0x63,
9221 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E,
9222 0x80, 0x63, 0x00, 0x43,
9223 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05,
9224 0x80, 0x67, 0x40, 0x0E,
9225 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
9226 0x07, 0xA6, 0xD6, 0x06,
9227 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00,
9228 0x0A, 0x2B, 0x07, 0xA6,
9229 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2,
9230 0xF4, 0x06, 0xC0, 0x0E,
9231 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
9232 0x81, 0x62, 0x04, 0x01,
9233 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
9234 0x8C, 0x06, 0x00, 0x33,
9235 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03,
9236 0x80, 0x63, 0x06, 0xA6,
9237 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
9238 0x00, 0x00, 0x80, 0x67,
9239 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05,
9240 0xBF, 0x23, 0x04, 0x61,
9241 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00,
9242 0x00, 0x01, 0xF2, 0x00,
9243 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
9244 0x80, 0x05, 0x81, 0x05,
9245 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00,
9246 0x70, 0x00, 0x81, 0x01,
9247 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04,
9248 0x70, 0x00, 0x80, 0x01,
9249 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
9250 0xF1, 0x00, 0x70, 0x00,
9251 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01,
9252 0x71, 0x04, 0x70, 0x00,
9253 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05,
9254 0xA3, 0x01, 0xA2, 0x01,
9255 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
9256 0xC4, 0x07, 0x00, 0x33,
9257 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8,
9258 0x48, 0x00, 0xB0, 0x01,
9259 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43,
9260 0x00, 0xA2, 0xE4, 0x07,
9261 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
9262 0x05, 0x05, 0x00, 0x63,
9263 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43,
9264 0x76, 0x08, 0x80, 0x02,
9265 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
9266 0x00, 0x02, 0x00, 0xA0,
9267 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
9268 0x00, 0x63, 0xF3, 0x04,
9269 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40,
9270 0x00, 0xA2, 0x44, 0x08,
9271 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1,
9272 0x24, 0x08, 0x04, 0x98,
9273 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
9274 0x5A, 0x88, 0x02, 0x01,
9275 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00,
9276 0x00, 0xA3, 0x64, 0x08,
9277 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63,
9278 0x06, 0xA6, 0x76, 0x08,
9279 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
9280 0x00, 0x63, 0x38, 0x2B,
9281 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98,
9282 0x05, 0x05, 0xB2, 0x09,
9283 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63,
9284 0x80, 0x32, 0x80, 0x36,
9285 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
9286 0x40, 0x36, 0x40, 0x3A,
9287 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08,
9288 0x5D, 0x00, 0xFE, 0xC3,
9289 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73,
9290 0xFF, 0xFD, 0x80, 0x73,
9291 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
9292 0xA1, 0x23, 0xA1, 0x01,
9293 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2,
9294 0x80, 0x00, 0x03, 0xC2,
9295 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23,
9296 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009297};
9298
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009299static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
9300static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009301
9302#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009303static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
9304 INQUIRY,
9305 REQUEST_SENSE,
9306 READ_CAPACITY,
9307 READ_TOC,
9308 MODE_SELECT,
9309 MODE_SENSE,
9310 MODE_SELECT_10,
9311 MODE_SENSE_10,
9312 0xFF,
9313 0xFF,
9314 0xFF,
9315 0xFF,
9316 0xFF,
9317 0xFF,
9318 0xFF,
9319 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07009320};
9321
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009322static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009323{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009324 PortAddr iop_base;
9325 ulong last_int_level;
9326 int sta;
9327 int n_q_required;
9328 int disable_syn_offset_one_fix;
9329 int i;
9330 ASC_PADDR addr;
9331 ASC_EXE_CALLBACK asc_exe_callback;
9332 ushort sg_entry_cnt = 0;
9333 ushort sg_entry_cnt_minus_one = 0;
9334 uchar target_ix;
9335 uchar tid_no;
9336 uchar sdtr_data;
9337 uchar extra_bytes;
9338 uchar scsi_cmd;
9339 uchar disable_cmd;
9340 ASC_SG_HEAD *sg_head;
9341 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009342
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009343 iop_base = asc_dvc->iop_base;
9344 sg_head = scsiq->sg_head;
9345 asc_exe_callback = asc_dvc->exe_callback;
9346 if (asc_dvc->err_code != 0)
9347 return (ERR);
9348 if (scsiq == (ASC_SCSI_Q *)0L) {
9349 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
9350 return (ERR);
9351 }
9352 scsiq->q1.q_no = 0;
9353 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
9354 scsiq->q1.extra_bytes = 0;
9355 }
9356 sta = 0;
9357 target_ix = scsiq->q2.target_ix;
9358 tid_no = ASC_TIX_TO_TID(target_ix);
9359 n_q_required = 1;
9360 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
9361 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
9362 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
9363 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9364 AscMsgOutSDTR(asc_dvc,
9365 asc_dvc->
9366 sdtr_period_tbl[(sdtr_data >> 4) &
9367 (uchar)(asc_dvc->
9368 max_sdtr_index -
9369 1)],
9370 (uchar)(sdtr_data & (uchar)
9371 ASC_SYN_MAX_OFFSET));
9372 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
9373 }
9374 }
9375 last_int_level = DvcEnterCritical();
9376 if (asc_dvc->in_critical_cnt != 0) {
9377 DvcLeaveCritical(last_int_level);
9378 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
9379 return (ERR);
9380 }
9381 asc_dvc->in_critical_cnt++;
9382 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
9383 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
9384 asc_dvc->in_critical_cnt--;
9385 DvcLeaveCritical(last_int_level);
9386 return (ERR);
9387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009388#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009389 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
9390 asc_dvc->in_critical_cnt--;
9391 DvcLeaveCritical(last_int_level);
9392 return (ERR);
9393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009394#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009395 if (sg_entry_cnt == 1) {
9396 scsiq->q1.data_addr =
9397 (ADV_PADDR)sg_head->sg_list[0].addr;
9398 scsiq->q1.data_cnt =
9399 (ADV_DCNT)sg_head->sg_list[0].bytes;
9400 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
9401 }
9402 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
9403 }
9404 scsi_cmd = scsiq->cdbptr[0];
9405 disable_syn_offset_one_fix = FALSE;
9406 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
9407 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
9408 if (scsiq->q1.cntl & QC_SG_HEAD) {
9409 data_cnt = 0;
9410 for (i = 0; i < sg_entry_cnt; i++) {
9411 data_cnt +=
9412 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
9413 bytes);
9414 }
9415 } else {
9416 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
9417 }
9418 if (data_cnt != 0UL) {
9419 if (data_cnt < 512UL) {
9420 disable_syn_offset_one_fix = TRUE;
9421 } else {
9422 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
9423 i++) {
9424 disable_cmd =
9425 _syn_offset_one_disable_cmd[i];
9426 if (disable_cmd == 0xFF) {
9427 break;
9428 }
9429 if (scsi_cmd == disable_cmd) {
9430 disable_syn_offset_one_fix =
9431 TRUE;
9432 break;
9433 }
9434 }
9435 }
9436 }
9437 }
9438 if (disable_syn_offset_one_fix) {
9439 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
9440 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
9441 ASC_TAG_FLAG_DISABLE_DISCONNECT);
9442 } else {
9443 scsiq->q2.tag_code &= 0x27;
9444 }
9445 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
9446 if (asc_dvc->bug_fix_cntl) {
9447 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
9448 if ((scsi_cmd == READ_6) ||
9449 (scsi_cmd == READ_10)) {
9450 addr =
9451 (ADV_PADDR)le32_to_cpu(sg_head->
9452 sg_list
9453 [sg_entry_cnt_minus_one].
9454 addr) +
9455 (ADV_DCNT)le32_to_cpu(sg_head->
9456 sg_list
9457 [sg_entry_cnt_minus_one].
9458 bytes);
9459 extra_bytes =
9460 (uchar)((ushort)addr & 0x0003);
9461 if ((extra_bytes != 0)
9462 &&
9463 ((scsiq->q2.
9464 tag_code &
9465 ASC_TAG_FLAG_EXTRA_BYTES)
9466 == 0)) {
9467 scsiq->q2.tag_code |=
9468 ASC_TAG_FLAG_EXTRA_BYTES;
9469 scsiq->q1.extra_bytes =
9470 extra_bytes;
9471 data_cnt =
9472 le32_to_cpu(sg_head->
9473 sg_list
9474 [sg_entry_cnt_minus_one].
9475 bytes);
9476 data_cnt -=
9477 (ASC_DCNT) extra_bytes;
9478 sg_head->
9479 sg_list
9480 [sg_entry_cnt_minus_one].
9481 bytes =
9482 cpu_to_le32(data_cnt);
9483 }
9484 }
9485 }
9486 }
9487 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009488#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009489 /*
9490 * Set the sg_entry_cnt to the maximum possible. The rest of
9491 * the SG elements will be copied when the RISC completes the
9492 * SG elements that fit and halts.
9493 */
9494 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
9495 sg_entry_cnt = ASC_MAX_SG_LIST;
9496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009497#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009498 n_q_required = AscSgListToQueue(sg_entry_cnt);
9499 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
9500 (uint) n_q_required)
9501 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
9502 if ((sta =
9503 AscSendScsiQueue(asc_dvc, scsiq,
9504 n_q_required)) == 1) {
9505 asc_dvc->in_critical_cnt--;
9506 if (asc_exe_callback != 0) {
9507 (*asc_exe_callback) (asc_dvc, scsiq);
9508 }
9509 DvcLeaveCritical(last_int_level);
9510 return (sta);
9511 }
9512 }
9513 } else {
9514 if (asc_dvc->bug_fix_cntl) {
9515 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
9516 if ((scsi_cmd == READ_6) ||
9517 (scsi_cmd == READ_10)) {
9518 addr =
9519 le32_to_cpu(scsiq->q1.data_addr) +
9520 le32_to_cpu(scsiq->q1.data_cnt);
9521 extra_bytes =
9522 (uchar)((ushort)addr & 0x0003);
9523 if ((extra_bytes != 0)
9524 &&
9525 ((scsiq->q2.
9526 tag_code &
9527 ASC_TAG_FLAG_EXTRA_BYTES)
9528 == 0)) {
9529 data_cnt =
9530 le32_to_cpu(scsiq->q1.
9531 data_cnt);
9532 if (((ushort)data_cnt & 0x01FF)
9533 == 0) {
9534 scsiq->q2.tag_code |=
9535 ASC_TAG_FLAG_EXTRA_BYTES;
9536 data_cnt -= (ASC_DCNT)
9537 extra_bytes;
9538 scsiq->q1.data_cnt =
9539 cpu_to_le32
9540 (data_cnt);
9541 scsiq->q1.extra_bytes =
9542 extra_bytes;
9543 }
9544 }
9545 }
9546 }
9547 }
9548 n_q_required = 1;
9549 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
9550 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
9551 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
9552 n_q_required)) == 1) {
9553 asc_dvc->in_critical_cnt--;
9554 if (asc_exe_callback != 0) {
9555 (*asc_exe_callback) (asc_dvc, scsiq);
9556 }
9557 DvcLeaveCritical(last_int_level);
9558 return (sta);
9559 }
9560 }
9561 }
9562 asc_dvc->in_critical_cnt--;
9563 DvcLeaveCritical(last_int_level);
9564 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009565}
9566
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009567static int
9568AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009569{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009570 PortAddr iop_base;
9571 uchar free_q_head;
9572 uchar next_qp;
9573 uchar tid_no;
9574 uchar target_ix;
9575 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009577 iop_base = asc_dvc->iop_base;
9578 target_ix = scsiq->q2.target_ix;
9579 tid_no = ASC_TIX_TO_TID(target_ix);
9580 sta = 0;
9581 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
9582 if (n_q_required > 1) {
9583 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
9584 free_q_head, (uchar)
9585 (n_q_required)))
9586 != (uchar)ASC_QLINK_END) {
9587 asc_dvc->last_q_shortage = 0;
9588 scsiq->sg_head->queue_cnt = n_q_required - 1;
9589 scsiq->q1.q_no = free_q_head;
9590 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
9591 free_q_head)) == 1) {
9592 AscPutVarFreeQHead(iop_base, next_qp);
9593 asc_dvc->cur_total_qng += (uchar)(n_q_required);
9594 asc_dvc->cur_dvc_qng[tid_no]++;
9595 }
9596 return (sta);
9597 }
9598 } else if (n_q_required == 1) {
9599 if ((next_qp = AscAllocFreeQueue(iop_base,
9600 free_q_head)) !=
9601 ASC_QLINK_END) {
9602 scsiq->q1.q_no = free_q_head;
9603 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
9604 free_q_head)) == 1) {
9605 AscPutVarFreeQHead(iop_base, next_qp);
9606 asc_dvc->cur_total_qng++;
9607 asc_dvc->cur_dvc_qng[tid_no]++;
9608 }
9609 return (sta);
9610 }
9611 }
9612 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009613}
9614
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009615static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009616{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009617 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009618
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009619 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
9620 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
9621 n_sg_list_qs++;
9622 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009623}
9624
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009625static uint
9626AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009627{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009628 uint cur_used_qs;
9629 uint cur_free_qs;
9630 ASC_SCSI_BIT_ID_TYPE target_id;
9631 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009632
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009633 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
9634 tid_no = ASC_TIX_TO_TID(target_ix);
9635 if ((asc_dvc->unit_not_ready & target_id) ||
9636 (asc_dvc->queue_full_or_busy & target_id)) {
9637 return (0);
9638 }
9639 if (n_qs == 1) {
9640 cur_used_qs = (uint) asc_dvc->cur_total_qng +
9641 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
9642 } else {
9643 cur_used_qs = (uint) asc_dvc->cur_total_qng +
9644 (uint) ASC_MIN_FREE_Q;
9645 }
9646 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
9647 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
9648 if (asc_dvc->cur_dvc_qng[tid_no] >=
9649 asc_dvc->max_dvc_qng[tid_no]) {
9650 return (0);
9651 }
9652 return (cur_free_qs);
9653 }
9654 if (n_qs > 1) {
9655 if ((n_qs > asc_dvc->last_q_shortage)
9656 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
9657 asc_dvc->last_q_shortage = n_qs;
9658 }
9659 }
9660 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009661}
9662
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009663static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009664{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009665 ushort q_addr;
9666 uchar tid_no;
9667 uchar sdtr_data;
9668 uchar syn_period_ix;
9669 uchar syn_offset;
9670 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009672 iop_base = asc_dvc->iop_base;
9673 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
9674 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
9675 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
9676 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9677 syn_period_ix =
9678 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
9679 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
9680 AscMsgOutSDTR(asc_dvc,
9681 asc_dvc->sdtr_period_tbl[syn_period_ix],
9682 syn_offset);
9683 scsiq->q1.cntl |= QC_MSG_OUT;
9684 }
9685 q_addr = ASC_QNO_TO_QADDR(q_no);
9686 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
9687 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
9688 }
9689 scsiq->q1.status = QS_FREE;
9690 AscMemWordCopyPtrToLram(iop_base,
9691 q_addr + ASC_SCSIQ_CDB_BEG,
9692 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009693
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009694 DvcPutScsiQ(iop_base,
9695 q_addr + ASC_SCSIQ_CPY_BEG,
9696 (uchar *)&scsiq->q1.cntl,
9697 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
9698 AscWriteLramWord(iop_base,
9699 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
9700 (ushort)(((ushort)scsiq->q1.
9701 q_no << 8) | (ushort)QS_READY));
9702 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009703}
9704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009705static int
9706AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009707{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009708 int sta;
9709 int i;
9710 ASC_SG_HEAD *sg_head;
9711 ASC_SG_LIST_Q scsi_sg_q;
9712 ASC_DCNT saved_data_addr;
9713 ASC_DCNT saved_data_cnt;
9714 PortAddr iop_base;
9715 ushort sg_list_dwords;
9716 ushort sg_index;
9717 ushort sg_entry_cnt;
9718 ushort q_addr;
9719 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009721 iop_base = asc_dvc->iop_base;
9722 sg_head = scsiq->sg_head;
9723 saved_data_addr = scsiq->q1.data_addr;
9724 saved_data_cnt = scsiq->q1.data_cnt;
9725 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
9726 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009727#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009728 /*
9729 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
9730 * then not all SG elements will fit in the allocated queues.
9731 * The rest of the SG elements will be copied when the RISC
9732 * completes the SG elements that fit and halts.
9733 */
9734 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
9735 /*
9736 * Set sg_entry_cnt to be the number of SG elements that
9737 * will fit in the allocated SG queues. It is minus 1, because
9738 * the first SG element is handled above. ASC_MAX_SG_LIST is
9739 * already inflated by 1 to account for this. For example it
9740 * may be 50 which is 1 + 7 queues * 7 SG elements.
9741 */
9742 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009744 /*
9745 * Keep track of remaining number of SG elements that will
9746 * need to be handled from a_isr.c.
9747 */
9748 scsiq->remain_sg_entry_cnt =
9749 sg_head->entry_cnt - ASC_MAX_SG_LIST;
9750 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009751#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009752 /*
9753 * Set sg_entry_cnt to be the number of SG elements that
9754 * will fit in the allocated SG queues. It is minus 1, because
9755 * the first SG element is handled above.
9756 */
9757 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009758#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009760#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009761 if (sg_entry_cnt != 0) {
9762 scsiq->q1.cntl |= QC_SG_HEAD;
9763 q_addr = ASC_QNO_TO_QADDR(q_no);
9764 sg_index = 1;
9765 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
9766 scsi_sg_q.sg_head_qp = q_no;
9767 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9768 for (i = 0; i < sg_head->queue_cnt; i++) {
9769 scsi_sg_q.seq_no = i + 1;
9770 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9771 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9772 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9773 if (i == 0) {
9774 scsi_sg_q.sg_list_cnt =
9775 ASC_SG_LIST_PER_Q;
9776 scsi_sg_q.sg_cur_list_cnt =
9777 ASC_SG_LIST_PER_Q;
9778 } else {
9779 scsi_sg_q.sg_list_cnt =
9780 ASC_SG_LIST_PER_Q - 1;
9781 scsi_sg_q.sg_cur_list_cnt =
9782 ASC_SG_LIST_PER_Q - 1;
9783 }
9784 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009785#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009786 /*
9787 * This is the last SG queue in the list of
9788 * allocated SG queues. If there are more
9789 * SG elements than will fit in the allocated
9790 * queues, then set the QCSG_SG_XFER_MORE flag.
9791 */
9792 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
9793 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9794 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009795#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009796 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009797#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009799#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009800 sg_list_dwords = sg_entry_cnt << 1;
9801 if (i == 0) {
9802 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
9803 scsi_sg_q.sg_cur_list_cnt =
9804 sg_entry_cnt;
9805 } else {
9806 scsi_sg_q.sg_list_cnt =
9807 sg_entry_cnt - 1;
9808 scsi_sg_q.sg_cur_list_cnt =
9809 sg_entry_cnt - 1;
9810 }
9811 sg_entry_cnt = 0;
9812 }
9813 next_qp = AscReadLramByte(iop_base,
9814 (ushort)(q_addr +
9815 ASC_SCSIQ_B_FWD));
9816 scsi_sg_q.q_no = next_qp;
9817 q_addr = ASC_QNO_TO_QADDR(next_qp);
9818 AscMemWordCopyPtrToLram(iop_base,
9819 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9820 (uchar *)&scsi_sg_q,
9821 sizeof(ASC_SG_LIST_Q) >> 1);
9822 AscMemDWordCopyPtrToLram(iop_base,
9823 q_addr + ASC_SGQ_LIST_BEG,
9824 (uchar *)&sg_head->
9825 sg_list[sg_index],
9826 sg_list_dwords);
9827 sg_index += ASC_SG_LIST_PER_Q;
9828 scsiq->next_sg_index = sg_index;
9829 }
9830 } else {
9831 scsiq->q1.cntl &= ~QC_SG_HEAD;
9832 }
9833 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
9834 scsiq->q1.data_addr = saved_data_addr;
9835 scsiq->q1.data_cnt = saved_data_cnt;
9836 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009837}
9838
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009839static int
9840AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009841{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009842 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009844 if (AscHostReqRiscHalt(iop_base)) {
9845 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9846 AscStartChip(iop_base);
9847 return (sta);
9848 }
9849 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009850}
9851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009852static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009853{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009854 ASC_SCSI_BIT_ID_TYPE org_id;
9855 int i;
9856 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009858 AscSetBank(iop_base, 1);
9859 org_id = AscReadChipDvcID(iop_base);
9860 for (i = 0; i <= ASC_MAX_TID; i++) {
9861 if (org_id == (0x01 << i))
9862 break;
9863 }
9864 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
9865 AscWriteChipDvcID(iop_base, id);
9866 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
9867 AscSetBank(iop_base, 0);
9868 AscSetChipSyn(iop_base, sdtr_data);
9869 if (AscGetChipSyn(iop_base) != sdtr_data) {
9870 sta = FALSE;
9871 }
9872 } else {
9873 sta = FALSE;
9874 }
9875 AscSetBank(iop_base, 1);
9876 AscWriteChipDvcID(iop_base, org_id);
9877 AscSetBank(iop_base, 0);
9878 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009879}
9880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009881static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009882{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009883 uchar i;
9884 ushort s_addr;
9885 PortAddr iop_base;
9886 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009888 iop_base = asc_dvc->iop_base;
9889 warn_code = 0;
9890 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
9891 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
9892 64) >> 1)
9893 );
9894 i = ASC_MIN_ACTIVE_QNO;
9895 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
9896 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
9897 (uchar)(i + 1));
9898 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
9899 (uchar)(asc_dvc->max_total_qng));
9900 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
9901 (uchar)i);
9902 i++;
9903 s_addr += ASC_QBLK_SIZE;
9904 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
9905 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
9906 (uchar)(i + 1));
9907 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
9908 (uchar)(i - 1));
9909 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
9910 (uchar)i);
9911 }
9912 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
9913 (uchar)ASC_QLINK_END);
9914 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
9915 (uchar)(asc_dvc->max_total_qng - 1));
9916 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
9917 (uchar)asc_dvc->max_total_qng);
9918 i++;
9919 s_addr += ASC_QBLK_SIZE;
9920 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
9921 i++, s_addr += ASC_QBLK_SIZE) {
9922 AscWriteLramByte(iop_base,
9923 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
9924 AscWriteLramByte(iop_base,
9925 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
9926 AscWriteLramByte(iop_base,
9927 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
9928 }
9929 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009930}
9931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009932static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009933{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009934 PortAddr iop_base;
9935 int i;
9936 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009938 iop_base = asc_dvc->iop_base;
9939 AscPutRiscVarFreeQHead(iop_base, 1);
9940 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
9941 AscPutVarFreeQHead(iop_base, 1);
9942 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
9943 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
9944 (uchar)((int)asc_dvc->max_total_qng + 1));
9945 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
9946 (uchar)((int)asc_dvc->max_total_qng + 2));
9947 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
9948 asc_dvc->max_total_qng);
9949 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
9950 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9951 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
9952 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
9953 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
9954 AscPutQDoneInProgress(iop_base, 0);
9955 lram_addr = ASC_QADR_BEG;
9956 for (i = 0; i < 32; i++, lram_addr += 2) {
9957 AscWriteLramWord(iop_base, lram_addr, 0);
9958 }
9959 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009960}
9961
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009962static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009963{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009964 if (asc_dvc->err_code == 0) {
9965 asc_dvc->err_code = err_code;
9966 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
9967 err_code);
9968 }
9969 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009970}
9971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009972static uchar
9973AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009974{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009975 EXT_MSG sdtr_buf;
9976 uchar sdtr_period_index;
9977 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009978
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009979 iop_base = asc_dvc->iop_base;
9980 sdtr_buf.msg_type = MS_EXTEND;
9981 sdtr_buf.msg_len = MS_SDTR_LEN;
9982 sdtr_buf.msg_req = MS_SDTR_CODE;
9983 sdtr_buf.xfer_period = sdtr_period;
9984 sdtr_offset &= ASC_SYN_MAX_OFFSET;
9985 sdtr_buf.req_ack_offset = sdtr_offset;
9986 if ((sdtr_period_index =
9987 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
9988 asc_dvc->max_sdtr_index) {
9989 AscMemWordCopyPtrToLram(iop_base,
9990 ASCV_MSGOUT_BEG,
9991 (uchar *)&sdtr_buf,
9992 sizeof(EXT_MSG) >> 1);
9993 return ((sdtr_period_index << 4) | sdtr_offset);
9994 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009996 sdtr_buf.req_ack_offset = 0;
9997 AscMemWordCopyPtrToLram(iop_base,
9998 ASCV_MSGOUT_BEG,
9999 (uchar *)&sdtr_buf,
10000 sizeof(EXT_MSG) >> 1);
10001 return (0);
10002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010003}
10004
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010005static uchar
10006AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010007{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010008 uchar byte;
10009 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010010
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010011 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
10012 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
10013 ) {
10014 return (0xFF);
10015 }
10016 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
10017 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010018}
10019
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010020static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010021{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010022 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
10023 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
10024 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010025}
10026
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010027static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010028{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010029 uchar *period_table;
10030 int max_index;
10031 int min_index;
10032 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010033
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010034 period_table = asc_dvc->sdtr_period_tbl;
10035 max_index = (int)asc_dvc->max_sdtr_index;
10036 min_index = (int)asc_dvc->host_init_sdtr_index;
10037 if ((syn_time <= period_table[max_index])) {
10038 for (i = min_index; i < (max_index - 1); i++) {
10039 if (syn_time <= period_table[i]) {
10040 return ((uchar)i);
10041 }
10042 }
10043 return ((uchar)max_index);
10044 } else {
10045 return ((uchar)(max_index + 1));
10046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010047}
10048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010049static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010050{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010051 ushort q_addr;
10052 uchar next_qp;
10053 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010054
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010055 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10056 q_status = (uchar)AscReadLramByte(iop_base,
10057 (ushort)(q_addr +
10058 ASC_SCSIQ_B_STATUS));
10059 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10060 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
10061 return (next_qp);
10062 }
10063 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010064}
10065
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010066static uchar
10067AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010068{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010069 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010071 for (i = 0; i < n_free_q; i++) {
10072 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
10073 == ASC_QLINK_END) {
10074 return (ASC_QLINK_END);
10075 }
10076 }
10077 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010078}
10079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010080static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010081{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010082 int count = 0;
10083 int sta = 0;
10084 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010085
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010086 if (AscIsChipHalted(iop_base))
10087 return (1);
10088 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
10089 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
10090 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
10091 do {
10092 if (AscIsChipHalted(iop_base)) {
10093 sta = 1;
10094 break;
10095 }
10096 DvcSleepMilliSecond(100);
10097 } while (count++ < 20);
10098 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
10099 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010100}
10101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010102static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010103{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010104 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010105
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010106 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
10107 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
10108 ASC_STOP_REQ_RISC_STOP);
10109 do {
10110 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
10111 ASC_STOP_ACK_RISC_STOP) {
10112 return (1);
10113 }
10114 DvcSleepMilliSecond(100);
10115 } while (count++ < 20);
10116 }
10117 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010118}
10119
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010120static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010121{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010122 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010123}
10124
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010125static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010126{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010127 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010128}
10129
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010130static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010131{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010132 AscSetChipControl(iop_base, 0);
10133 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
10134 return (0);
10135 }
10136 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010137}
10138
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010139static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010140{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010141 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010142
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010143 cc_val =
10144 AscGetChipControl(iop_base) &
10145 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
10146 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
10147 AscSetChipIH(iop_base, INS_HALT);
10148 AscSetChipIH(iop_base, INS_RFLAG_WTM);
10149 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
10150 return (0);
10151 }
10152 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010153}
10154
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010155static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010156{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010157 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
10158 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
10159 return (1);
10160 }
10161 }
10162 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010163}
10164
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010165static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010166{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010167 AscSetBank(iop_base, 1);
10168 AscWriteChipIH(iop_base, ins_code);
10169 AscSetBank(iop_base, 0);
10170 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010171}
10172
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010173static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010174{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010175 uchar host_flag;
10176 uchar risc_flag;
10177 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010178
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010179 loop = 0;
10180 do {
10181 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
10182 if (loop++ > 0x7FFF) {
10183 break;
10184 }
10185 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
10186 host_flag =
10187 AscReadLramByte(iop_base,
10188 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
10189 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
10190 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
10191 AscSetChipStatus(iop_base, CIW_INT_ACK);
10192 loop = 0;
10193 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
10194 AscSetChipStatus(iop_base, CIW_INT_ACK);
10195 if (loop++ > 3) {
10196 break;
10197 }
10198 }
10199 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
10200 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010201}
10202
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010203static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010204{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010205 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010206
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010207 cfg = AscGetChipCfgLsw(iop_base);
10208 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
10209 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010210}
10211
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010212static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010213{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010214 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010215
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010216 cfg = AscGetChipCfgLsw(iop_base);
10217 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
10218 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010219}
10220
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010221static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010222{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010223 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010224
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010225 val = AscGetChipControl(iop_base) &
10226 (~
10227 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
10228 CC_CHIP_RESET));
10229 if (bank == 1) {
10230 val |= CC_BANK_ONE;
10231 } else if (bank == 2) {
10232 val |= CC_DIAG | CC_BANK_ONE;
10233 } else {
10234 val &= ~CC_BANK_ONE;
10235 }
10236 AscSetChipControl(iop_base, val);
10237 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010238}
10239
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010240static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010241{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010242 PortAddr iop_base;
10243 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010244
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010245 iop_base = asc_dvc->iop_base;
10246 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
10247 && (i-- > 0)) {
10248 DvcSleepMilliSecond(100);
10249 }
10250 AscStopChip(iop_base);
10251 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
10252 DvcDelayNanoSecond(asc_dvc, 60000);
10253 AscSetChipIH(iop_base, INS_RFLAG_WTM);
10254 AscSetChipIH(iop_base, INS_HALT);
10255 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
10256 AscSetChipControl(iop_base, CC_HALT);
10257 DvcSleepMilliSecond(200);
10258 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
10259 AscSetChipStatus(iop_base, 0);
10260 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010261}
10262
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010263static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010264{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010265 if (bus_type & ASC_IS_ISA)
10266 return (ASC_MAX_ISA_DMA_COUNT);
10267 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
10268 return (ASC_MAX_VL_DMA_COUNT);
10269 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010270}
10271
10272#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010273static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010274{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010275 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010276
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010277 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
10278 if (channel == 0x03)
10279 return (0);
10280 else if (channel == 0x00)
10281 return (7);
10282 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010283}
10284
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010285static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010286{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010287 ushort cfg_lsw;
10288 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010289
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010290 if ((dma_channel >= 5) && (dma_channel <= 7)) {
10291 if (dma_channel == 7)
10292 value = 0x00;
10293 else
10294 value = dma_channel - 4;
10295 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
10296 cfg_lsw |= value;
10297 AscSetChipCfgLsw(iop_base, cfg_lsw);
10298 return (AscGetIsaDmaChannel(iop_base));
10299 }
10300 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010301}
10302
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010303static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010304{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010305 speed_value &= 0x07;
10306 AscSetBank(iop_base, 1);
10307 AscWriteChipDmaSpeed(iop_base, speed_value);
10308 AscSetBank(iop_base, 0);
10309 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010310}
10311
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010312static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010313{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010314 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010315
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010316 AscSetBank(iop_base, 1);
10317 speed_value = AscReadChipDmaSpeed(iop_base);
10318 speed_value &= 0x07;
10319 AscSetBank(iop_base, 0);
10320 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010321}
10322#endif /* CONFIG_ISA */
10323
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010324static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010325AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010326{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010327 uchar lsb, msb;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010328
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010329 lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
10330 msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
10331 return ((ushort)((msb << 8) | lsb));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010332}
10333
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010334static ushort __devinit AscInitGetConfig(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010335{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010336 ushort warn_code;
10337 PortAddr iop_base;
10338 ushort PCIDeviceID;
10339 ushort PCIVendorID;
10340 uchar PCIRevisionID;
10341 uchar prevCmdRegBits;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010342
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010343 warn_code = 0;
10344 iop_base = asc_dvc->iop_base;
10345 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
10346 if (asc_dvc->err_code != 0) {
10347 return (UW_ERR);
10348 }
10349 if (asc_dvc->bus_type == ASC_IS_PCI) {
10350 PCIVendorID = AscReadPCIConfigWord(asc_dvc,
10351 AscPCIConfigVendorIDRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010352
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010353 PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
10354 AscPCIConfigDeviceIDRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010355
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010356 PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
10357 AscPCIConfigRevisionIDRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010358
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010359 if (PCIVendorID != PCI_VENDOR_ID_ASP) {
10360 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
10361 }
10362 prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
10363 AscPCIConfigCommandRegister);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010364
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010365 if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
10366 AscPCICmdRegBits_IOMemBusMaster) {
10367 DvcWritePCIConfigByte(asc_dvc,
10368 AscPCIConfigCommandRegister,
10369 (prevCmdRegBits |
10370 AscPCICmdRegBits_IOMemBusMaster));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010371
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010372 if ((DvcReadPCIConfigByte(asc_dvc,
10373 AscPCIConfigCommandRegister)
10374 & AscPCICmdRegBits_IOMemBusMaster)
10375 != AscPCICmdRegBits_IOMemBusMaster) {
10376 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
10377 }
10378 }
10379 if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) ||
10380 (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) {
10381 DvcWritePCIConfigByte(asc_dvc,
10382 AscPCIConfigLatencyTimer, 0x00);
10383 if (DvcReadPCIConfigByte
10384 (asc_dvc, AscPCIConfigLatencyTimer)
10385 != 0x00) {
10386 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
10387 }
10388 } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) {
10389 if (DvcReadPCIConfigByte(asc_dvc,
10390 AscPCIConfigLatencyTimer) <
10391 0x20) {
10392 DvcWritePCIConfigByte(asc_dvc,
10393 AscPCIConfigLatencyTimer,
10394 0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010396 if (DvcReadPCIConfigByte(asc_dvc,
10397 AscPCIConfigLatencyTimer)
10398 < 0x20) {
10399 warn_code |=
10400 ASC_WARN_SET_PCI_CONFIG_SPACE;
10401 }
10402 }
10403 }
10404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010405
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010406 if (AscFindSignature(iop_base)) {
10407 warn_code |= AscInitAscDvcVar(asc_dvc);
10408 warn_code |= AscInitFromEEP(asc_dvc);
10409 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
10410 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
10411 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
10412 }
10413 } else {
10414 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10415 }
10416 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010417}
10418
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010419static ushort __devinit AscInitSetConfig(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010420{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010421 ushort warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010422
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010423 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
10424 if (asc_dvc->err_code != 0)
10425 return (UW_ERR);
10426 if (AscFindSignature(asc_dvc->iop_base)) {
10427 warn_code |= AscInitFromAscDvcVar(asc_dvc);
10428 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
10429 } else {
10430 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10431 }
10432 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010433}
10434
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010435static ushort __devinit AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010436{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010437 PortAddr iop_base;
10438 ushort cfg_msw;
10439 ushort warn_code;
10440 ushort pci_device_id = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010442 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010443#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010444 if (asc_dvc->cfg->dev)
10445 pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010446#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010447 warn_code = 0;
10448 cfg_msw = AscGetChipCfgMsw(iop_base);
10449 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
10450 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
10451 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
10452 AscSetChipCfgMsw(iop_base, cfg_msw);
10453 }
10454 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
10455 asc_dvc->cfg->cmd_qng_enabled) {
10456 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
10457 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
10458 }
10459 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
10460 warn_code |= ASC_WARN_AUTO_CONFIG;
10461 }
10462 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
10463 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
10464 != asc_dvc->irq_no) {
10465 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
10466 }
10467 }
10468 if (asc_dvc->bus_type & ASC_IS_PCI) {
10469 cfg_msw &= 0xFFC0;
10470 AscSetChipCfgMsw(iop_base, cfg_msw);
10471 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
10472 } else {
10473 if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) ||
10474 (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) {
10475 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
10476 asc_dvc->bug_fix_cntl |=
10477 ASC_BUG_FIX_ASYN_USE_SYN;
10478 }
10479 }
10480 } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
10481 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
10482 == ASC_CHIP_VER_ASYN_BUG) {
10483 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
10484 }
10485 }
10486 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
10487 asc_dvc->cfg->chip_scsi_id) {
10488 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
10489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010490#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010491 if (asc_dvc->bus_type & ASC_IS_ISA) {
10492 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
10493 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
10494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010495#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010496 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010497}
10498
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010499static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010500{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010501 ushort warn_code;
10502 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010503
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010504 iop_base = asc_dvc->iop_base;
10505 warn_code = 0;
10506 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
10507 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
10508 AscResetChipAndScsiBus(asc_dvc);
10509 DvcSleepMilliSecond((ASC_DCNT)
10510 ((ushort)asc_dvc->scsi_reset_wait * 1000));
10511 }
10512 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
10513 if (asc_dvc->err_code != 0)
10514 return (UW_ERR);
10515 if (!AscFindSignature(asc_dvc->iop_base)) {
10516 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
10517 return (warn_code);
10518 }
10519 AscDisableInterrupt(iop_base);
10520 warn_code |= AscInitLram(asc_dvc);
10521 if (asc_dvc->err_code != 0)
10522 return (UW_ERR);
10523 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
10524 (ulong)_asc_mcode_chksum);
10525 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
10526 _asc_mcode_size) != _asc_mcode_chksum) {
10527 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
10528 return (warn_code);
10529 }
10530 warn_code |= AscInitMicroCodeVar(asc_dvc);
10531 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
10532 AscEnableInterrupt(iop_base);
10533 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010534}
10535
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010536static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010537{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010538 int i;
10539 PortAddr iop_base;
10540 ushort warn_code;
10541 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010542
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010543 iop_base = asc_dvc->iop_base;
10544 warn_code = 0;
10545 asc_dvc->err_code = 0;
10546 if ((asc_dvc->bus_type &
10547 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
10548 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
10549 }
10550 AscSetChipControl(iop_base, CC_HALT);
10551 AscSetChipStatus(iop_base, 0);
10552 asc_dvc->bug_fix_cntl = 0;
10553 asc_dvc->pci_fix_asyn_xfer = 0;
10554 asc_dvc->pci_fix_asyn_xfer_always = 0;
10555 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
10556 asc_dvc->sdtr_done = 0;
10557 asc_dvc->cur_total_qng = 0;
10558 asc_dvc->is_in_int = 0;
10559 asc_dvc->in_critical_cnt = 0;
10560 asc_dvc->last_q_shortage = 0;
10561 asc_dvc->use_tagged_qng = 0;
10562 asc_dvc->no_scam = 0;
10563 asc_dvc->unit_not_ready = 0;
10564 asc_dvc->queue_full_or_busy = 0;
10565 asc_dvc->redo_scam = 0;
10566 asc_dvc->res2 = 0;
10567 asc_dvc->host_init_sdtr_index = 0;
10568 asc_dvc->cfg->can_tagged_qng = 0;
10569 asc_dvc->cfg->cmd_qng_enabled = 0;
10570 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
10571 asc_dvc->init_sdtr = 0;
10572 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
10573 asc_dvc->scsi_reset_wait = 3;
10574 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
10575 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
10576 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
10577 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
10578 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
10579 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
10580 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
10581 ASC_LIB_VERSION_MINOR;
10582 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
10583 asc_dvc->cfg->chip_version = chip_version;
10584 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
10585 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
10586 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
10587 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
10588 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
10589 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
10590 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
10591 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
10592 asc_dvc->max_sdtr_index = 7;
10593 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
10594 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
10595 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
10596 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
10597 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
10598 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
10599 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
10600 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
10601 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
10602 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
10603 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
10604 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
10605 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
10606 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
10607 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
10608 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
10609 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
10610 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
10611 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
10612 asc_dvc->max_sdtr_index = 15;
10613 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
10614 AscSetExtraControl(iop_base,
10615 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
10616 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
10617 AscSetExtraControl(iop_base,
10618 (SEC_ACTIVE_NEGATE |
10619 SEC_ENABLE_FILTER));
10620 }
10621 }
10622 if (asc_dvc->bus_type == ASC_IS_PCI) {
10623 AscSetExtraControl(iop_base,
10624 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
10625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010626
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010627 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
10628 if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
10629 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
10630 asc_dvc->bus_type = ASC_IS_ISAPNP;
10631 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010632#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010633 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
10634 asc_dvc->cfg->isa_dma_channel =
10635 (uchar)AscGetIsaDmaChannel(iop_base);
10636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010637#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010638 for (i = 0; i <= ASC_MAX_TID; i++) {
10639 asc_dvc->cur_dvc_qng[i] = 0;
10640 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
10641 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
10642 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
10643 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
10644 }
10645 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010646}
10647
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010648static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010649{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010650 ASCEEP_CONFIG eep_config_buf;
10651 ASCEEP_CONFIG *eep_config;
10652 PortAddr iop_base;
10653 ushort chksum;
10654 ushort warn_code;
10655 ushort cfg_msw, cfg_lsw;
10656 int i;
10657 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010658
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010659 iop_base = asc_dvc->iop_base;
10660 warn_code = 0;
10661 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
10662 AscStopQueueExe(iop_base);
10663 if ((AscStopChip(iop_base) == FALSE) ||
10664 (AscGetChipScsiCtrl(iop_base) != 0)) {
10665 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
10666 AscResetChipAndScsiBus(asc_dvc);
10667 DvcSleepMilliSecond((ASC_DCNT)
10668 ((ushort)asc_dvc->scsi_reset_wait * 1000));
10669 }
10670 if (AscIsChipHalted(iop_base) == FALSE) {
10671 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
10672 return (warn_code);
10673 }
10674 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
10675 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
10676 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
10677 return (warn_code);
10678 }
10679 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
10680 cfg_msw = AscGetChipCfgMsw(iop_base);
10681 cfg_lsw = AscGetChipCfgLsw(iop_base);
10682 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
10683 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
10684 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
10685 AscSetChipCfgMsw(iop_base, cfg_msw);
10686 }
10687 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
10688 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
10689 if (chksum == 0) {
10690 chksum = 0xaa55;
10691 }
10692 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
10693 warn_code |= ASC_WARN_AUTO_CONFIG;
10694 if (asc_dvc->cfg->chip_version == 3) {
10695 if (eep_config->cfg_lsw != cfg_lsw) {
10696 warn_code |= ASC_WARN_EEPROM_RECOVER;
10697 eep_config->cfg_lsw =
10698 AscGetChipCfgLsw(iop_base);
10699 }
10700 if (eep_config->cfg_msw != cfg_msw) {
10701 warn_code |= ASC_WARN_EEPROM_RECOVER;
10702 eep_config->cfg_msw =
10703 AscGetChipCfgMsw(iop_base);
10704 }
10705 }
10706 }
10707 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
10708 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
10709 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
10710 eep_config->chksum);
10711 if (chksum != eep_config->chksum) {
10712 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
10713 ASC_CHIP_VER_PCI_ULTRA_3050) {
10714 ASC_DBG(1,
10715 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
10716 eep_config->init_sdtr = 0xFF;
10717 eep_config->disc_enable = 0xFF;
10718 eep_config->start_motor = 0xFF;
10719 eep_config->use_cmd_qng = 0;
10720 eep_config->max_total_qng = 0xF0;
10721 eep_config->max_tag_qng = 0x20;
10722 eep_config->cntl = 0xBFFF;
10723 ASC_EEP_SET_CHIP_ID(eep_config, 7);
10724 eep_config->no_scam = 0;
10725 eep_config->adapter_info[0] = 0;
10726 eep_config->adapter_info[1] = 0;
10727 eep_config->adapter_info[2] = 0;
10728 eep_config->adapter_info[3] = 0;
10729 eep_config->adapter_info[4] = 0;
10730 /* Indicate EEPROM-less board. */
10731 eep_config->adapter_info[5] = 0xBB;
10732 } else {
10733 ASC_PRINT
10734 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
10735 write_eep = 1;
10736 warn_code |= ASC_WARN_EEPROM_CHKSUM;
10737 }
10738 }
10739 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
10740 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
10741 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
10742 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
10743 asc_dvc->start_motor = eep_config->start_motor;
10744 asc_dvc->dvc_cntl = eep_config->cntl;
10745 asc_dvc->no_scam = eep_config->no_scam;
10746 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
10747 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
10748 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
10749 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
10750 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
10751 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
10752 if (!AscTestExternalLram(asc_dvc)) {
10753 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
10754 ASC_IS_PCI_ULTRA)) {
10755 eep_config->max_total_qng =
10756 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
10757 eep_config->max_tag_qng =
10758 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
10759 } else {
10760 eep_config->cfg_msw |= 0x0800;
10761 cfg_msw |= 0x0800;
10762 AscSetChipCfgMsw(iop_base, cfg_msw);
10763 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
10764 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
10765 }
10766 } else {
10767 }
10768 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
10769 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
10770 }
10771 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
10772 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
10773 }
10774 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
10775 eep_config->max_tag_qng = eep_config->max_total_qng;
10776 }
10777 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
10778 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
10779 }
10780 asc_dvc->max_total_qng = eep_config->max_total_qng;
10781 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
10782 eep_config->use_cmd_qng) {
10783 eep_config->disc_enable = eep_config->use_cmd_qng;
10784 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
10785 }
10786 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
10787 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
10788 }
10789 ASC_EEP_SET_CHIP_ID(eep_config,
10790 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
10791 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
10792 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
10793 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
10794 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
10795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010796
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010797 for (i = 0; i <= ASC_MAX_TID; i++) {
10798 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
10799 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
10800 asc_dvc->cfg->sdtr_period_offset[i] =
10801 (uchar)(ASC_DEF_SDTR_OFFSET |
10802 (asc_dvc->host_init_sdtr_index << 4));
10803 }
10804 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
10805 if (write_eep) {
10806 if ((i =
10807 AscSetEEPConfig(iop_base, eep_config,
10808 asc_dvc->bus_type)) != 0) {
10809 ASC_PRINT1
10810 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
10811 i);
10812 } else {
10813 ASC_PRINT
10814 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
10815 }
10816 }
10817 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010818}
10819
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010820static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010821{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010822 int i;
10823 ushort warn_code;
10824 PortAddr iop_base;
10825 ASC_PADDR phy_addr;
10826 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010827
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010828 iop_base = asc_dvc->iop_base;
10829 warn_code = 0;
10830 for (i = 0; i <= ASC_MAX_TID; i++) {
10831 AscPutMCodeInitSDTRAtID(iop_base, i,
10832 asc_dvc->cfg->sdtr_period_offset[i]
10833 );
10834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010835
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010836 AscInitQLinkVar(asc_dvc);
10837 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
10838 asc_dvc->cfg->disc_enable);
10839 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
10840 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070010841
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010842 /* Align overrun buffer on an 8 byte boundary. */
10843 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
10844 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
10845 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
10846 (uchar *)&phy_addr, 1);
10847 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
10848 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
10849 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010850
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010851 asc_dvc->cfg->mcode_date =
10852 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
10853 asc_dvc->cfg->mcode_version =
10854 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010855
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010856 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
10857 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
10858 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
10859 return (warn_code);
10860 }
10861 if (AscStartChip(iop_base) != 1) {
10862 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
10863 return (warn_code);
10864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010865
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010866 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010867}
10868
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010869static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010870{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010871 PortAddr iop_base;
10872 ushort q_addr;
10873 ushort saved_word;
10874 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010875
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010876 iop_base = asc_dvc->iop_base;
10877 sta = 0;
10878 q_addr = ASC_QNO_TO_QADDR(241);
10879 saved_word = AscReadLramWord(iop_base, q_addr);
10880 AscSetChipLramAddr(iop_base, q_addr);
10881 AscSetChipLramData(iop_base, 0x55AA);
10882 DvcSleepMilliSecond(10);
10883 AscSetChipLramAddr(iop_base, q_addr);
10884 if (AscGetChipLramData(iop_base) == 0x55AA) {
10885 sta = 1;
10886 AscWriteLramWord(iop_base, q_addr, saved_word);
10887 }
10888 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010889}
10890
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010891static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010892{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010893 uchar read_back;
10894 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010895
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010896 retry = 0;
10897 while (TRUE) {
10898 AscSetChipEEPCmd(iop_base, cmd_reg);
10899 DvcSleepMilliSecond(1);
10900 read_back = AscGetChipEEPCmd(iop_base);
10901 if (read_back == cmd_reg) {
10902 return (1);
10903 }
10904 if (retry++ > ASC_EEP_MAX_RETRY) {
10905 return (0);
10906 }
10907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010908}
10909
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010910static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010911{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010912 ushort read_back;
10913 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010914
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010915 retry = 0;
10916 while (TRUE) {
10917 AscSetChipEEPData(iop_base, data_reg);
10918 DvcSleepMilliSecond(1);
10919 read_back = AscGetChipEEPData(iop_base);
10920 if (read_back == data_reg) {
10921 return (1);
10922 }
10923 if (retry++ > ASC_EEP_MAX_RETRY) {
10924 return (0);
10925 }
10926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010927}
10928
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010929static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010930{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010931 DvcSleepMilliSecond(1);
10932 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010933}
10934
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010935static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010936{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010937 DvcSleepMilliSecond(20);
10938 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010939}
10940
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010941static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010942{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010943 ushort read_wval;
10944 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010945
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010946 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
10947 AscWaitEEPRead();
10948 cmd_reg = addr | ASC_EEP_CMD_READ;
10949 AscWriteEEPCmdReg(iop_base, cmd_reg);
10950 AscWaitEEPRead();
10951 read_wval = AscGetChipEEPData(iop_base);
10952 AscWaitEEPRead();
10953 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010954}
10955
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010956static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010957AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010958{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010959 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010960
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010961 read_wval = AscReadEEPWord(iop_base, addr);
10962 if (read_wval != word_val) {
10963 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
10964 AscWaitEEPRead();
10965 AscWriteEEPDataReg(iop_base, word_val);
10966 AscWaitEEPRead();
10967 AscWriteEEPCmdReg(iop_base,
10968 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
10969 AscWaitEEPWrite();
10970 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
10971 AscWaitEEPRead();
10972 return (AscReadEEPWord(iop_base, addr));
10973 }
10974 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010975}
10976
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010977static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010978AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010979{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010980 ushort wval;
10981 ushort sum;
10982 ushort *wbuf;
10983 int cfg_beg;
10984 int cfg_end;
10985 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
10986 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010987
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010988 wbuf = (ushort *)cfg_buf;
10989 sum = 0;
10990 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
10991 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
10992 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
10993 sum += *wbuf;
10994 }
10995 if (bus_type & ASC_IS_VL) {
10996 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
10997 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
10998 } else {
10999 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11000 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11001 }
11002 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11003 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11004 if (s_addr <= uchar_end_in_config) {
11005 /*
11006 * Swap all char fields - must unswap bytes already swapped
11007 * by AscReadEEPWord().
11008 */
11009 *wbuf = le16_to_cpu(wval);
11010 } else {
11011 /* Don't swap word field at the end - cntl field. */
11012 *wbuf = wval;
11013 }
11014 sum += wval; /* Checksum treats all EEPROM data as words. */
11015 }
11016 /*
11017 * Read the checksum word which will be compared against 'sum'
11018 * by the caller. Word field already swapped.
11019 */
11020 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11021 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011022}
11023
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011024static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011025AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011026{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011027 int n_error;
11028 ushort *wbuf;
11029 ushort word;
11030 ushort sum;
11031 int s_addr;
11032 int cfg_beg;
11033 int cfg_end;
11034 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011035
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011036 wbuf = (ushort *)cfg_buf;
11037 n_error = 0;
11038 sum = 0;
11039 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11040 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11041 sum += *wbuf;
11042 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11043 n_error++;
11044 }
11045 }
11046 if (bus_type & ASC_IS_VL) {
11047 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11048 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11049 } else {
11050 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11051 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11052 }
11053 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11054 if (s_addr <= uchar_end_in_config) {
11055 /*
11056 * This is a char field. Swap char fields before they are
11057 * swapped again by AscWriteEEPWord().
11058 */
11059 word = cpu_to_le16(*wbuf);
11060 if (word !=
11061 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11062 n_error++;
11063 }
11064 } else {
11065 /* Don't swap word field at the end - cntl field. */
11066 if (*wbuf !=
11067 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11068 n_error++;
11069 }
11070 }
11071 sum += *wbuf; /* Checksum calculated from word values. */
11072 }
11073 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11074 *wbuf = sum;
11075 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11076 n_error++;
11077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011078
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011079 /* Read EEPROM back again. */
11080 wbuf = (ushort *)cfg_buf;
11081 /*
11082 * Read two config words; Byte-swapping done by AscReadEEPWord().
11083 */
11084 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11085 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11086 n_error++;
11087 }
11088 }
11089 if (bus_type & ASC_IS_VL) {
11090 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11091 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11092 } else {
11093 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11094 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11095 }
11096 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11097 if (s_addr <= uchar_end_in_config) {
11098 /*
11099 * Swap all char fields. Must unswap bytes already swapped
11100 * by AscReadEEPWord().
11101 */
11102 word =
11103 le16_to_cpu(AscReadEEPWord
11104 (iop_base, (uchar)s_addr));
11105 } else {
11106 /* Don't swap word field at the end - cntl field. */
11107 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11108 }
11109 if (*wbuf != word) {
11110 n_error++;
11111 }
11112 }
11113 /* Read checksum; Byte swapping not needed. */
11114 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11115 n_error++;
11116 }
11117 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011118}
11119
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011120static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011121AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011122{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011123 int retry;
11124 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011125
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011126 retry = 0;
11127 while (TRUE) {
11128 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
11129 bus_type)) == 0) {
11130 break;
11131 }
11132 if (++retry > ASC_EEP_MAX_RETRY) {
11133 break;
11134 }
11135 }
11136 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011137}
11138
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011139static void
11140AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011141{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011142 uchar dvc_type;
11143 ASC_SCSI_BIT_ID_TYPE tid_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011144
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011145 dvc_type = ASC_INQ_DVC_TYPE(inq);
11146 tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011147
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011148 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
11149 if (!(asc_dvc->init_sdtr & tid_bits)) {
11150 if ((dvc_type == TYPE_ROM) &&
11151 (AscCompareString((uchar *)inq->vendor_id,
11152 (uchar *)"HP ", 3) == 0)) {
11153 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
11154 }
11155 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
11156 if ((dvc_type == TYPE_PROCESSOR) ||
11157 (dvc_type == TYPE_SCANNER) ||
11158 (dvc_type == TYPE_ROM) || (dvc_type == TYPE_TAPE)) {
11159 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
11160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011161
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011162 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
11163 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
11164 tid_no,
11165 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11166 }
11167 }
11168 }
11169 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011170}
11171
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011172static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011173{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011174 if ((inq->add_len >= 32) &&
11175 (AscCompareString((uchar *)inq->vendor_id,
11176 (uchar *)"QUANTUM XP34301", 15) == 0) &&
11177 (AscCompareString((uchar *)inq->product_rev_level,
11178 (uchar *)"1071", 4) == 0)) {
11179 return 0;
11180 }
11181 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011182}
11183
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011184static void
11185AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011186{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011187 ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
11188 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011189
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011190 orig_init_sdtr = asc_dvc->init_sdtr;
11191 orig_use_tagged_qng = asc_dvc->use_tagged_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011192
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011193 asc_dvc->init_sdtr &= ~tid_bit;
11194 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
11195 asc_dvc->use_tagged_qng &= ~tid_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011197 if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) {
11198 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) {
11199 asc_dvc->init_sdtr |= tid_bit;
11200 }
11201 if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) &&
11202 ASC_INQ_CMD_QUEUE(inq)) {
11203 if (AscTagQueuingSafe(inq)) {
11204 asc_dvc->use_tagged_qng |= tid_bit;
11205 asc_dvc->cfg->can_tagged_qng |= tid_bit;
11206 }
11207 }
11208 }
11209 if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
11210 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
11211 asc_dvc->cfg->disc_enable);
11212 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
11213 asc_dvc->use_tagged_qng);
11214 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
11215 asc_dvc->cfg->can_tagged_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011216
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011217 asc_dvc->max_dvc_qng[tid_no] =
11218 asc_dvc->cfg->max_tag_qng[tid_no];
11219 AscWriteLramByte(asc_dvc->iop_base,
11220 (ushort)(ASCV_MAX_DVC_QNG_BEG + tid_no),
11221 asc_dvc->max_dvc_qng[tid_no]);
11222 }
11223 if (orig_init_sdtr != asc_dvc->init_sdtr) {
11224 AscAsyncFix(asc_dvc, tid_no, inq);
11225 }
11226 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011227}
11228
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011229static int AscCompareString(uchar *str1, uchar *str2, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011230{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011231 int i;
11232 int diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011233
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011234 for (i = 0; i < len; i++) {
11235 diff = (int)(str1[i] - str2[i]);
11236 if (diff != 0)
11237 return (diff);
11238 }
11239 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011240}
11241
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011242static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011243{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011244 uchar byte_data;
11245 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011246
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011247 if (isodd_word(addr)) {
11248 AscSetChipLramAddr(iop_base, addr - 1);
11249 word_data = AscGetChipLramData(iop_base);
11250 byte_data = (uchar)((word_data >> 8) & 0xFF);
11251 } else {
11252 AscSetChipLramAddr(iop_base, addr);
11253 word_data = AscGetChipLramData(iop_base);
11254 byte_data = (uchar)(word_data & 0xFF);
11255 }
11256 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011257}
Linus Torvalds1da177e2005-04-16 15:20:36 -070011258
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011259static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
11260{
11261 ushort word_data;
11262
11263 AscSetChipLramAddr(iop_base, addr);
11264 word_data = AscGetChipLramData(iop_base);
11265 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011266}
11267
11268#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011269static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011270{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011271 ushort val_low, val_high;
11272 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011273
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011274 AscSetChipLramAddr(iop_base, addr);
11275 val_low = AscGetChipLramData(iop_base);
11276 val_high = AscGetChipLramData(iop_base);
11277 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
11278 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011279}
11280#endif /* CC_VERY_LONG_SG_LIST */
11281
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011282static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011283{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011284 AscSetChipLramAddr(iop_base, addr);
11285 AscSetChipLramData(iop_base, word_val);
11286 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011287}
11288
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011289static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011290{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011291 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011292
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011293 if (isodd_word(addr)) {
11294 addr--;
11295 word_data = AscReadLramWord(iop_base, addr);
11296 word_data &= 0x00FF;
11297 word_data |= (((ushort)byte_val << 8) & 0xFF00);
11298 } else {
11299 word_data = AscReadLramWord(iop_base, addr);
11300 word_data &= 0xFF00;
11301 word_data |= ((ushort)byte_val & 0x00FF);
11302 }
11303 AscWriteLramWord(iop_base, addr, word_data);
11304 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011305}
11306
11307/*
11308 * Copy 2 bytes to LRAM.
11309 *
11310 * The source data is assumed to be in little-endian order in memory
11311 * and is maintained in little-endian order when written to LRAM.
11312 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011313static void
11314AscMemWordCopyPtrToLram(PortAddr iop_base,
11315 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011316{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011317 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011318
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011319 AscSetChipLramAddr(iop_base, s_addr);
11320 for (i = 0; i < 2 * words; i += 2) {
11321 /*
11322 * On a little-endian system the second argument below
11323 * produces a little-endian ushort which is written to
11324 * LRAM in little-endian order. On a big-endian system
11325 * the second argument produces a big-endian ushort which
11326 * is "transparently" byte-swapped by outpw() and written
11327 * in little-endian order to LRAM.
11328 */
11329 outpw(iop_base + IOP_RAM_DATA,
11330 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
11331 }
11332 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011333}
11334
11335/*
11336 * Copy 4 bytes to LRAM.
11337 *
11338 * The source data is assumed to be in little-endian order in memory
11339 * and is maintained in little-endian order when writen to LRAM.
11340 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011341static void
11342AscMemDWordCopyPtrToLram(PortAddr iop_base,
11343 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011344{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011345 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011346
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011347 AscSetChipLramAddr(iop_base, s_addr);
11348 for (i = 0; i < 4 * dwords; i += 4) {
11349 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
11350 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
11351 }
11352 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011353}
11354
11355/*
11356 * Copy 2 bytes from LRAM.
11357 *
11358 * The source data is assumed to be in little-endian order in LRAM
11359 * and is maintained in little-endian order when written to memory.
11360 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011361static void
11362AscMemWordCopyPtrFromLram(PortAddr iop_base,
11363 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011364{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011365 int i;
11366 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011367
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011368 AscSetChipLramAddr(iop_base, s_addr);
11369 for (i = 0; i < 2 * words; i += 2) {
11370 word = inpw(iop_base + IOP_RAM_DATA);
11371 d_buffer[i] = word & 0xff;
11372 d_buffer[i + 1] = (word >> 8) & 0xff;
11373 }
11374 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011375}
11376
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011377static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011378{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011379 ASC_DCNT sum;
11380 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011381
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011382 sum = 0L;
11383 for (i = 0; i < words; i++, s_addr += 2) {
11384 sum += AscReadLramWord(iop_base, s_addr);
11385 }
11386 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011387}
11388
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011389static void
11390AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011391{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011392 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011393
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011394 AscSetChipLramAddr(iop_base, s_addr);
11395 for (i = 0; i < words; i++) {
11396 AscSetChipLramData(iop_base, set_wval);
11397 }
11398 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011399}
11400
Linus Torvalds1da177e2005-04-16 15:20:36 -070011401/*
11402 * --- Adv Library Functions
11403 */
11404
11405/* a_mcode.h */
11406
11407/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011408static unsigned char _adv_asc3550_buf[] = {
11409 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
11410 0x01, 0x00, 0x48, 0xe4,
11411 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff,
11412 0x28, 0x0e, 0x9e, 0xe7,
11413 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7,
11414 0x55, 0xf0, 0x01, 0xf6,
11415 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
11416 0x00, 0xec, 0x85, 0xf0,
11417 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0,
11418 0x86, 0xf0, 0xb4, 0x00,
11419 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00,
11420 0xaa, 0x18, 0x02, 0x80,
11421 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
11422 0x00, 0x57, 0x01, 0xea,
11423 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80,
11424 0x03, 0xe6, 0xb6, 0x00,
11425 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12,
11426 0x02, 0x4a, 0xb9, 0x54,
11427 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
11428 0x3e, 0x00, 0x80, 0x00,
11429 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
11430 0x74, 0x01, 0x76, 0x01,
11431 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13,
11432 0x4c, 0x1c, 0xbb, 0x55,
11433 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
11434 0x03, 0xf7, 0x06, 0xf7,
11435 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08,
11436 0x30, 0x13, 0x64, 0x15,
11437 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c,
11438 0x04, 0xea, 0x5d, 0xf0,
11439 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
11440 0xcc, 0x00, 0x20, 0x01,
11441 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13,
11442 0x40, 0x13, 0x30, 0x1c,
11443 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
11444 0x59, 0xf0, 0xa7, 0xf0,
11445 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
11446 0xa4, 0x00, 0xb5, 0x00,
11447 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a,
11448 0x14, 0x0e, 0x02, 0x10,
11449 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13,
11450 0x10, 0x15, 0x14, 0x15,
11451 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
11452 0x91, 0x44, 0x0a, 0x45,
11453 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58,
11454 0x83, 0x59, 0x05, 0xe6,
11455 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8,
11456 0x02, 0xfa, 0x03, 0xfa,
11457 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
11458 0x9e, 0x00, 0xa8, 0x00,
11459 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01,
11460 0x7a, 0x01, 0xc0, 0x01,
11461 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08,
11462 0x69, 0x08, 0xba, 0x08,
11463 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
11464 0xf1, 0x10, 0x06, 0x12,
11465 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14,
11466 0x8a, 0x15, 0xc6, 0x17,
11467 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
11468 0x0e, 0x47, 0x48, 0x47,
11469 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
11470 0x14, 0x56, 0x77, 0x57,
11471 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c,
11472 0xf0, 0x29, 0x02, 0xfe,
11473 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf,
11474 0xfe, 0x80, 0x01, 0xff,
11475 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
11476 0x00, 0xfe, 0x57, 0x24,
11477 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09,
11478 0x00, 0x00, 0xff, 0x08,
11479 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
11480 0xff, 0xff, 0xff, 0x0f,
11481 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
11482 0xfe, 0x04, 0xf7, 0xcf,
11483 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67,
11484 0x0b, 0x3c, 0x2a, 0xfe,
11485 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0,
11486 0xfe, 0xf0, 0x01, 0xfe,
11487 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
11488 0x02, 0xfe, 0xd4, 0x0c,
11489 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
11490 0x1c, 0x05, 0xfe, 0xa6,
11491 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48,
11492 0xf0, 0xfe, 0x86, 0x02,
11493 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
11494 0xfe, 0x46, 0xf0, 0xfe,
11495 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
11496 0x44, 0x02, 0xfe, 0x44,
11497 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b,
11498 0xa0, 0x17, 0x06, 0x18,
11499 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
11500 0x1e, 0x1c, 0xfe, 0xe9,
11501 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7,
11502 0x0a, 0x6b, 0x01, 0x9e,
11503 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b,
11504 0x01, 0x82, 0xfe, 0xbd,
11505 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
11506 0x58, 0x1c, 0x17, 0x06,
11507 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21,
11508 0xfe, 0x94, 0x02, 0xfe,
11509 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97,
11510 0x01, 0xfe, 0x54, 0x0f,
11511 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
11512 0x69, 0x10, 0x17, 0x06,
11513 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05,
11514 0xf6, 0xc7, 0x01, 0xfe,
11515 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6,
11516 0x02, 0x29, 0x0a, 0x40,
11517 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
11518 0x58, 0x0a, 0x99, 0x01,
11519 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29,
11520 0x2a, 0x46, 0xfe, 0x02,
11521 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc,
11522 0x01, 0xfe, 0x07, 0x4b,
11523 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
11524 0xfe, 0x56, 0x03, 0xfe,
11525 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10,
11526 0xfe, 0x9f, 0xf0, 0xfe,
11527 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48,
11528 0x1c, 0xeb, 0x09, 0x04,
11529 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
11530 0x01, 0x0e, 0xac, 0x75,
11531 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2,
11532 0xfe, 0x82, 0xf0, 0xfe,
11533 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25,
11534 0x32, 0x1f, 0xfe, 0xb4,
11535 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
11536 0x0a, 0xf0, 0xfe, 0x7a,
11537 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c,
11538 0x01, 0x33, 0x8f, 0xfe,
11539 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8,
11540 0xf7, 0xfe, 0x48, 0x1c,
11541 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
11542 0x0a, 0xca, 0x01, 0x0e,
11543 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14,
11544 0x2c, 0x01, 0x33, 0x8f,
11545 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65,
11546 0xfe, 0x3c, 0x04, 0x1f,
11547 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
11548 0x12, 0x2b, 0xff, 0x02,
11549 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f,
11550 0x22, 0x30, 0x2e, 0xd5,
11551 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c,
11552 0xfe, 0x4c, 0x54, 0x64,
11553 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
11554 0xfe, 0x2a, 0x13, 0x2f,
11555 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
11556 0xd3, 0xfa, 0xef, 0x86,
11557 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04,
11558 0x1d, 0xfe, 0x1c, 0x12,
11559 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
11560 0x70, 0x0c, 0x02, 0x22,
11561 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92,
11562 0x01, 0x33, 0x02, 0x29,
11563 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87,
11564 0x80, 0xfe, 0x31, 0xe4,
11565 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
11566 0xfe, 0x70, 0x12, 0x49,
11567 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe,
11568 0x80, 0x05, 0xfe, 0x31,
11569 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00,
11570 0x28, 0xfe, 0x42, 0x12,
11571 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
11572 0x11, 0xfe, 0xe3, 0x00,
11573 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
11574 0x64, 0x05, 0x83, 0x24,
11575 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe,
11576 0x09, 0x48, 0x01, 0x08,
11577 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
11578 0x86, 0x24, 0x06, 0x12,
11579 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47,
11580 0x01, 0xa7, 0x14, 0x92,
11581 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c,
11582 0x02, 0x22, 0x05, 0xfe,
11583 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
11584 0x47, 0x01, 0xa7, 0x26,
11585 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f,
11586 0x01, 0xfe, 0xaa, 0x14,
11587 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00,
11588 0x05, 0x50, 0xb4, 0x0c,
11589 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
11590 0x13, 0x01, 0xfe, 0x14,
11591 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c,
11592 0xff, 0x02, 0x00, 0x57,
11593 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe,
11594 0x72, 0x06, 0x49, 0x04,
11595 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
11596 0x06, 0x11, 0x9a, 0x01,
11597 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06,
11598 0x01, 0xa7, 0xec, 0x72,
11599 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32,
11600 0xfe, 0x0a, 0xf0, 0xfe,
11601 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
11602 0x8d, 0x81, 0x02, 0x22,
11603 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00,
11604 0x01, 0x08, 0x15, 0x00,
11605 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15,
11606 0x00, 0x02, 0xfe, 0x32,
11607 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
11608 0xfe, 0x1b, 0x00, 0x01,
11609 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
11610 0x08, 0x15, 0x06, 0x01,
11611 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe,
11612 0x9a, 0x81, 0x4b, 0x1d,
11613 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
11614 0x45, 0xfe, 0x32, 0x12,
11615 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0,
11616 0xfe, 0x32, 0x07, 0x8d,
11617 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a,
11618 0x06, 0x15, 0x19, 0x02,
11619 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
11620 0x90, 0x77, 0xfe, 0xca,
11621 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07,
11622 0x10, 0xfe, 0x0e, 0x12,
11623 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe,
11624 0x83, 0xe7, 0xc4, 0xa1,
11625 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
11626 0x40, 0x12, 0x58, 0x01,
11627 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6,
11628 0x51, 0x83, 0xfb, 0xfe,
11629 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90,
11630 0xfe, 0x40, 0x50, 0xfe,
11631 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
11632 0xfe, 0x2a, 0x12, 0xfe,
11633 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f,
11634 0x85, 0x01, 0xa8, 0xfe,
11635 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56,
11636 0x18, 0x57, 0xfb, 0xfe,
11637 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
11638 0x0c, 0x39, 0x18, 0x3a,
11639 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e,
11640 0x11, 0x65, 0xfe, 0x48,
11641 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73,
11642 0xdd, 0xb8, 0xfe, 0x80,
11643 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
11644 0xfe, 0x7a, 0x08, 0x8d,
11645 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9,
11646 0x10, 0x61, 0x04, 0x06,
11647 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68,
11648 0x12, 0xfe, 0x2e, 0x1c,
11649 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
11650 0x52, 0x12, 0xfe, 0x2c,
11651 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe,
11652 0x08, 0xfe, 0x8a, 0x10,
11653 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe,
11654 0x24, 0x0a, 0xab, 0xfe,
11655 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
11656 0x1c, 0x12, 0xb5, 0xfe,
11657 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb,
11658 0x1c, 0x06, 0x16, 0x9d,
11659 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b,
11660 0x14, 0x92, 0x01, 0x33,
11661 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
11662 0xfe, 0x74, 0x18, 0x1c,
11663 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b,
11664 0x01, 0xe6, 0x1e, 0x27,
11665 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a,
11666 0x09, 0x04, 0x6a, 0xfe,
11667 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
11668 0xfe, 0x83, 0x80, 0xfe,
11669 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63,
11670 0x27, 0xfe, 0x40, 0x59,
11671 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18,
11672 0x7c, 0xbe, 0x54, 0xbf,
11673 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
11674 0x79, 0x56, 0x68, 0x57,
11675 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5,
11676 0xa2, 0x23, 0x0c, 0x7b,
11677 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19,
11678 0x16, 0xd7, 0x79, 0x39,
11679 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
11680 0xfe, 0x10, 0x58, 0xfe,
11681 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04,
11682 0x19, 0x16, 0xd7, 0x09,
11683 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f,
11684 0xfe, 0x10, 0x90, 0xfe,
11685 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
11686 0x11, 0x9b, 0x09, 0x04,
11687 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08,
11688 0xfe, 0x0c, 0x58, 0xfe,
11689 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04,
11690 0x0b, 0xfe, 0x1a, 0x12,
11691 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
11692 0x14, 0x7a, 0x01, 0x33,
11693 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39,
11694 0xfe, 0xed, 0x19, 0xbf,
11695 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff,
11696 0x34, 0xfe, 0x74, 0x10,
11697 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
11698 0x84, 0x05, 0xcb, 0x1c,
11699 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1,
11700 0xf0, 0xfe, 0xc4, 0x0a,
11701 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe,
11702 0xce, 0xf0, 0xfe, 0xca,
11703 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
11704 0x22, 0x00, 0x02, 0x5a,
11705 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a,
11706 0xfe, 0xd0, 0xf0, 0xfe,
11707 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f,
11708 0x4c, 0xfe, 0x10, 0x10,
11709 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
11710 0x2a, 0x13, 0xfe, 0x4e,
11711 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1,
11712 0x16, 0x32, 0x2a, 0x73,
11713 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25,
11714 0x32, 0x8c, 0xfe, 0x48,
11715 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
11716 0xdb, 0x10, 0x11, 0xfe,
11717 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0,
11718 0x22, 0x30, 0x2e, 0xd8,
11719 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1,
11720 0x45, 0x0f, 0xfe, 0x42,
11721 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
11722 0x09, 0x04, 0x0b, 0xfe,
11723 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28,
11724 0x00, 0x21, 0xfe, 0xa6,
11725 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00,
11726 0xfe, 0xe2, 0x10, 0x01,
11727 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
11728 0x01, 0x6f, 0x02, 0x29,
11729 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10,
11730 0x01, 0x86, 0x3e, 0x0b,
11731 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3,
11732 0x3e, 0x0b, 0x0f, 0xfe,
11733 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
11734 0xe8, 0x59, 0x11, 0x2d,
11735 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09,
11736 0x04, 0x0b, 0x84, 0x3e,
11737 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12,
11738 0x09, 0x04, 0x1b, 0xfe,
11739 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
11740 0x1c, 0x1c, 0xfe, 0x9d,
11741 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f,
11742 0xfe, 0x15, 0x00, 0xfe,
11743 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10,
11744 0x0f, 0xfe, 0x47, 0x00,
11745 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
11746 0xab, 0x70, 0x05, 0x6b,
11747 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe,
11748 0x1c, 0x42, 0x59, 0x01,
11749 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31,
11750 0x00, 0x37, 0x97, 0x01,
11751 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
11752 0x1d, 0xfe, 0xce, 0x45,
11753 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75,
11754 0x57, 0x05, 0x51, 0xfe,
11755 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48,
11756 0x46, 0x09, 0x04, 0x1d,
11757 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
11758 0x99, 0x01, 0x0e, 0xfe,
11759 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51,
11760 0xfe, 0xee, 0x14, 0xee,
11761 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad,
11762 0x13, 0x02, 0x29, 0x1e,
11763 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
11764 0xce, 0x1e, 0x2d, 0x47,
11765 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06,
11766 0x12, 0x4d, 0x01, 0xfe,
11767 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe,
11768 0xf0, 0x0d, 0xfe, 0x02,
11769 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
11770 0xf6, 0xfe, 0x34, 0x01,
11771 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13,
11772 0xaf, 0xfe, 0x02, 0xea,
11773 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c,
11774 0x05, 0xfe, 0x38, 0x01,
11775 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
11776 0x0c, 0xfe, 0x62, 0x01,
11777 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06,
11778 0x03, 0x23, 0x03, 0x1e,
11779 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe,
11780 0x71, 0x13, 0xfe, 0x24,
11781 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
11782 0xdc, 0xfe, 0x73, 0x57,
11783 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe,
11784 0x80, 0x5d, 0x03, 0xfe,
11785 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6,
11786 0x75, 0x03, 0x09, 0x04,
11787 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
11788 0xfe, 0x1e, 0x80, 0xe1,
11789 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e,
11790 0x90, 0xa3, 0xfe, 0x3c,
11791 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82,
11792 0x16, 0x2f, 0x07, 0x2d,
11793 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
11794 0xe8, 0x11, 0xfe, 0xe9,
11795 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe,
11796 0x1e, 0x1c, 0xfe, 0x14,
11797 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01,
11798 0x09, 0x04, 0x4f, 0xfe,
11799 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
11800 0x40, 0x12, 0x20, 0x63,
11801 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08,
11802 0x1c, 0x05, 0xfe, 0xac,
11803 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05,
11804 0xfe, 0xb0, 0x00, 0xfe,
11805 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
11806 0x24, 0x69, 0x12, 0xc9,
11807 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe,
11808 0x90, 0x4d, 0xfe, 0x91,
11809 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c,
11810 0xfe, 0x90, 0x4d, 0xfe,
11811 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
11812 0x46, 0x1e, 0x20, 0xed,
11813 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea,
11814 0x70, 0xfe, 0x14, 0x1c,
11815 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee,
11816 0xfe, 0x07, 0xe6, 0x1d,
11817 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
11818 0xfa, 0xef, 0xfe, 0x42,
11819 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0,
11820 0xfe, 0x36, 0x12, 0xf0,
11821 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
11822 0x3d, 0x75, 0x07, 0x10,
11823 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
11824 0x10, 0x07, 0x7e, 0x45,
11825 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74,
11826 0xfe, 0x01, 0xec, 0x97,
11827 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76,
11828 0x27, 0x01, 0xda, 0xfe,
11829 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
11830 0xfe, 0x48, 0x12, 0x07,
11831 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16,
11832 0xfe, 0x3e, 0x11, 0x07,
11833 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8,
11834 0x11, 0x07, 0x19, 0xfe,
11835 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
11836 0x01, 0x08, 0x8c, 0x43,
11837 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11,
11838 0x7e, 0x02, 0x29, 0x2b,
11839 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe,
11840 0xfc, 0x10, 0x09, 0x04,
11841 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
11842 0xc6, 0x10, 0x1e, 0x58,
11843 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c,
11844 0x54, 0x18, 0x55, 0x23,
11845 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01,
11846 0xa5, 0xc0, 0x38, 0xc1,
11847 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
11848 0x05, 0xfa, 0x4e, 0xfe,
11849 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56,
11850 0x0c, 0x56, 0x18, 0x57,
11851 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe,
11852 0x00, 0x56, 0xfe, 0xa1,
11853 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
11854 0x58, 0xfe, 0x1f, 0x40,
11855 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56,
11856 0x31, 0x57, 0xfe, 0x44,
11857 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe,
11858 0x8a, 0x50, 0x05, 0x39,
11859 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
11860 0x12, 0xcd, 0x02, 0x5b,
11861 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44,
11862 0x2f, 0x07, 0x9b, 0x21,
11863 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79,
11864 0x39, 0x68, 0x3a, 0xfe,
11865 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
11866 0x51, 0xfe, 0x8e, 0x51,
11867 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b,
11868 0x01, 0x08, 0x25, 0x32,
11869 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b,
11870 0x3b, 0x02, 0x44, 0x01,
11871 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
11872 0x01, 0x08, 0x1f, 0xa2,
11873 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c,
11874 0x00, 0x28, 0x84, 0x49,
11875 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06,
11876 0x78, 0x3d, 0xfe, 0xda,
11877 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
11878 0x05, 0xc6, 0x28, 0x84,
11879 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8,
11880 0x14, 0xfe, 0x03, 0x17,
11881 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01,
11882 0xfe, 0xaa, 0x14, 0x02,
11883 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
11884 0x21, 0x44, 0x01, 0xfe,
11885 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87,
11886 0xfe, 0x4a, 0xf4, 0x0b,
11887 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a,
11888 0x85, 0x02, 0x5b, 0x05,
11889 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
11890 0xd8, 0x14, 0x02, 0x5c,
11891 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1,
11892 0x01, 0x08, 0x23, 0x72,
11893 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca,
11894 0x12, 0x5e, 0x2b, 0x01,
11895 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
11896 0x1c, 0xfe, 0xff, 0x7f,
11897 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00,
11898 0x57, 0x48, 0x8b, 0x1c,
11899 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02,
11900 0x00, 0x57, 0x48, 0x8b,
11901 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
11902 0x03, 0x0a, 0x50, 0x01,
11903 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00,
11904 0x54, 0xfe, 0x00, 0xf4,
11905 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe,
11906 0x03, 0x7c, 0x63, 0x27,
11907 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
11908 0xfe, 0x82, 0x4a, 0xfe,
11909 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe,
11910 0x42, 0x48, 0x5f, 0x60,
11911 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08,
11912 0x1f, 0xfe, 0xa2, 0x14,
11913 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
11914 0xcc, 0x12, 0x49, 0x04,
11915 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe,
11916 0xe8, 0x13, 0x3b, 0x13,
11917 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55,
11918 0xa1, 0xff, 0x02, 0x83,
11919 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
11920 0x13, 0x06, 0xfe, 0x56,
11921 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe,
11922 0x64, 0x00, 0x17, 0x93,
11923 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe,
11924 0xc8, 0x00, 0x8e, 0xe4,
11925 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
11926 0x01, 0xba, 0xfe, 0x4e,
11927 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0,
11928 0xfe, 0x60, 0x14, 0xfe,
11929 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01,
11930 0xfe, 0x22, 0x13, 0x1c,
11931 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
11932 0xfe, 0x9c, 0x14, 0xb7,
11933 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba,
11934 0xfe, 0x9c, 0x14, 0xb7,
11935 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06,
11936 0xfe, 0xb4, 0x56, 0xfe,
11937 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
11938 0xe5, 0x15, 0x0b, 0x01,
11939 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89,
11940 0x49, 0x01, 0x08, 0x03,
11941 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6,
11942 0x15, 0x06, 0x01, 0x08,
11943 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
11944 0x4a, 0x01, 0x08, 0x03,
11945 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc,
11946 0xfe, 0x49, 0xf4, 0x00,
11947 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01,
11948 0x08, 0x2f, 0x07, 0xfe,
11949 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
11950 0x01, 0x43, 0x1e, 0xcd,
11951 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e,
11952 0xed, 0x88, 0x07, 0x10,
11953 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a,
11954 0x80, 0x01, 0x0e, 0x88,
11955 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
11956 0x88, 0x03, 0x0a, 0x42,
11957 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e,
11958 0xfe, 0x80, 0x80, 0xf2,
11959 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51,
11960 0x01, 0x82, 0x03, 0x17,
11961 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
11962 0xfe, 0x24, 0x1c, 0xfe,
11963 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0,
11964 0x91, 0x1d, 0x66, 0xfe,
11965 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe,
11966 0xda, 0x10, 0x17, 0x10,
11967 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
11968 0x05, 0xfe, 0x66, 0x01,
11969 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06,
11970 0xfe, 0x3c, 0x50, 0x66,
11971 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe,
11972 0x40, 0x16, 0xfe, 0xb6,
11973 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
11974 0x10, 0x71, 0xfe, 0x83,
11975 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90,
11976 0xfe, 0x62, 0x16, 0xfe,
11977 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19,
11978 0xfe, 0x98, 0xe7, 0x00,
11979 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
11980 0xfe, 0x30, 0xbc, 0xfe,
11981 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
11982 0xc5, 0x90, 0xfe, 0x9a,
11983 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe,
11984 0x42, 0x10, 0xfe, 0x02,
11985 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
11986 0xfe, 0x1d, 0xf7, 0x4f,
11987 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f,
11988 0x47, 0xfe, 0x83, 0x58,
11989 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11,
11990 0xfe, 0xdd, 0x00, 0x63,
11991 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
11992 0x06, 0x37, 0x95, 0xa9,
11993 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e,
11994 0x18, 0x1c, 0x1a, 0x5d,
11995 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe,
11996 0xe1, 0x10, 0x78, 0x2c,
11997 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
11998 0x13, 0x3c, 0x8a, 0x0a,
11999 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
12000 0xe3, 0xfe, 0x00, 0xcc,
12001 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01,
12002 0x0e, 0xf2, 0x01, 0x6f,
12003 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
12004 0xf6, 0xfe, 0xd6, 0xf0,
12005 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe,
12006 0x15, 0x00, 0x59, 0x76,
12007 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35,
12008 0x11, 0x2d, 0x01, 0x6f,
12009 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
12010 0xc8, 0xfe, 0x48, 0x55,
12011 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a,
12012 0x99, 0x01, 0x0e, 0xf0,
12013 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73,
12014 0x75, 0x03, 0x0a, 0x42,
12015 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
12016 0x0e, 0x73, 0x75, 0x03,
12017 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00,
12018 0xfe, 0x3a, 0x45, 0x5b,
12019 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00,
12020 0xfe, 0x02, 0xe6, 0x1b,
12021 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
12022 0xfe, 0x94, 0x00, 0xfe,
12023 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02,
12024 0xe6, 0x2c, 0xfe, 0x4e,
12025 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69,
12026 0x03, 0x07, 0x7a, 0xfe,
12027 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
12028 0x07, 0x1b, 0xfe, 0x5a,
12029 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d,
12030 0x24, 0x2c, 0xdc, 0x07,
12031 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d,
12032 0x9f, 0xad, 0x03, 0x14,
12033 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
12034 0x03, 0x25, 0xfe, 0xca,
12035 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a,
12036 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012037};
12038
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012039static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
12040static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012041
12042/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012043static unsigned char _adv_asc38C0800_buf[] = {
12044 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
12045 0x01, 0x00, 0x48, 0xe4,
12046 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff,
12047 0x1c, 0x0f, 0x00, 0xf6,
12048 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6,
12049 0x09, 0xe7, 0x55, 0xf0,
12050 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
12051 0x18, 0xf4, 0x08, 0x00,
12052 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6,
12053 0x86, 0xf0, 0xb1, 0xf0,
12054 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c,
12055 0x3c, 0x00, 0xbb, 0x00,
12056 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
12057 0xba, 0x13, 0x18, 0x40,
12058 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01,
12059 0x6e, 0x01, 0x74, 0x01,
12060 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00,
12061 0xc0, 0x00, 0x01, 0x01,
12062 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
12063 0x08, 0x12, 0x02, 0x4a,
12064 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4,
12065 0x5d, 0xf0, 0x02, 0xfa,
12066 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01,
12067 0x68, 0x01, 0x6a, 0x01,
12068 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
12069 0x06, 0x13, 0x4c, 0x1c,
12070 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00,
12071 0x0f, 0x00, 0x47, 0x00,
12072 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c,
12073 0x4e, 0x1c, 0x10, 0x44,
12074 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
12075 0x05, 0x00, 0x34, 0x00,
12076 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b,
12077 0x42, 0x0c, 0x12, 0x0f,
12078 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48,
12079 0x00, 0x4e, 0x42, 0x54,
12080 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
12081 0x59, 0xf0, 0xb8, 0xf0,
12082 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00,
12083 0x19, 0x00, 0x33, 0x00,
12084 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00,
12085 0xe7, 0x00, 0xe2, 0x03,
12086 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
12087 0x12, 0x13, 0x24, 0x14,
12088 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c,
12089 0x36, 0x1c, 0x08, 0x44,
12090 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54,
12091 0x3a, 0x55, 0x83, 0x55,
12092 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
12093 0x0c, 0xf0, 0x04, 0xf8,
12094 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00,
12095 0xa8, 0x00, 0xaa, 0x00,
12096 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01,
12097 0xc4, 0x01, 0xc6, 0x01,
12098 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
12099 0x68, 0x08, 0x69, 0x08,
12100 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10,
12101 0xed, 0x10, 0xf1, 0x10,
12102 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13,
12103 0x1e, 0x13, 0x46, 0x14,
12104 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
12105 0xca, 0x18, 0xe6, 0x19,
12106 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c,
12107 0xf0, 0x2b, 0x02, 0xfe,
12108 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6,
12109 0xfe, 0x84, 0x01, 0xff,
12110 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
12111 0x00, 0xfe, 0x57, 0x24,
12112 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09,
12113 0x00, 0x00, 0xff, 0x08,
12114 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
12115 0xff, 0xff, 0xff, 0x11,
12116 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
12117 0xfe, 0x04, 0xf7, 0xd6,
12118 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99,
12119 0x0a, 0x42, 0x2c, 0xfe,
12120 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0,
12121 0xfe, 0xf4, 0x01, 0xfe,
12122 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
12123 0x02, 0xfe, 0xc8, 0x0d,
12124 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
12125 0x1c, 0x03, 0xfe, 0xa6,
12126 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48,
12127 0xf0, 0xfe, 0x8a, 0x02,
12128 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
12129 0xfe, 0x46, 0xf0, 0xfe,
12130 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
12131 0x48, 0x02, 0xfe, 0x44,
12132 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a,
12133 0xaa, 0x18, 0x06, 0x14,
12134 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
12135 0x1e, 0x1c, 0xfe, 0xe9,
12136 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce,
12137 0x09, 0x70, 0x01, 0xa8,
12138 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70,
12139 0x01, 0x87, 0xfe, 0xbd,
12140 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
12141 0x58, 0x1c, 0x18, 0x06,
12142 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23,
12143 0xfe, 0x98, 0x02, 0xfe,
12144 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2,
12145 0x01, 0xfe, 0x48, 0x10,
12146 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
12147 0x69, 0x10, 0x18, 0x06,
12148 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05,
12149 0xf6, 0xce, 0x01, 0xfe,
12150 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe,
12151 0x82, 0x16, 0x02, 0x2b,
12152 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
12153 0xfe, 0x41, 0x58, 0x09,
12154 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe,
12155 0x82, 0x16, 0x02, 0x2b,
12156 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43,
12157 0xfe, 0x77, 0x57, 0xfe,
12158 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
12159 0xfe, 0x40, 0x1c, 0x1c,
12160 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48,
12161 0x03, 0xfe, 0x11, 0xf0,
12162 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10,
12163 0xfe, 0x11, 0x00, 0x02,
12164 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
12165 0x21, 0x22, 0xa3, 0xb7,
12166 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16,
12167 0x12, 0xd1, 0x1c, 0xd9,
12168 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12,
12169 0xfe, 0xe4, 0x00, 0x27,
12170 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
12171 0x06, 0xf0, 0xfe, 0xc8,
12172 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03,
12173 0x70, 0x28, 0x17, 0xfe,
12174 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8,
12175 0xf9, 0x2c, 0x99, 0x19,
12176 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
12177 0x74, 0x01, 0xaf, 0x8c,
12178 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e,
12179 0x8d, 0x51, 0x64, 0x79,
12180 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b,
12181 0xfe, 0x6a, 0x02, 0x02,
12182 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
12183 0xfe, 0x3c, 0x04, 0x3b,
12184 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02,
12185 0x00, 0x10, 0x01, 0x0b,
12186 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde,
12187 0xfe, 0x4c, 0x44, 0xfe,
12188 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
12189 0xda, 0x4f, 0x79, 0x2a,
12190 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b,
12191 0xfe, 0x2a, 0x13, 0x32,
12192 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c,
12193 0x54, 0x6b, 0xda, 0xfe,
12194 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
12195 0x08, 0x13, 0x32, 0x07,
12196 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d,
12197 0x08, 0x05, 0x06, 0x4d,
12198 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24,
12199 0x2d, 0x12, 0xfe, 0xe6,
12200 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
12201 0x02, 0x2b, 0xfe, 0x42,
12202 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
12203 0xfe, 0x87, 0x80, 0xfe,
12204 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80,
12205 0x07, 0x19, 0xfe, 0x7c,
12206 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
12207 0x17, 0xfe, 0x90, 0x05,
12208 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe,
12209 0xa0, 0x00, 0x28, 0xfe,
12210 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c,
12211 0x34, 0xfe, 0x89, 0x48,
12212 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
12213 0x12, 0xfe, 0xe3, 0x00,
12214 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
12215 0x70, 0x05, 0x88, 0x25,
12216 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe,
12217 0x09, 0x48, 0xff, 0x02,
12218 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
12219 0x08, 0x53, 0x05, 0xcb,
12220 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08,
12221 0x05, 0x1b, 0xfe, 0x22,
12222 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe,
12223 0x0d, 0x00, 0x01, 0x36,
12224 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
12225 0x03, 0x5c, 0x28, 0xfe,
12226 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53,
12227 0x05, 0x1f, 0xfe, 0x02,
12228 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5,
12229 0x01, 0x4b, 0x12, 0xfe,
12230 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
12231 0x12, 0x03, 0x45, 0x28,
12232 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe,
12233 0x43, 0x48, 0xc4, 0xcc,
12234 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4,
12235 0x6e, 0x41, 0x01, 0xb2,
12236 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
12237 0xfe, 0xcc, 0x15, 0x1d,
12238 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03,
12239 0x45, 0xc1, 0x0c, 0x45,
12240 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe,
12241 0xe2, 0x00, 0x27, 0xdb,
12242 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
12243 0xfe, 0x06, 0xf0, 0xfe,
12244 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12,
12245 0x16, 0x19, 0x01, 0x0b,
12246 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
12247 0xfe, 0x99, 0xa4, 0x01,
12248 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
12249 0x12, 0x08, 0x05, 0x1a,
12250 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
12251 0x0b, 0x16, 0x00, 0x01,
12252 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02,
12253 0xe2, 0x6c, 0x58, 0xbe,
12254 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
12255 0xfe, 0x09, 0x6f, 0xba,
12256 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27,
12257 0xfe, 0x54, 0x07, 0x1c,
12258 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c,
12259 0x07, 0x02, 0x24, 0x01,
12260 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
12261 0x2c, 0x90, 0xfe, 0xae,
12262 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a,
12263 0x37, 0x22, 0x20, 0x07,
12264 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a,
12265 0xfe, 0x06, 0x10, 0xfe,
12266 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
12267 0x37, 0x01, 0xb3, 0xb8,
12268 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a,
12269 0x50, 0xfe, 0x44, 0x51,
12270 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e,
12271 0x14, 0x5f, 0xfe, 0x0c,
12272 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
12273 0x14, 0x3e, 0xfe, 0x4a,
12274 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
12275 0x90, 0x0c, 0x60, 0x14,
12276 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62,
12277 0xfe, 0x44, 0x90, 0xfe,
12278 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
12279 0x0c, 0x5e, 0x14, 0x5f,
12280 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e,
12281 0x14, 0x3c, 0x21, 0x0c,
12282 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11,
12283 0x27, 0xdd, 0xfe, 0x9e,
12284 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
12285 0x9a, 0x08, 0xc6, 0xfe,
12286 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08,
12287 0x95, 0x86, 0x02, 0x24,
12288 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05,
12289 0x06, 0xfe, 0x10, 0x12,
12290 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
12291 0x1c, 0x02, 0xfe, 0x18,
12292 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe,
12293 0x2c, 0x1c, 0xfe, 0xaa,
12294 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe,
12295 0xde, 0x09, 0xfe, 0xb7,
12296 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
12297 0xfe, 0xf1, 0x18, 0xfe,
12298 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe,
12299 0x14, 0x59, 0xfe, 0x95,
12300 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0,
12301 0xfe, 0xf0, 0x08, 0xb5,
12302 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
12303 0x0b, 0xb6, 0xfe, 0xbf,
12304 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c,
12305 0x12, 0xc2, 0xfe, 0xd2,
12306 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e,
12307 0x06, 0x17, 0x85, 0xc5,
12308 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
12309 0x9d, 0x01, 0x36, 0x10,
12310 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe,
12311 0x98, 0x80, 0xfe, 0x19,
12312 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18,
12313 0xfe, 0x44, 0x54, 0xbe,
12314 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
12315 0x02, 0x4a, 0x08, 0x05,
12316 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e,
12317 0x9c, 0x3c, 0xfe, 0x6c,
12318 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f,
12319 0x3b, 0x40, 0x03, 0x49,
12320 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
12321 0x8f, 0xfe, 0xe3, 0x54,
12322 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe,
12323 0xda, 0x09, 0xfe, 0x8b,
12324 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa,
12325 0x0a, 0x3a, 0x49, 0x3b,
12326 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
12327 0xad, 0xfe, 0x01, 0x59,
12328 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a,
12329 0x49, 0x8f, 0xfe, 0xe3,
12330 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02,
12331 0x4a, 0x3a, 0x49, 0x3b,
12332 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
12333 0x02, 0x4a, 0x08, 0x05,
12334 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62,
12335 0xb7, 0xfe, 0x03, 0xa1,
12336 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
12337 0xfe, 0x86, 0x91, 0x6a,
12338 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
12339 0x61, 0x0c, 0x7f, 0x14,
12340 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62,
12341 0x9b, 0x2e, 0x9c, 0x3c,
12342 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05,
12343 0xfa, 0x3c, 0x01, 0xef,
12344 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
12345 0xe4, 0x08, 0x05, 0x1f,
12346 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37,
12347 0x03, 0x5e, 0x29, 0x5f,
12348 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe,
12349 0xf4, 0x09, 0x08, 0x05,
12350 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
12351 0x81, 0x50, 0xfe, 0x10,
12352 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe,
12353 0x08, 0x09, 0x12, 0xa6,
12354 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe,
12355 0x08, 0x09, 0xfe, 0x0c,
12356 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
12357 0x08, 0x05, 0x0a, 0xfe,
12358 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1,
12359 0xf0, 0xe2, 0x15, 0x7e,
12360 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19,
12361 0x57, 0x3d, 0xfe, 0xed,
12362 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
12363 0x00, 0xff, 0x35, 0xfe,
12364 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18,
12365 0x1e, 0x19, 0x8a, 0x03,
12366 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65,
12367 0xfe, 0xd1, 0xf0, 0xfe,
12368 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
12369 0x10, 0xfe, 0xce, 0xf0,
12370 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b,
12371 0x10, 0xfe, 0x22, 0x00,
12372 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00,
12373 0x02, 0x65, 0xfe, 0xd0,
12374 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
12375 0x0b, 0x10, 0x58, 0xfe,
12376 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe,
12377 0x12, 0x00, 0x2c, 0x0f,
12378 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14,
12379 0x0c, 0xbc, 0x17, 0x34,
12380 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
12381 0x0c, 0x1c, 0x34, 0x94,
12382 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01,
12383 0x4b, 0xfe, 0xdb, 0x10,
12384 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe,
12385 0x89, 0xf0, 0x24, 0x33,
12386 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
12387 0x33, 0x31, 0xdf, 0xbc,
12388 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49,
12389 0x17, 0xfe, 0x2c, 0x0d,
12390 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54,
12391 0x12, 0x55, 0xfe, 0x28,
12392 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
12393 0x44, 0xfe, 0x28, 0x00,
12394 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26,
12395 0x0f, 0x64, 0x12, 0x2f,
12396 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44,
12397 0x0a, 0xfe, 0xb4, 0x10,
12398 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
12399 0xfe, 0x34, 0x46, 0xac,
12400 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a,
12401 0x37, 0x01, 0xf5, 0x01,
12402 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02,
12403 0xfe, 0x2e, 0x03, 0x08,
12404 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
12405 0x1a, 0xfe, 0x58, 0x12,
12406 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
12407 0xfe, 0x50, 0x0d, 0xfe,
12408 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37,
12409 0xfe, 0xa9, 0x10, 0x10,
12410 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
12411 0xfe, 0x13, 0x00, 0xfe,
12412 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe,
12413 0x24, 0x00, 0x8c, 0xb5,
12414 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a,
12415 0xfe, 0x9d, 0x41, 0xfe,
12416 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
12417 0xb4, 0x15, 0xfe, 0x31,
12418 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06,
12419 0xec, 0xd0, 0xfc, 0x44,
12420 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47,
12421 0x4b, 0x91, 0xfe, 0x75,
12422 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
12423 0x0e, 0xfe, 0x44, 0x48,
12424 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41,
12425 0xfe, 0x41, 0x58, 0x09,
12426 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe,
12427 0x2e, 0x03, 0x09, 0x5d,
12428 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
12429 0xce, 0x47, 0xfe, 0xad,
12430 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13,
12431 0x59, 0x13, 0x9f, 0x13,
12432 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe,
12433 0xe0, 0x0e, 0x0f, 0x06,
12434 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
12435 0x3a, 0x01, 0x56, 0xfe,
12436 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec,
12437 0x20, 0x4f, 0xfe, 0x05,
12438 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe,
12439 0x48, 0xf4, 0x0d, 0xfe,
12440 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
12441 0x15, 0x1a, 0x39, 0xa0,
12442 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff,
12443 0x0c, 0xfe, 0x60, 0x01,
12444 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25,
12445 0x06, 0x13, 0x2f, 0x12,
12446 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
12447 0x22, 0x9f, 0xb7, 0x13,
12448 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39,
12449 0xa0, 0xb4, 0xfe, 0xd9,
12450 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04,
12451 0xc3, 0xfe, 0x03, 0xdc,
12452 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
12453 0xfe, 0x00, 0xcc, 0x04,
12454 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13,
12455 0xfe, 0x1c, 0x80, 0x07,
12456 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae,
12457 0xfe, 0x0c, 0x90, 0xfe,
12458 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
12459 0x0a, 0xfe, 0x3c, 0x50,
12460 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4,
12461 0x16, 0x08, 0x05, 0x1b,
12462 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58,
12463 0xfe, 0x2c, 0x13, 0x01,
12464 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
12465 0x0c, 0xfe, 0x64, 0x01,
12466 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03,
12467 0x80, 0x8d, 0xfe, 0x01,
12468 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64,
12469 0x22, 0x20, 0xfb, 0x79,
12470 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
12471 0x03, 0xfe, 0xae, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012472
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012473 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe,
12474 0xb2, 0x00, 0xfe, 0x09,
12475 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c,
12476 0x45, 0x0f, 0x46, 0x52,
12477 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
12478 0x0f, 0x44, 0x11, 0x0f,
12479 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4,
12480 0x25, 0x11, 0x13, 0x20,
12481 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14,
12482 0x56, 0xfe, 0xd6, 0xf0,
12483 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
12484 0x18, 0x1c, 0x04, 0x42,
12485 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe,
12486 0xf5, 0x13, 0x04, 0x01,
12487 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
12488 0x13, 0x32, 0x07, 0x2f,
12489 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
12490 0x41, 0x48, 0xfe, 0x45,
12491 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78,
12492 0x07, 0x11, 0xac, 0x09,
12493 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07,
12494 0x82, 0x4e, 0xfe, 0x14,
12495 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
12496 0xfe, 0x01, 0xec, 0xa2,
12497 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79,
12498 0x2a, 0x01, 0xe3, 0xfe,
12499 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a,
12500 0xfe, 0x48, 0x12, 0x07,
12501 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
12502 0xfe, 0x32, 0x12, 0x07,
12503 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07,
12504 0x1f, 0xfe, 0x12, 0x12,
12505 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b,
12506 0x94, 0x4b, 0x04, 0x2d,
12507 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
12508 0x32, 0x07, 0xa6, 0xfe,
12509 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05,
12510 0x5a, 0xfe, 0x72, 0x12,
12511 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62,
12512 0xfe, 0x26, 0x13, 0x03,
12513 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
12514 0x0c, 0x7f, 0x0c, 0x80,
12515 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c,
12516 0x3c, 0xfe, 0x04, 0x55,
12517 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe,
12518 0x91, 0x10, 0x03, 0x3f,
12519 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
12520 0x88, 0x9b, 0x2e, 0x9c,
12521 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
12522 0x56, 0x0c, 0x5e, 0x14,
12523 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40,
12524 0x03, 0x60, 0x29, 0x61,
12525 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
12526 0x50, 0xfe, 0xc6, 0x50,
12527 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d,
12528 0x29, 0x3e, 0xfe, 0x40,
12529 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72,
12530 0x2d, 0x01, 0x0b, 0x1d,
12531 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
12532 0x72, 0x01, 0xaf, 0x1e,
12533 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe,
12534 0x0a, 0x55, 0x35, 0xfe,
12535 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51,
12536 0x02, 0x72, 0xfe, 0x19,
12537 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
12538 0x1d, 0xe8, 0x33, 0x31,
12539 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01,
12540 0x0b, 0x1c, 0x34, 0x1d,
12541 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8,
12542 0x33, 0x31, 0xfe, 0xe8,
12543 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
12544 0x05, 0x1f, 0x35, 0xa9,
12545 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda,
12546 0x14, 0x01, 0xaf, 0x8c,
12547 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a,
12548 0x03, 0x45, 0x28, 0x35,
12549 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
12550 0x03, 0x5c, 0xc1, 0x0c,
12551 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02,
12552 0x89, 0x01, 0x0b, 0x1c,
12553 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1,
12554 0xfe, 0x42, 0x58, 0xf1,
12555 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
12556 0xf4, 0x06, 0xea, 0x32,
12557 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d,
12558 0x01, 0x0b, 0x26, 0x89,
12559 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13,
12560 0x26, 0xfe, 0xd4, 0x13,
12561 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
12562 0x13, 0x1c, 0xfe, 0xd0,
12563 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10,
12564 0x0f, 0x71, 0xff, 0x02,
12565 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe,
12566 0x00, 0x5c, 0x04, 0x0f,
12567 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
12568 0xfe, 0x00, 0x5c, 0x04,
12569 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff,
12570 0x02, 0x00, 0x57, 0x52,
12571 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01,
12572 0x87, 0x04, 0xfe, 0x03,
12573 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
12574 0xfe, 0x00, 0x7d, 0xfe,
12575 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e,
12576 0x14, 0x5f, 0x57, 0x3f,
12577 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83,
12578 0x5a, 0x8d, 0x04, 0x01,
12579 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
12580 0xfe, 0x96, 0x15, 0x33,
12581 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8,
12582 0x0a, 0xfe, 0xc1, 0x59,
12583 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13,
12584 0x21, 0x69, 0x1a, 0xee,
12585 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
12586 0x30, 0xfe, 0x78, 0x10,
12587 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae,
12588 0x98, 0xfe, 0x30, 0x00,
12589 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed,
12590 0x98, 0xfe, 0x64, 0x00,
12591 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
12592 0x10, 0x69, 0x06, 0xfe,
12593 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00,
12594 0x18, 0x59, 0x0f, 0x06,
12595 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe,
12596 0x43, 0xf4, 0x9f, 0xfe,
12597 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
12598 0x9e, 0xfe, 0xf3, 0x10,
12599 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00,
12600 0x17, 0xfe, 0x4d, 0xe4,
12601 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00,
12602 0x17, 0xfe, 0x4d, 0xe4,
12603 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
12604 0xf4, 0x00, 0xe9, 0x91,
12605 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a,
12606 0x04, 0x16, 0x06, 0x01,
12607 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01,
12608 0x0b, 0x26, 0xf3, 0x76,
12609 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
12610 0x16, 0x19, 0x01, 0x0b,
12611 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01,
12612 0x0b, 0x26, 0xb1, 0x76,
12613 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06,
12614 0xfe, 0x48, 0x13, 0xb8,
12615 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
12616 0xec, 0xfe, 0x27, 0x01,
12617 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32,
12618 0x07, 0xfe, 0xe3, 0x00,
12619 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b,
12620 0x22, 0xd4, 0x07, 0x06,
12621 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
12622 0x07, 0x11, 0xae, 0x09,
12623 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01,
12624 0x0e, 0x8e, 0xfe, 0x80,
12625 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04,
12626 0x09, 0x48, 0x01, 0x0e,
12627 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
12628 0x80, 0xfe, 0x80, 0x4c,
12629 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c,
12630 0x09, 0x5d, 0x01, 0x87,
12631 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe,
12632 0x19, 0xde, 0xfe, 0x24,
12633 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
12634 0x17, 0xad, 0x9a, 0x1b,
12635 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde,
12636 0x16, 0xfe, 0xda, 0x10,
12637 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe,
12638 0x18, 0x58, 0x03, 0xfe,
12639 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
12640 0xf4, 0x06, 0xfe, 0x3c,
12641 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f,
12642 0x97, 0xfe, 0x38, 0x17,
12643 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c,
12644 0x10, 0x18, 0x11, 0x75,
12645 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
12646 0x2e, 0x97, 0xfe, 0x5a,
12647 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19,
12648 0xfe, 0x98, 0xe7, 0x00,
12649 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75,
12650 0xfe, 0x30, 0xbc, 0xfe,
12651 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
12652 0xcb, 0x97, 0xfe, 0x92,
12653 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe,
12654 0x42, 0x10, 0xfe, 0x02,
12655 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe,
12656 0x03, 0xa1, 0xfe, 0x1d,
12657 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
12658 0x9a, 0x5b, 0x41, 0xfe,
12659 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7,
12660 0x11, 0x12, 0xfe, 0xdd,
12661 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8,
12662 0x17, 0x15, 0x06, 0x39,
12663 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
12664 0xfe, 0x7e, 0x18, 0x1e,
12665 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef,
12666 0x12, 0xfe, 0xe1, 0x10,
12667 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42,
12668 0x13, 0x42, 0x92, 0x09,
12669 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
12670 0xf0, 0xfe, 0x00, 0xcc,
12671 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01,
12672 0x0e, 0xfe, 0x80, 0x4c,
12673 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe,
12674 0x24, 0x12, 0xfe, 0x14,
12675 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
12676 0xe7, 0x0a, 0x10, 0xfe,
12677 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92,
12678 0x08, 0x54, 0x1b, 0x37,
12679 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba,
12680 0x90, 0x3a, 0xce, 0x3b,
12681 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
12682 0x13, 0xa3, 0x04, 0x09,
12683 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49,
12684 0x44, 0x17, 0xfe, 0xe8,
12685 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09,
12686 0x5d, 0x01, 0xa8, 0x09,
12687 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
12688 0x1c, 0x19, 0x03, 0xfe,
12689 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9,
12690 0x6b, 0xfe, 0x2e, 0x19,
12691 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4,
12692 0xfe, 0x0b, 0x00, 0x6b,
12693 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
12694 0x08, 0x10, 0x03, 0xfe,
12695 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff,
12696 0x04, 0x68, 0x54, 0xe7,
12697 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe,
12698 0x1a, 0xf4, 0xfe, 0x00,
12699 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
12700 0x04, 0x07, 0x7e, 0xfe,
12701 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
12702 0x07, 0x1a, 0xfe, 0x5a,
12703 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66,
12704 0x25, 0x6d, 0xe5, 0x07,
12705 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
12706 0xa9, 0xb8, 0x04, 0x15,
12707 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe,
12708 0x40, 0x5c, 0x04, 0x1c,
12709 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b,
12710 0xf7, 0xfe, 0x82, 0xf0,
12711 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070012712};
12713
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012714static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
12715static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012716
12717/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012718static unsigned char _adv_asc38C1600_buf[] = {
12719 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
12720 0x18, 0xe4, 0x01, 0x00,
12721 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00,
12722 0x07, 0x17, 0xc0, 0x5f,
12723 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7,
12724 0x85, 0xf0, 0x86, 0xf0,
12725 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
12726 0x98, 0x57, 0x01, 0xe6,
12727 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d,
12728 0x38, 0x54, 0x32, 0xf0,
12729 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4,
12730 0x00, 0xe6, 0xb1, 0xf0,
12731 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
12732 0x06, 0x13, 0x0c, 0x1c,
12733 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12,
12734 0xb9, 0x54, 0x00, 0x80,
12735 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56,
12736 0x03, 0xe6, 0x01, 0xea,
12737 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
12738 0x04, 0x13, 0xbb, 0x55,
12739 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00,
12740 0xbb, 0x00, 0xc0, 0x00,
12741 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12,
12742 0x4c, 0x1c, 0x4e, 0x1c,
12743 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
12744 0x24, 0x01, 0x3c, 0x01,
12745 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01,
12746 0x78, 0x01, 0x7c, 0x01,
12747 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c,
12748 0x6e, 0x1e, 0x02, 0x48,
12749 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
12750 0x03, 0xfc, 0x06, 0x00,
12751 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a,
12752 0x30, 0x1c, 0x38, 0x1c,
12753 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea,
12754 0x5d, 0xf0, 0xa7, 0xf0,
12755 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
12756 0x33, 0x00, 0x34, 0x00,
12757 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01,
12758 0x79, 0x01, 0x3c, 0x09,
12759 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13,
12760 0x40, 0x16, 0x50, 0x16,
12761 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
12762 0x05, 0xf0, 0x09, 0xf0,
12763 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00,
12764 0x9c, 0x00, 0xa4, 0x00,
12765 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08,
12766 0xe9, 0x09, 0x5c, 0x0c,
12767 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
12768 0x42, 0x1d, 0x08, 0x44,
12769 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54,
12770 0x83, 0x55, 0x83, 0x59,
12771 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0,
12772 0x4b, 0xf4, 0x04, 0xf8,
12773 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
12774 0xa8, 0x00, 0xaa, 0x00,
12775 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01,
12776 0x7a, 0x01, 0x82, 0x01,
12777 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07,
12778 0x68, 0x08, 0x10, 0x0d,
12779 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
12780 0xf3, 0x10, 0x06, 0x12,
12781 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c,
12782 0xf0, 0x35, 0x05, 0xfe,
12783 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8,
12784 0xfe, 0x88, 0x01, 0xff,
12785 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
12786 0x00, 0xfe, 0x57, 0x24,
12787 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09,
12788 0x00, 0x00, 0xff, 0x08,
12789 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
12790 0xff, 0xff, 0xff, 0x13,
12791 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
12792 0xfe, 0x04, 0xf7, 0xe8,
12793 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d,
12794 0x0d, 0x51, 0x37, 0xfe,
12795 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0,
12796 0xfe, 0xf8, 0x01, 0xfe,
12797 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
12798 0x05, 0xfe, 0x08, 0x0f,
12799 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe,
12800 0x28, 0x1c, 0x03, 0xfe,
12801 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe,
12802 0x48, 0xf0, 0xfe, 0x90,
12803 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
12804 0x02, 0xfe, 0x46, 0xf0,
12805 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0,
12806 0xfe, 0x4e, 0x02, 0xfe,
12807 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c,
12808 0x0d, 0xa2, 0x1c, 0x07,
12809 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
12810 0x1c, 0xf5, 0xfe, 0x1e,
12811 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc,
12812 0xde, 0x0a, 0x81, 0x01,
12813 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a,
12814 0x81, 0x01, 0x5c, 0xfe,
12815 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
12816 0xfe, 0x58, 0x1c, 0x1c,
12817 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02,
12818 0x2b, 0xfe, 0x9e, 0x02,
12819 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30,
12820 0x00, 0x47, 0xb8, 0x01,
12821 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
12822 0x1a, 0x31, 0xfe, 0x69,
12823 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe,
12824 0x1e, 0x1e, 0x20, 0x2c,
12825 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a,
12826 0x44, 0x15, 0x56, 0x51,
12827 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
12828 0x01, 0x18, 0x09, 0x00,
12829 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01,
12830 0x18, 0xfe, 0xc8, 0x54,
12831 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60,
12832 0xfe, 0x02, 0xe8, 0x30,
12833 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
12834 0xfe, 0xe4, 0x01, 0xfe,
12835 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe,
12836 0x26, 0xf0, 0xfe, 0x66,
12837 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe,
12838 0xef, 0x10, 0xfe, 0x9f,
12839 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
12840 0x70, 0x37, 0xfe, 0x48,
12841 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26,
12842 0x21, 0xb9, 0xc7, 0x20,
12843 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15,
12844 0xe1, 0x2a, 0xeb, 0xfe,
12845 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
12846 0x15, 0xfe, 0xe4, 0x00,
12847 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41,
12848 0xfe, 0x06, 0xf0, 0xfe,
12849 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29,
12850 0x03, 0x81, 0x1e, 0x1b,
12851 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
12852 0xea, 0xfe, 0x46, 0x1c,
12853 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
12854 0xfe, 0x48, 0x1c, 0x75,
12855 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a,
12856 0xe1, 0x01, 0x18, 0x77,
12857 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
12858 0x8f, 0xfe, 0x70, 0x02,
12859 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04,
12860 0x16, 0xfe, 0x4a, 0x04,
12861 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff,
12862 0x02, 0x00, 0x10, 0x01,
12863 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
12864 0xee, 0xfe, 0x4c, 0x44,
12865 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54,
12866 0x7b, 0xec, 0x60, 0x8d,
12867 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01,
12868 0x0c, 0x06, 0x28, 0xfe,
12869 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
12870 0x13, 0x34, 0xfe, 0x4c,
12871 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54,
12872 0x13, 0x01, 0x0c, 0x06,
12873 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06,
12874 0x28, 0xf9, 0x1f, 0x7f,
12875 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
12876 0xfe, 0xa4, 0x0e, 0x05,
12877 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe,
12878 0x9c, 0x93, 0x3a, 0x0b,
12879 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b,
12880 0x7d, 0x1d, 0xfe, 0x46,
12881 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
12882 0xfe, 0x87, 0x83, 0xfe,
12883 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98,
12884 0x13, 0x0f, 0xfe, 0x20,
12885 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84,
12886 0x12, 0x01, 0x38, 0x06,
12887 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
12888 0x05, 0xd0, 0x54, 0x01,
12889 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe,
12890 0x50, 0x12, 0x5e, 0xff,
12891 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02,
12892 0x00, 0x10, 0x2f, 0xfe,
12893 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
12894 0x38, 0xfe, 0x4a, 0xf0,
12895 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe,
12896 0x21, 0x00, 0xf1, 0x2e,
12897 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00,
12898 0x10, 0x2f, 0xfe, 0xd0,
12899 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
12900 0x1c, 0x00, 0x4d, 0x01,
12901 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06,
12902 0x28, 0xfe, 0x24, 0x12,
12903 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe,
12904 0x0d, 0x00, 0x01, 0x42,
12905 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
12906 0x03, 0xb6, 0x1e, 0xfe,
12907 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17,
12908 0xfe, 0x72, 0x06, 0x0a,
12909 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56,
12910 0x19, 0x16, 0xfe, 0x68,
12911 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
12912 0x03, 0x9a, 0x1e, 0xfe,
12913 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12,
12914 0x48, 0xfe, 0x92, 0x06,
12915 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13,
12916 0x58, 0xff, 0x02, 0x00,
12917 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
12918 0xfe, 0xea, 0x06, 0x01,
12919 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16,
12920 0xfe, 0xe0, 0x06, 0x15,
12921 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07,
12922 0x01, 0x84, 0xfe, 0xae,
12923 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
12924 0x1e, 0xfe, 0x1a, 0x12,
12925 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
12926 0x43, 0x48, 0x62, 0x80,
12927 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24,
12928 0x36, 0xfe, 0x02, 0xf6,
12929 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
12930 0xd0, 0x0d, 0x17, 0xfe,
12931 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20,
12932 0x9e, 0x15, 0x82, 0x01,
12933 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58,
12934 0x57, 0x10, 0xe6, 0x05,
12935 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
12936 0xfe, 0x9c, 0x32, 0x5f,
12937 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c,
12938 0xfe, 0x0a, 0xf0, 0xfe,
12939 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08,
12940 0xaf, 0xa0, 0x05, 0x29,
12941 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
12942 0x00, 0x01, 0x08, 0x14,
12943 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08,
12944 0x14, 0x00, 0x05, 0xfe,
12945 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06,
12946 0x12, 0xfe, 0x30, 0x13,
12947 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
12948 0x01, 0x08, 0x14, 0x00,
12949 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a,
12950 0x78, 0x4f, 0x0f, 0xfe,
12951 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d,
12952 0x28, 0x48, 0xfe, 0x6c,
12953 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
12954 0x12, 0x53, 0x63, 0x4e,
12955 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe,
12956 0x6c, 0x08, 0xaf, 0xa0,
12957 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24,
12958 0x05, 0xed, 0xfe, 0x9c,
12959 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
12960 0x1e, 0xfe, 0x99, 0x58,
12961 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a,
12962 0x22, 0x6b, 0x01, 0x0c,
12963 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e,
12964 0x1e, 0x47, 0x2c, 0x7a,
12965 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
12966 0x01, 0x0c, 0x61, 0x65,
12967 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a,
12968 0x16, 0xfe, 0x08, 0x50,
12969 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10,
12970 0x01, 0xfe, 0xce, 0x1e,
12971 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
12972 0x01, 0xfe, 0xfe, 0x1e,
12973 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a,
12974 0x10, 0x01, 0x0c, 0x06,
12975 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e,
12976 0x10, 0x6a, 0x22, 0x6b,
12977 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
12978 0xfe, 0x9f, 0x83, 0x33,
12979 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93,
12980 0x3a, 0x0b, 0xfe, 0xc6,
12981 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d,
12982 0x01, 0xfe, 0xce, 0x1e,
12983 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
12984 0x04, 0xfe, 0xc0, 0x93,
12985 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e,
12986 0x10, 0x4b, 0x22, 0x4c,
12987 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe,
12988 0x4e, 0x11, 0x2f, 0xfe,
12989 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
12990 0x3c, 0x37, 0x88, 0xf5,
12991 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a,
12992 0xd3, 0xfe, 0x42, 0x0a,
12993 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0,
12994 0x05, 0x29, 0x01, 0x41,
12995 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
12996 0xfe, 0x14, 0x12, 0x01,
12997 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe,
12998 0x2e, 0x1c, 0x05, 0xfe,
12999 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41,
13000 0xfe, 0x2c, 0x1c, 0xfe,
13001 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
13002 0x92, 0x10, 0xc4, 0xf6,
13003 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe,
13004 0xe7, 0x10, 0xfe, 0x2b,
13005 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12,
13006 0xac, 0xfe, 0xd2, 0xf0,
13007 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
13008 0x1b, 0xbf, 0xd4, 0x5b,
13009 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75,
13010 0x5e, 0x32, 0x1f, 0x7f,
13011 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98,
13012 0x05, 0x70, 0xfe, 0x74,
13013 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
13014 0x0f, 0x4d, 0x01, 0xfe,
13015 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06,
13016 0x0d, 0x2b, 0xfe, 0xe2,
13017 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24,
13018 0xfe, 0x88, 0x13, 0x21,
13019 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
13020 0x83, 0x83, 0xfe, 0xc9,
13021 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04,
13022 0x91, 0x04, 0xfe, 0x84,
13023 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93,
13024 0xfe, 0xcb, 0x57, 0x0b,
13025 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
13026 0x6a, 0x3b, 0x6b, 0x10,
13027 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30,
13028 0x20, 0x6e, 0xdb, 0x64,
13029 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55,
13030 0xfe, 0x04, 0xfa, 0x64,
13031 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
13032 0x10, 0x98, 0x91, 0x6c,
13033 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91,
13034 0x4b, 0x7e, 0x4c, 0x01,
13035 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10,
13036 0x58, 0xfe, 0x91, 0x58,
13037 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
13038 0x1b, 0x40, 0x01, 0x0c,
13039 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f,
13040 0xfe, 0x10, 0x90, 0x04,
13041 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93,
13042 0x79, 0x0b, 0x0e, 0xfe,
13043 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
13044 0x01, 0x0c, 0x06, 0x0d,
13045 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe,
13046 0x0c, 0x58, 0xfe, 0x8d,
13047 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99,
13048 0x83, 0x33, 0x0b, 0x0e,
13049 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
13050 0x19, 0xfe, 0x19, 0x41,
13051 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42,
13052 0x19, 0xfe, 0x44, 0x00,
13053 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda,
13054 0x4c, 0xfe, 0x0c, 0x51,
13055 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
13056 0x76, 0x10, 0xac, 0xfe,
13057 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03,
13058 0xe3, 0x23, 0x07, 0xfe,
13059 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe,
13060 0xcc, 0x0c, 0x1f, 0x92,
13061 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
13062 0x0c, 0xfe, 0x3e, 0x10,
13063 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70,
13064 0xfe, 0xcb, 0xf0, 0xfe,
13065 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe,
13066 0xf4, 0x0c, 0x19, 0x94,
13067 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
13068 0xfe, 0xcc, 0xf0, 0xef,
13069 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe,
13070 0x4e, 0x11, 0x2f, 0xfe,
13071 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b,
13072 0x3c, 0x37, 0x88, 0xf5,
13073 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
13074 0x2f, 0xfe, 0x3e, 0x0d,
13075 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f,
13076 0xd2, 0x9f, 0xd3, 0x9f,
13077 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4,
13078 0xc5, 0x75, 0xd7, 0x99,
13079 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
13080 0x9c, 0x2f, 0xfe, 0x8c,
13081 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe,
13082 0x42, 0x00, 0x05, 0x70,
13083 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06,
13084 0x0d, 0xfe, 0x44, 0x13,
13085 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
13086 0xfe, 0xda, 0x0e, 0x0a,
13087 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa,
13088 0x10, 0x01, 0xfe, 0xf4,
13089 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40,
13090 0x15, 0x56, 0x01, 0x85,
13091 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
13092 0xcc, 0x10, 0x01, 0xa7,
13093 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04,
13094 0xfe, 0x99, 0x83, 0xfe,
13095 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe,
13096 0x43, 0x00, 0xfe, 0xa2,
13097 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
13098 0x00, 0x1d, 0x40, 0x15,
13099 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05,
13100 0xfe, 0x3a, 0x03, 0x01,
13101 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01,
13102 0x76, 0x06, 0x12, 0xfe,
13103 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
13104 0xfe, 0x9d, 0xf0, 0xfe,
13105 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01,
13106 0x0c, 0x61, 0x12, 0x44,
13107 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f,
13108 0xfe, 0x2e, 0x10, 0x19,
13109 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
13110 0xfe, 0x41, 0x00, 0xa2,
13111 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b,
13112 0xea, 0x4f, 0xfe, 0x04,
13113 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05,
13114 0x35, 0xfe, 0x12, 0x1c,
13115 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
13116 0xfe, 0xd4, 0x11, 0x05,
13117 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe,
13118 0xce, 0x45, 0x31, 0x51,
13119 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03,
13120 0x67, 0xfe, 0x98, 0x56,
13121 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
13122 0x0c, 0x06, 0x28, 0xfe,
13123 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba,
13124 0xfe, 0xfa, 0x14, 0xfe,
13125 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67,
13126 0xfe, 0xe0, 0x14, 0xfe,
13127 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
13128 0xfe, 0xad, 0x13, 0x05,
13129 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20,
13130 0xe7, 0xfe, 0x08, 0x1c,
13131 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe,
13132 0x48, 0x55, 0xa5, 0x3b,
13133 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
13134 0xf0, 0x1a, 0x03, 0xfe,
13135 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02,
13136 0xec, 0xe7, 0x53, 0x00,
13137 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
13138 0x01, 0xfe, 0x62, 0x1b,
13139 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
13140 0xea, 0xe7, 0x53, 0x92,
13141 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03,
13142 0xfe, 0x38, 0x01, 0x23,
13143 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62,
13144 0x01, 0x01, 0xfe, 0x1e,
13145 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
13146 0x26, 0x02, 0x21, 0x96,
13147 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5,
13148 0xc3, 0xfe, 0xe1, 0x10,
13149 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf,
13150 0xfe, 0x03, 0xdc, 0xfe,
13151 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
13152 0x00, 0xcc, 0x02, 0xfe,
13153 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13,
13154 0x0f, 0xfe, 0x1c, 0x80,
13155 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13,
13156 0x0f, 0xfe, 0x1e, 0x80,
13157 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
13158 0x1d, 0x80, 0x04, 0xfe,
13159 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee,
13160 0x1e, 0xac, 0xfe, 0x14,
13161 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e,
13162 0x1f, 0xfe, 0x30, 0xf4,
13163 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
13164 0x56, 0xfb, 0x01, 0xfe,
13165 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01,
13166 0xfe, 0x00, 0x1d, 0x15,
13167 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe,
13168 0x22, 0x1b, 0xfe, 0x1e,
13169 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
13170 0x96, 0x90, 0x04, 0xfe,
13171 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66,
13172 0x01, 0x01, 0x0c, 0x06,
13173 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b,
13174 0x0e, 0x77, 0xfe, 0x01,
13175 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
13176 0x21, 0x2c, 0xfe, 0x00,
13177 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe,
13178 0x06, 0x58, 0x03, 0xfe,
13179 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58,
13180 0x03, 0xfe, 0xb2, 0x00,
13181 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
13182 0x66, 0x10, 0x55, 0x10,
13183 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91,
13184 0x54, 0x2b, 0xfe, 0x88,
13185 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe,
13186 0x91, 0x54, 0x2b, 0xfe,
13187 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
13188 0x00, 0x40, 0x8d, 0x2c,
13189 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe,
13190 0x12, 0x1c, 0x75, 0xfe,
13191 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c,
13192 0x14, 0xfe, 0x0e, 0x47,
13193 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
13194 0xa7, 0x90, 0x34, 0x60,
13195 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80,
13196 0x09, 0x56, 0xfe, 0x34,
13197 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48,
13198 0xfe, 0x45, 0x48, 0x01,
13199 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
13200 0x09, 0x1a, 0xa5, 0x0a,
13201 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4,
13202 0xfe, 0x14, 0x56, 0xfe,
13203 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01,
13204 0xec, 0xb8, 0xfe, 0x9e,
13205 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
13206 0xf4, 0xfe, 0xdd, 0x10,
13207 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48,
13208 0x12, 0x09, 0x0d, 0xfe,
13209 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4,
13210 0x13, 0x09, 0xfe, 0x23,
13211 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
13212 0x24, 0xfe, 0x12, 0x12,
13213 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08,
13214 0xae, 0x41, 0x02, 0x32,
13215 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05,
13216 0x35, 0x32, 0x01, 0x43,
13217 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
13218 0x13, 0x01, 0x0c, 0x06,
13219 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe,
13220 0xe5, 0x55, 0xb0, 0xfe,
13221 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e,
13222 0xfe, 0xb6, 0x0e, 0x10,
13223 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
13224 0x88, 0x20, 0x6e, 0x01,
13225 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5,
13226 0x55, 0xfe, 0x04, 0xfa,
13227 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d,
13228 0xfe, 0x40, 0x56, 0xfe,
13229 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
13230 0x44, 0x55, 0xfe, 0xe5,
13231 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10,
13232 0x68, 0x22, 0x69, 0x01,
13233 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b,
13234 0x6b, 0xfe, 0x2c, 0x50,
13235 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
13236 0x50, 0x03, 0x68, 0x3b,
13237 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe,
13238 0x40, 0x50, 0xfe, 0xc2,
13239 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08,
13240 0x16, 0x3d, 0x27, 0x25,
13241 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
13242 0xa6, 0x23, 0x3f, 0x1b,
13243 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c,
13244 0xfe, 0x0a, 0x55, 0x31,
13245 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e,
13246 0x51, 0x05, 0x72, 0x01,
13247 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
13248 0x2a, 0x3c, 0x16, 0xc0,
13249 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b,
13250 0xfe, 0x66, 0x15, 0x05,
13251 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d,
13252 0x2b, 0x3d, 0x01, 0x08,
13253 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
13254 0xb6, 0x1e, 0x83, 0x01,
13255 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46,
13256 0x07, 0x90, 0x3f, 0x01,
13257 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13,
13258 0x01, 0x43, 0x09, 0x82,
13259 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
13260 0x05, 0x72, 0xfe, 0xc0,
13261 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e,
13262 0x32, 0x01, 0x08, 0x17,
13263 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16,
13264 0x3d, 0x27, 0x25, 0xbd,
13265 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
13266 0xe8, 0x14, 0x01, 0xa6,
13267 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe,
13268 0x0e, 0x12, 0x01, 0x43,
13269 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32,
13270 0x01, 0x08, 0x17, 0x73,
13271 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
13272 0x27, 0x25, 0xbd, 0x09,
13273 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe,
13274 0xb6, 0x14, 0x86, 0xa8,
13275 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09,
13276 0x82, 0x4e, 0x05, 0x72,
13277 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
13278 0xfe, 0xc0, 0x19, 0x05,
13279 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f,
13280 0xcc, 0x01, 0x08, 0x26,
13281 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe,
13282 0xcc, 0x15, 0x5e, 0x32,
13283 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
13284 0xad, 0x23, 0xfe, 0xff,
13285 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02,
13286 0x00, 0x57, 0x52, 0xad,
13287 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff,
13288 0x02, 0x00, 0x57, 0x52,
13289 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
13290 0x02, 0x13, 0x58, 0xff,
13291 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01,
13292 0x5c, 0x0a, 0x55, 0x01,
13293 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a,
13294 0xff, 0x03, 0x00, 0x54,
13295 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
13296 0x7c, 0x3a, 0x0b, 0x0e,
13297 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19,
13298 0xfe, 0x1a, 0xf7, 0x00,
13299 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c,
13300 0xda, 0x6d, 0x02, 0xfe,
13301 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
13302 0x02, 0x01, 0xc6, 0xfe,
13303 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27,
13304 0x25, 0xbe, 0x01, 0x08,
13305 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59,
13306 0x03, 0x9a, 0x1e, 0xfe,
13307 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
13308 0x48, 0xfe, 0x08, 0x17,
13309 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26,
13310 0x17, 0x4d, 0x13, 0x07,
13311 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1,
13312 0xff, 0x02, 0x83, 0x55,
13313 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
13314 0x17, 0x1c, 0x63, 0x13,
13315 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64,
13316 0x00, 0xb0, 0xfe, 0x80,
13317 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10,
13318 0x53, 0x07, 0xfe, 0x60,
13319 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
13320 0x00, 0x1c, 0x95, 0x13,
13321 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3,
13322 0xfe, 0x43, 0xf4, 0x96,
13323 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43,
13324 0xf4, 0x94, 0xf6, 0x8b,
13325 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
13326 0xda, 0x17, 0x62, 0x49,
13327 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80,
13328 0x71, 0x50, 0x26, 0xfe,
13329 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3,
13330 0x58, 0x02, 0x50, 0x13,
13331 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
13332 0x25, 0xbe, 0xfe, 0x03,
13333 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9,
13334 0x0a, 0x01, 0x08, 0x16,
13335 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01,
13336 0x01, 0x08, 0x16, 0xa9,
13337 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
13338 0x08, 0x16, 0xa9, 0x27,
13339 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83,
13340 0x01, 0x38, 0x06, 0x24,
13341 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1,
13342 0x78, 0x03, 0x9a, 0x1e,
13343 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
13344 0xfe, 0x40, 0x5a, 0x23,
13345 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c,
13346 0x80, 0x48, 0xfe, 0xaa,
13347 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01,
13348 0xfe, 0xac, 0x1d, 0xfe,
13349 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
13350 0x43, 0x48, 0x2d, 0x93,
13351 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4,
13352 0x36, 0xfe, 0x34, 0xf4,
13353 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe,
13354 0x28, 0x10, 0xfe, 0xc0,
13355 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
13356 0x18, 0x45, 0xfe, 0x1c,
13357 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c,
13358 0x19, 0xfe, 0x04, 0xf4,
13359 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d,
13360 0x21, 0xfe, 0x7f, 0x01,
13361 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
13362 0x7e, 0x01, 0xfe, 0xc8,
13363 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa,
13364 0x21, 0xfe, 0x81, 0x01,
13365 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50,
13366 0x13, 0x0d, 0x02, 0x14,
13367 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
13368 0xfe, 0x82, 0x19, 0x14,
13369 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01,
13370 0x08, 0x02, 0x14, 0x07,
13371 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07,
13372 0x01, 0x08, 0x17, 0xc1,
13373 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
13374 0x08, 0x02, 0x50, 0x02,
13375 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74,
13376 0x14, 0x12, 0x01, 0x08,
13377 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01,
13378 0x08, 0x17, 0x74, 0xfe,
13379 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
13380 0x74, 0x5f, 0xcc, 0x01,
13381 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4,
13382 0xfe, 0x49, 0xf4, 0x00,
13383 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff,
13384 0x02, 0x00, 0x10, 0x2f,
13385 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
13386 0x16, 0xfe, 0x64, 0x1a,
13387 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c,
13388 0x61, 0x07, 0x44, 0x02,
13389 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12,
13390 0x13, 0x0a, 0x9d, 0x01,
13391 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
13392 0xfe, 0x80, 0xe7, 0x1a,
13393 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02,
13394 0x0a, 0x5a, 0x01, 0x18,
13395 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe,
13396 0x7e, 0x1e, 0xfe, 0x80,
13397 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
13398 0xfe, 0x80, 0x4c, 0x0a,
13399 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf,
13400 0xfe, 0x19, 0xde, 0xfe,
13401 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe,
13402 0x2a, 0x1c, 0xfa, 0xb3,
13403 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
13404 0xf4, 0x1a, 0xfe, 0xfa,
13405 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24,
13406 0xfe, 0x18, 0x58, 0x03,
13407 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f,
13408 0xfe, 0x30, 0xf4, 0x07,
13409 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
13410 0xf7, 0x24, 0xb1, 0xfe,
13411 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b,
13412 0xfe, 0xba, 0x10, 0x1c,
13413 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
13414 0x1d, 0xf7, 0x54, 0xb1,
13415 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
13416 0xaf, 0x19, 0xfe, 0x98,
13417 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c,
13418 0x1a, 0x87, 0x8b, 0x0f,
13419 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58,
13420 0xfe, 0x32, 0x90, 0x04,
13421 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
13422 0x7c, 0x12, 0xfe, 0x0f,
13423 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14,
13424 0x31, 0x02, 0xc9, 0x2b,
13425 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe,
13426 0x6a, 0xfe, 0x19, 0xfe,
13427 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
13428 0x1b, 0xfe, 0x36, 0x14,
13429 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19,
13430 0xfe, 0x80, 0xe7, 0x1a,
13431 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a,
13432 0x30, 0xfe, 0x12, 0x45,
13433 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
13434 0x39, 0xf0, 0x75, 0x26,
13435 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03,
13436 0xe3, 0x23, 0x07, 0xfe,
13437 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09,
13438 0x56, 0xfe, 0x3c, 0x13,
13439 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
13440 0x01, 0x18, 0xcb, 0xfe,
13441 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16,
13442 0xfe, 0x00, 0xcc, 0xcb,
13443 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18,
13444 0xfe, 0x80, 0x4c, 0x01,
13445 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
13446 0x12, 0xfe, 0x14, 0x56,
13447 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7,
13448 0x0d, 0x19, 0xfe, 0x15,
13449 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06,
13450 0x83, 0xfe, 0x18, 0x80,
13451 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
13452 0x90, 0xfe, 0xba, 0x90,
13453 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02,
13454 0x21, 0xb9, 0x88, 0x20,
13455 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01,
13456 0x18, 0xfe, 0x49, 0x44,
13457 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
13458 0x1a, 0xa4, 0x0a, 0x67,
13459 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4,
13460 0x1d, 0x7b, 0xfe, 0x52,
13461 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe,
13462 0x4e, 0xe4, 0xdd, 0x7b,
13463 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
13464 0xfe, 0x4e, 0xe4, 0xfe,
13465 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24,
13466 0xfe, 0x08, 0x10, 0x03,
13467 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04,
13468 0x68, 0x54, 0xfe, 0xf1,
13469 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
13470 0xfe, 0x1a, 0xf4, 0xfe,
13471 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02,
13472 0x09, 0x92, 0xfe, 0x5a,
13473 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe,
13474 0x5a, 0xf0, 0xfe, 0xc8,
13475 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
13476 0x1a, 0x10, 0x09, 0x0d,
13477 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02,
13478 0x1f, 0x93, 0x01, 0x42,
13479 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e,
13480 0xfe, 0x14, 0xf0, 0x08,
13481 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
13482 0xfe, 0x82, 0xf0, 0xfe,
13483 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e,
13484 0x02, 0x0f, 0xfe, 0x18,
13485 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02,
13486 0x80, 0x04, 0xfe, 0x82,
13487 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
13488 0x83, 0x33, 0x0b, 0x0e,
13489 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e,
13490 0x02, 0x0f, 0xfe, 0x04,
13491 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80,
13492 0x80, 0x04, 0xfe, 0x80,
13493 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
13494 0xfe, 0x99, 0x83, 0xfe,
13495 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86,
13496 0x83, 0xfe, 0xce, 0x47,
13497 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a,
13498 0x0b, 0x0e, 0x02, 0x0f,
13499 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
13500 0xfe, 0x08, 0x90, 0x04,
13501 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04,
13502 0xfe, 0x8a, 0x93, 0x79,
13503 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a,
13504 0x0b, 0x0e, 0x02, 0x0f,
13505 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
13506 0xfe, 0x3c, 0x90, 0x04,
13507 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80,
13508 0x04, 0xfe, 0x83, 0x83,
13509 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070013510};
13511
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013512static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
13513static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013514
13515/* a_init.c */
13516/*
13517 * EEPROM Configuration.
13518 *
13519 * All drivers should use this structure to set the default EEPROM
13520 * configuration. The BIOS now uses this structure when it is built.
13521 * Additional structure information can be found in a_condor.h where
13522 * the structure is defined.
13523 *
13524 * The *_Field_IsChar structs are needed to correct for endianness.
13525 * These values are read from the board 16 bits at a time directly
13526 * into the structs. Because some fields are char, the values will be
13527 * in the wrong order. The *_Field_IsChar tells when to flip the
13528 * bytes. Data read and written to PCI memory is automatically swapped
13529 * on big-endian platforms so char fields read as words are actually being
13530 * unswapped on big-endian platforms.
13531 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013532static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013533 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
13534 0x0000, /* cfg_msw */
13535 0xFFFF, /* disc_enable */
13536 0xFFFF, /* wdtr_able */
13537 0xFFFF, /* sdtr_able */
13538 0xFFFF, /* start_motor */
13539 0xFFFF, /* tagqng_able */
13540 0xFFFF, /* bios_scan */
13541 0, /* scam_tolerant */
13542 7, /* adapter_scsi_id */
13543 0, /* bios_boot_delay */
13544 3, /* scsi_reset_delay */
13545 0, /* bios_id_lun */
13546 0, /* termination */
13547 0, /* reserved1 */
13548 0xFFE7, /* bios_ctrl */
13549 0xFFFF, /* ultra_able */
13550 0, /* reserved2 */
13551 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
13552 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13553 0, /* dvc_cntl */
13554 0, /* bug_fix */
13555 0, /* serial_number_word1 */
13556 0, /* serial_number_word2 */
13557 0, /* serial_number_word3 */
13558 0, /* check_sum */
13559 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13560 , /* oem_name[16] */
13561 0, /* dvc_err_code */
13562 0, /* adv_err_code */
13563 0, /* adv_err_addr */
13564 0, /* saved_dvc_err_code */
13565 0, /* saved_adv_err_code */
13566 0, /* saved_adv_err_addr */
13567 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013568};
13569
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013570static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013571 0, /* cfg_lsw */
13572 0, /* cfg_msw */
13573 0, /* -disc_enable */
13574 0, /* wdtr_able */
13575 0, /* sdtr_able */
13576 0, /* start_motor */
13577 0, /* tagqng_able */
13578 0, /* bios_scan */
13579 0, /* scam_tolerant */
13580 1, /* adapter_scsi_id */
13581 1, /* bios_boot_delay */
13582 1, /* scsi_reset_delay */
13583 1, /* bios_id_lun */
13584 1, /* termination */
13585 1, /* reserved1 */
13586 0, /* bios_ctrl */
13587 0, /* ultra_able */
13588 0, /* reserved2 */
13589 1, /* max_host_qng */
13590 1, /* max_dvc_qng */
13591 0, /* dvc_cntl */
13592 0, /* bug_fix */
13593 0, /* serial_number_word1 */
13594 0, /* serial_number_word2 */
13595 0, /* serial_number_word3 */
13596 0, /* check_sum */
13597 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13598 , /* oem_name[16] */
13599 0, /* dvc_err_code */
13600 0, /* adv_err_code */
13601 0, /* adv_err_addr */
13602 0, /* saved_dvc_err_code */
13603 0, /* saved_adv_err_code */
13604 0, /* saved_adv_err_addr */
13605 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013606};
13607
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013608static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013609 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
13610 0x0000, /* 01 cfg_msw */
13611 0xFFFF, /* 02 disc_enable */
13612 0xFFFF, /* 03 wdtr_able */
13613 0x4444, /* 04 sdtr_speed1 */
13614 0xFFFF, /* 05 start_motor */
13615 0xFFFF, /* 06 tagqng_able */
13616 0xFFFF, /* 07 bios_scan */
13617 0, /* 08 scam_tolerant */
13618 7, /* 09 adapter_scsi_id */
13619 0, /* bios_boot_delay */
13620 3, /* 10 scsi_reset_delay */
13621 0, /* bios_id_lun */
13622 0, /* 11 termination_se */
13623 0, /* termination_lvd */
13624 0xFFE7, /* 12 bios_ctrl */
13625 0x4444, /* 13 sdtr_speed2 */
13626 0x4444, /* 14 sdtr_speed3 */
13627 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
13628 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13629 0, /* 16 dvc_cntl */
13630 0x4444, /* 17 sdtr_speed4 */
13631 0, /* 18 serial_number_word1 */
13632 0, /* 19 serial_number_word2 */
13633 0, /* 20 serial_number_word3 */
13634 0, /* 21 check_sum */
13635 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13636 , /* 22-29 oem_name[16] */
13637 0, /* 30 dvc_err_code */
13638 0, /* 31 adv_err_code */
13639 0, /* 32 adv_err_addr */
13640 0, /* 33 saved_dvc_err_code */
13641 0, /* 34 saved_adv_err_code */
13642 0, /* 35 saved_adv_err_addr */
13643 0, /* 36 reserved */
13644 0, /* 37 reserved */
13645 0, /* 38 reserved */
13646 0, /* 39 reserved */
13647 0, /* 40 reserved */
13648 0, /* 41 reserved */
13649 0, /* 42 reserved */
13650 0, /* 43 reserved */
13651 0, /* 44 reserved */
13652 0, /* 45 reserved */
13653 0, /* 46 reserved */
13654 0, /* 47 reserved */
13655 0, /* 48 reserved */
13656 0, /* 49 reserved */
13657 0, /* 50 reserved */
13658 0, /* 51 reserved */
13659 0, /* 52 reserved */
13660 0, /* 53 reserved */
13661 0, /* 54 reserved */
13662 0, /* 55 reserved */
13663 0, /* 56 cisptr_lsw */
13664 0, /* 57 cisprt_msw */
13665 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
13666 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
13667 0, /* 60 reserved */
13668 0, /* 61 reserved */
13669 0, /* 62 reserved */
13670 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013671};
13672
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013673static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013674 0, /* 00 cfg_lsw */
13675 0, /* 01 cfg_msw */
13676 0, /* 02 disc_enable */
13677 0, /* 03 wdtr_able */
13678 0, /* 04 sdtr_speed1 */
13679 0, /* 05 start_motor */
13680 0, /* 06 tagqng_able */
13681 0, /* 07 bios_scan */
13682 0, /* 08 scam_tolerant */
13683 1, /* 09 adapter_scsi_id */
13684 1, /* bios_boot_delay */
13685 1, /* 10 scsi_reset_delay */
13686 1, /* bios_id_lun */
13687 1, /* 11 termination_se */
13688 1, /* termination_lvd */
13689 0, /* 12 bios_ctrl */
13690 0, /* 13 sdtr_speed2 */
13691 0, /* 14 sdtr_speed3 */
13692 1, /* 15 max_host_qng */
13693 1, /* max_dvc_qng */
13694 0, /* 16 dvc_cntl */
13695 0, /* 17 sdtr_speed4 */
13696 0, /* 18 serial_number_word1 */
13697 0, /* 19 serial_number_word2 */
13698 0, /* 20 serial_number_word3 */
13699 0, /* 21 check_sum */
13700 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13701 , /* 22-29 oem_name[16] */
13702 0, /* 30 dvc_err_code */
13703 0, /* 31 adv_err_code */
13704 0, /* 32 adv_err_addr */
13705 0, /* 33 saved_dvc_err_code */
13706 0, /* 34 saved_adv_err_code */
13707 0, /* 35 saved_adv_err_addr */
13708 0, /* 36 reserved */
13709 0, /* 37 reserved */
13710 0, /* 38 reserved */
13711 0, /* 39 reserved */
13712 0, /* 40 reserved */
13713 0, /* 41 reserved */
13714 0, /* 42 reserved */
13715 0, /* 43 reserved */
13716 0, /* 44 reserved */
13717 0, /* 45 reserved */
13718 0, /* 46 reserved */
13719 0, /* 47 reserved */
13720 0, /* 48 reserved */
13721 0, /* 49 reserved */
13722 0, /* 50 reserved */
13723 0, /* 51 reserved */
13724 0, /* 52 reserved */
13725 0, /* 53 reserved */
13726 0, /* 54 reserved */
13727 0, /* 55 reserved */
13728 0, /* 56 cisptr_lsw */
13729 0, /* 57 cisprt_msw */
13730 0, /* 58 subsysvid */
13731 0, /* 59 subsysid */
13732 0, /* 60 reserved */
13733 0, /* 61 reserved */
13734 0, /* 62 reserved */
13735 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013736};
13737
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013738static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013739 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
13740 0x0000, /* 01 cfg_msw */
13741 0xFFFF, /* 02 disc_enable */
13742 0xFFFF, /* 03 wdtr_able */
13743 0x5555, /* 04 sdtr_speed1 */
13744 0xFFFF, /* 05 start_motor */
13745 0xFFFF, /* 06 tagqng_able */
13746 0xFFFF, /* 07 bios_scan */
13747 0, /* 08 scam_tolerant */
13748 7, /* 09 adapter_scsi_id */
13749 0, /* bios_boot_delay */
13750 3, /* 10 scsi_reset_delay */
13751 0, /* bios_id_lun */
13752 0, /* 11 termination_se */
13753 0, /* termination_lvd */
13754 0xFFE7, /* 12 bios_ctrl */
13755 0x5555, /* 13 sdtr_speed2 */
13756 0x5555, /* 14 sdtr_speed3 */
13757 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
13758 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
13759 0, /* 16 dvc_cntl */
13760 0x5555, /* 17 sdtr_speed4 */
13761 0, /* 18 serial_number_word1 */
13762 0, /* 19 serial_number_word2 */
13763 0, /* 20 serial_number_word3 */
13764 0, /* 21 check_sum */
13765 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
13766 , /* 22-29 oem_name[16] */
13767 0, /* 30 dvc_err_code */
13768 0, /* 31 adv_err_code */
13769 0, /* 32 adv_err_addr */
13770 0, /* 33 saved_dvc_err_code */
13771 0, /* 34 saved_adv_err_code */
13772 0, /* 35 saved_adv_err_addr */
13773 0, /* 36 reserved */
13774 0, /* 37 reserved */
13775 0, /* 38 reserved */
13776 0, /* 39 reserved */
13777 0, /* 40 reserved */
13778 0, /* 41 reserved */
13779 0, /* 42 reserved */
13780 0, /* 43 reserved */
13781 0, /* 44 reserved */
13782 0, /* 45 reserved */
13783 0, /* 46 reserved */
13784 0, /* 47 reserved */
13785 0, /* 48 reserved */
13786 0, /* 49 reserved */
13787 0, /* 50 reserved */
13788 0, /* 51 reserved */
13789 0, /* 52 reserved */
13790 0, /* 53 reserved */
13791 0, /* 54 reserved */
13792 0, /* 55 reserved */
13793 0, /* 56 cisptr_lsw */
13794 0, /* 57 cisprt_msw */
13795 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
13796 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
13797 0, /* 60 reserved */
13798 0, /* 61 reserved */
13799 0, /* 62 reserved */
13800 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013801};
13802
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013803static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013804 0, /* 00 cfg_lsw */
13805 0, /* 01 cfg_msw */
13806 0, /* 02 disc_enable */
13807 0, /* 03 wdtr_able */
13808 0, /* 04 sdtr_speed1 */
13809 0, /* 05 start_motor */
13810 0, /* 06 tagqng_able */
13811 0, /* 07 bios_scan */
13812 0, /* 08 scam_tolerant */
13813 1, /* 09 adapter_scsi_id */
13814 1, /* bios_boot_delay */
13815 1, /* 10 scsi_reset_delay */
13816 1, /* bios_id_lun */
13817 1, /* 11 termination_se */
13818 1, /* termination_lvd */
13819 0, /* 12 bios_ctrl */
13820 0, /* 13 sdtr_speed2 */
13821 0, /* 14 sdtr_speed3 */
13822 1, /* 15 max_host_qng */
13823 1, /* max_dvc_qng */
13824 0, /* 16 dvc_cntl */
13825 0, /* 17 sdtr_speed4 */
13826 0, /* 18 serial_number_word1 */
13827 0, /* 19 serial_number_word2 */
13828 0, /* 20 serial_number_word3 */
13829 0, /* 21 check_sum */
13830 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
13831 , /* 22-29 oem_name[16] */
13832 0, /* 30 dvc_err_code */
13833 0, /* 31 adv_err_code */
13834 0, /* 32 adv_err_addr */
13835 0, /* 33 saved_dvc_err_code */
13836 0, /* 34 saved_adv_err_code */
13837 0, /* 35 saved_adv_err_addr */
13838 0, /* 36 reserved */
13839 0, /* 37 reserved */
13840 0, /* 38 reserved */
13841 0, /* 39 reserved */
13842 0, /* 40 reserved */
13843 0, /* 41 reserved */
13844 0, /* 42 reserved */
13845 0, /* 43 reserved */
13846 0, /* 44 reserved */
13847 0, /* 45 reserved */
13848 0, /* 46 reserved */
13849 0, /* 47 reserved */
13850 0, /* 48 reserved */
13851 0, /* 49 reserved */
13852 0, /* 50 reserved */
13853 0, /* 51 reserved */
13854 0, /* 52 reserved */
13855 0, /* 53 reserved */
13856 0, /* 54 reserved */
13857 0, /* 55 reserved */
13858 0, /* 56 cisptr_lsw */
13859 0, /* 57 cisprt_msw */
13860 0, /* 58 subsysvid */
13861 0, /* 59 subsysid */
13862 0, /* 60 reserved */
13863 0, /* 61 reserved */
13864 0, /* 62 reserved */
13865 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013866};
13867
13868/*
13869 * Initialize the ADV_DVC_VAR structure.
13870 *
13871 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13872 *
13873 * For a non-fatal error return a warning code. If there are no warnings
13874 * then 0 is returned.
13875 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013876static int __devinit AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013877{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013878 ushort warn_code;
13879 AdvPortAddr iop_base;
13880 uchar pci_cmd_reg;
13881 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013882
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013883 warn_code = 0;
13884 asc_dvc->err_code = 0;
13885 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013887 /*
13888 * PCI Command Register
13889 *
13890 * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes
13891 * I/O Space Control, Memory Space Control and Bus Master Control bits.
13892 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013893
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013894 if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
13895 AscPCIConfigCommandRegister))
13896 & AscPCICmdRegBits_BusMastering)
13897 != AscPCICmdRegBits_BusMastering) {
13898 pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013899
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013900 DvcAdvWritePCIConfigByte(asc_dvc,
13901 AscPCIConfigCommandRegister,
13902 pci_cmd_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013903
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013904 if (((DvcAdvReadPCIConfigByte
13905 (asc_dvc, AscPCIConfigCommandRegister))
13906 & AscPCICmdRegBits_BusMastering)
13907 != AscPCICmdRegBits_BusMastering) {
13908 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
13909 }
13910 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013911
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013912 /*
13913 * PCI Latency Timer
13914 *
13915 * If the "latency timer" register is 0x20 or above, then we don't need
13916 * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
13917 * comes up less than 0x20).
13918 */
13919 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
13920 DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer,
13921 0x20);
13922 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) <
13923 0x20) {
13924 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
13925 }
13926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013927
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013928 /*
13929 * Save the state of the PCI Configuration Command Register
13930 * "Parity Error Response Control" Bit. If the bit is clear (0),
13931 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13932 * DMA parity errors.
13933 */
13934 asc_dvc->cfg->control_flag = 0;
13935 if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
13936 & AscPCICmdRegBits_ParErrRespCtrl)) == 0) {
13937 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
13938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013940 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
13941 ADV_LIB_VERSION_MINOR;
13942 asc_dvc->cfg->chip_version =
13943 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013944
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013945 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
13946 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13947 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013948
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013949 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
13950 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13951 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013952
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013953 /*
13954 * Reset the chip to start and allow register writes.
13955 */
13956 if (AdvFindSignature(iop_base) == 0) {
13957 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13958 return ADV_ERROR;
13959 } else {
13960 /*
13961 * The caller must set 'chip_type' to a valid setting.
13962 */
13963 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13964 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13965 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13966 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13967 return ADV_ERROR;
13968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013969
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013970 /*
13971 * Reset Chip.
13972 */
13973 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13974 ADV_CTRL_REG_CMD_RESET);
13975 DvcSleepMilliSecond(100);
13976 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13977 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013978
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013979 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13980 if ((status =
13981 AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) {
13982 return ADV_ERROR;
13983 }
13984 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13985 if ((status =
13986 AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) {
13987 return ADV_ERROR;
13988 }
13989 } else {
13990 if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) {
13991 return ADV_ERROR;
13992 }
13993 }
13994 warn_code |= status;
13995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013996
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013997 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013998}
13999
14000/*
14001 * Initialize the ASC-3550.
14002 *
14003 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14004 *
14005 * For a non-fatal error return a warning code. If there are no warnings
14006 * then 0 is returned.
14007 *
14008 * Needed after initialization for error recovery.
14009 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014010static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014011{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014012 AdvPortAddr iop_base;
14013 ushort warn_code;
14014 ADV_DCNT sum;
14015 int begin_addr;
14016 int end_addr;
14017 ushort code_sum;
14018 int word;
14019 int j;
14020 int adv_asc3550_expanded_size;
14021 ADV_CARR_T *carrp;
14022 ADV_DCNT contig_len;
14023 ADV_SDCNT buf_size;
14024 ADV_PADDR carr_paddr;
14025 int i;
14026 ushort scsi_cfg1;
14027 uchar tid;
14028 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
14029 ushort wdtr_able = 0, sdtr_able, tagqng_able;
14030 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070014031
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014032 /* If there is already an error, don't continue. */
14033 if (asc_dvc->err_code != 0) {
14034 return ADV_ERROR;
14035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014036
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014037 /*
14038 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
14039 */
14040 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
14041 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
14042 return ADV_ERROR;
14043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014044
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014045 warn_code = 0;
14046 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014047
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014048 /*
14049 * Save the RISC memory BIOS region before writing the microcode.
14050 * The BIOS may already be loaded and using its RISC LRAM region
14051 * so its region must be saved and restored.
14052 *
14053 * Note: This code makes the assumption, which is currently true,
14054 * that a chip reset does not clear RISC LRAM.
14055 */
14056 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14057 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14058 bios_mem[i]);
14059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014060
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014061 /*
14062 * Save current per TID negotiated values.
14063 */
14064 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
14065 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014066
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014067 bios_version =
14068 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
14069 major = (bios_version >> 12) & 0xF;
14070 minor = (bios_version >> 8) & 0xF;
14071 if (major < 3 || (major == 3 && minor == 1)) {
14072 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
14073 AdvReadWordLram(iop_base, 0x120, wdtr_able);
14074 } else {
14075 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14076 }
14077 }
14078 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14079 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14080 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14081 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14082 max_cmd[tid]);
14083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014084
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014085 /*
14086 * Load the Microcode
14087 *
14088 * Write the microcode image to RISC memory starting at address 0.
14089 */
14090 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14091 /* Assume the following compressed format of the microcode buffer:
14092 *
14093 * 254 word (508 byte) table indexed by byte code followed
14094 * by the following byte codes:
14095 *
14096 * 1-Byte Code:
14097 * 00: Emit word 0 in table.
14098 * 01: Emit word 1 in table.
14099 * .
14100 * FD: Emit word 253 in table.
14101 *
14102 * Multi-Byte Code:
14103 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
14104 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
14105 */
14106 word = 0;
14107 for (i = 253 * 2; i < _adv_asc3550_size; i++) {
14108 if (_adv_asc3550_buf[i] == 0xff) {
14109 for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) {
14110 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14111 _adv_asc3550_buf
14112 [i +
14113 3] << 8) |
14114 _adv_asc3550_buf
14115 [i + 2]));
14116 word++;
14117 }
14118 i += 3;
14119 } else if (_adv_asc3550_buf[i] == 0xfe) {
14120 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14121 _adv_asc3550_buf[i +
14122 2]
14123 << 8) |
14124 _adv_asc3550_buf[i +
14125 1]));
14126 i += 2;
14127 word++;
14128 } else {
14129 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14130 _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
14131 word++;
14132 }
14133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014134
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014135 /*
14136 * Set 'word' for later use to clear the rest of memory and save
14137 * the expanded mcode size.
14138 */
14139 word *= 2;
14140 adv_asc3550_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014141
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014142 /*
14143 * Clear the rest of ASC-3550 Internal RAM (8KB).
14144 */
14145 for (; word < ADV_3550_MEMSIZE; word += 2) {
14146 AdvWriteWordAutoIncLram(iop_base, 0);
14147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014148
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014149 /*
14150 * Verify the microcode checksum.
14151 */
14152 sum = 0;
14153 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014154
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014155 for (word = 0; word < adv_asc3550_expanded_size; word += 2) {
14156 sum += AdvReadWordAutoIncLram(iop_base);
14157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014158
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014159 if (sum != _adv_asc3550_chksum) {
14160 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14161 return ADV_ERROR;
14162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014163
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014164 /*
14165 * Restore the RISC memory BIOS region.
14166 */
14167 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14168 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14169 bios_mem[i]);
14170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014171
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014172 /*
14173 * Calculate and write the microcode code checksum to the microcode
14174 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14175 */
14176 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14177 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14178 code_sum = 0;
14179 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
14180 for (word = begin_addr; word < end_addr; word += 2) {
14181 code_sum += AdvReadWordAutoIncLram(iop_base);
14182 }
14183 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014184
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014185 /*
14186 * Read and save microcode version and date.
14187 */
14188 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
14189 asc_dvc->cfg->mcode_date);
14190 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
14191 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014192
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014193 /*
14194 * Set the chip type to indicate the ASC3550.
14195 */
14196 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014197
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014198 /*
14199 * If the PCI Configuration Command Register "Parity Error Response
14200 * Control" Bit was clear (0), then set the microcode variable
14201 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14202 * to ignore DMA parity errors.
14203 */
14204 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
14205 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14206 word |= CONTROL_FLAG_IGNORE_PERR;
14207 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014209
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014210 /*
14211 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
14212 * threshold of 128 bytes. This register is only accessible to the host.
14213 */
14214 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14215 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014216
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014217 /*
14218 * Microcode operating variables for WDTR, SDTR, and command tag
14219 * queuing will be set in AdvInquiryHandling() based on what a
14220 * device reports it is capable of in Inquiry byte 7.
14221 *
14222 * If SCSI Bus Resets have been disabled, then directly set
14223 * SDTR and WDTR from the EEPROM configuration. This will allow
14224 * the BIOS and warm boot to work without a SCSI bus hang on
14225 * the Inquiry caused by host and target mismatched DTR values.
14226 * Without the SCSI Bus Reset, before an Inquiry a device can't
14227 * be assumed to be in Asynchronous, Narrow mode.
14228 */
14229 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
14230 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
14231 asc_dvc->wdtr_able);
14232 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
14233 asc_dvc->sdtr_able);
14234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014235
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014236 /*
14237 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
14238 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
14239 * bitmask. These values determine the maximum SDTR speed negotiated
14240 * with a device.
14241 *
14242 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
14243 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
14244 * without determining here whether the device supports SDTR.
14245 *
14246 * 4-bit speed SDTR speed name
14247 * =========== ===============
14248 * 0000b (0x0) SDTR disabled
14249 * 0001b (0x1) 5 Mhz
14250 * 0010b (0x2) 10 Mhz
14251 * 0011b (0x3) 20 Mhz (Ultra)
14252 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
14253 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
14254 * 0110b (0x6) Undefined
14255 * .
14256 * 1111b (0xF) Undefined
14257 */
14258 word = 0;
14259 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14260 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
14261 /* Set Ultra speed for TID 'tid'. */
14262 word |= (0x3 << (4 * (tid % 4)));
14263 } else {
14264 /* Set Fast speed for TID 'tid'. */
14265 word |= (0x2 << (4 * (tid % 4)));
14266 }
14267 if (tid == 3) { /* Check if done with sdtr_speed1. */
14268 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
14269 word = 0;
14270 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
14271 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
14272 word = 0;
14273 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
14274 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
14275 word = 0;
14276 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
14277 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
14278 /* End of loop. */
14279 }
14280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014281
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014282 /*
14283 * Set microcode operating variable for the disconnect per TID bitmask.
14284 */
14285 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
14286 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014287
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014288 /*
14289 * Set SCSI_CFG0 Microcode Default Value.
14290 *
14291 * The microcode will set the SCSI_CFG0 register using this value
14292 * after it is started below.
14293 */
14294 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14295 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
14296 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014298 /*
14299 * Determine SCSI_CFG1 Microcode Default Value.
14300 *
14301 * The microcode will set the SCSI_CFG1 register using this value
14302 * after it is started below.
14303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014304
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014305 /* Read current SCSI_CFG1 Register value. */
14306 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014307
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014308 /*
14309 * If all three connectors are in use, return an error.
14310 */
14311 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
14312 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
14313 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
14314 return ADV_ERROR;
14315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014316
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014317 /*
14318 * If the internal narrow cable is reversed all of the SCSI_CTRL
14319 * register signals will be set. Check for and return an error if
14320 * this condition is found.
14321 */
14322 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
14323 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14324 return ADV_ERROR;
14325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014326
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014327 /*
14328 * If this is a differential board and a single-ended device
14329 * is attached to one of the connectors, return an error.
14330 */
14331 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
14332 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
14333 return ADV_ERROR;
14334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014335
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014336 /*
14337 * If automatic termination control is enabled, then set the
14338 * termination value based on a table listed in a_condor.h.
14339 *
14340 * If manual termination was specified with an EEPROM setting
14341 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
14342 * is ready to be 'ored' into SCSI_CFG1.
14343 */
14344 if (asc_dvc->cfg->termination == 0) {
14345 /*
14346 * The software always controls termination by setting TERM_CTL_SEL.
14347 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
14348 */
14349 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014350
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014351 switch (scsi_cfg1 & CABLE_DETECT) {
14352 /* TERM_CTL_H: on, TERM_CTL_L: on */
14353 case 0x3:
14354 case 0x7:
14355 case 0xB:
14356 case 0xD:
14357 case 0xE:
14358 case 0xF:
14359 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
14360 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014362 /* TERM_CTL_H: on, TERM_CTL_L: off */
14363 case 0x1:
14364 case 0x5:
14365 case 0x9:
14366 case 0xA:
14367 case 0xC:
14368 asc_dvc->cfg->termination |= TERM_CTL_H;
14369 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014370
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014371 /* TERM_CTL_H: off, TERM_CTL_L: off */
14372 case 0x2:
14373 case 0x6:
14374 break;
14375 }
14376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014377
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014378 /*
14379 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
14380 */
14381 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014382
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014383 /*
14384 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
14385 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
14386 * referenced, because the hardware internally inverts
14387 * the Termination High and Low bits if TERM_POL is set.
14388 */
14389 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014390
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014391 /*
14392 * Set SCSI_CFG1 Microcode Default Value
14393 *
14394 * Set filter value and possibly modified termination control
14395 * bits in the Microcode SCSI_CFG1 Register Value.
14396 *
14397 * The microcode will set the SCSI_CFG1 register using this value
14398 * after it is started below.
14399 */
14400 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
14401 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014402
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014403 /*
14404 * Set MEM_CFG Microcode Default Value
14405 *
14406 * The microcode will set the MEM_CFG register using this value
14407 * after it is started below.
14408 *
14409 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
14410 * are defined.
14411 *
14412 * ASC-3550 has 8KB internal memory.
14413 */
14414 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
14415 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014416
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014417 /*
14418 * Set SEL_MASK Microcode Default Value
14419 *
14420 * The microcode will set the SEL_MASK register using this value
14421 * after it is started below.
14422 */
14423 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14424 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014425
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014426 /*
14427 * Build carrier freelist.
14428 *
14429 * Driver must have already allocated memory and set 'carrier_buf'.
14430 */
14431 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014432
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014433 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
14434 asc_dvc->carr_freelist = NULL;
14435 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
14436 buf_size = ADV_CARRIER_BUFSIZE;
14437 } else {
14438 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
14439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014440
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014441 do {
14442 /*
14443 * Get physical address of the carrier 'carrp'.
14444 */
14445 contig_len = sizeof(ADV_CARR_T);
14446 carr_paddr =
14447 cpu_to_le32(DvcGetPhyAddr
14448 (asc_dvc, NULL, (uchar *)carrp,
14449 (ADV_SDCNT *)&contig_len,
14450 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014451
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014452 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014453
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014454 /*
14455 * If the current carrier is not physically contiguous, then
14456 * maybe there was a page crossing. Try the next carrier aligned
14457 * start address.
14458 */
14459 if (contig_len < sizeof(ADV_CARR_T)) {
14460 carrp++;
14461 continue;
14462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014463
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014464 carrp->carr_pa = carr_paddr;
14465 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014466
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014467 /*
14468 * Insert the carrier at the beginning of the freelist.
14469 */
14470 carrp->next_vpa =
14471 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14472 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014473
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014474 carrp++;
14475 }
14476 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014477
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014478 /*
14479 * Set-up the Host->RISC Initiator Command Queue (ICQ).
14480 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014481
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014482 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
14483 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14484 return ADV_ERROR;
14485 }
14486 asc_dvc->carr_freelist = (ADV_CARR_T *)
14487 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014488
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014489 /*
14490 * The first command issued will be placed in the stopper carrier.
14491 */
14492 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014493
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014494 /*
14495 * Set RISC ICQ physical address start value.
14496 */
14497 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014498
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014499 /*
14500 * Set-up the RISC->Host Initiator Response Queue (IRQ).
14501 */
14502 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
14503 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
14504 return ADV_ERROR;
14505 }
14506 asc_dvc->carr_freelist = (ADV_CARR_T *)
14507 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014508
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014509 /*
14510 * The first command completed by the RISC will be placed in
14511 * the stopper.
14512 *
14513 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
14514 * completed the RISC will set the ASC_RQ_STOPPER bit.
14515 */
14516 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014517
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014518 /*
14519 * Set RISC IRQ physical address start value.
14520 */
14521 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
14522 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014523
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014524 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14525 (ADV_INTR_ENABLE_HOST_INTR |
14526 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014527
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014528 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14529 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014530
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014531 /* finally, finally, gentlemen, start your engine */
14532 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014533
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014534 /*
14535 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14536 * Resets should be performed. The RISC has to be running
14537 * to issue a SCSI Bus Reset.
14538 */
14539 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
14540 /*
14541 * If the BIOS Signature is present in memory, restore the
14542 * BIOS Handshake Configuration Table and do not perform
14543 * a SCSI Bus Reset.
14544 */
14545 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
14546 0x55AA) {
14547 /*
14548 * Restore per TID negotiated values.
14549 */
14550 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14551 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14552 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
14553 tagqng_able);
14554 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14555 AdvWriteByteLram(iop_base,
14556 ASC_MC_NUMBER_OF_MAX_CMD + tid,
14557 max_cmd[tid]);
14558 }
14559 } else {
14560 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
14561 warn_code = ASC_WARN_BUSRESET_ERROR;
14562 }
14563 }
14564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014565
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014566 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014567}
14568
14569/*
14570 * Initialize the ASC-38C0800.
14571 *
14572 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14573 *
14574 * For a non-fatal error return a warning code. If there are no warnings
14575 * then 0 is returned.
14576 *
14577 * Needed after initialization for error recovery.
14578 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014579static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014580{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014581 AdvPortAddr iop_base;
14582 ushort warn_code;
14583 ADV_DCNT sum;
14584 int begin_addr;
14585 int end_addr;
14586 ushort code_sum;
14587 int word;
14588 int j;
14589 int adv_asc38C0800_expanded_size;
14590 ADV_CARR_T *carrp;
14591 ADV_DCNT contig_len;
14592 ADV_SDCNT buf_size;
14593 ADV_PADDR carr_paddr;
14594 int i;
14595 ushort scsi_cfg1;
14596 uchar byte;
14597 uchar tid;
14598 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
14599 ushort wdtr_able, sdtr_able, tagqng_able;
14600 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070014601
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014602 /* If there is already an error, don't continue. */
14603 if (asc_dvc->err_code != 0) {
14604 return ADV_ERROR;
14605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014606
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014607 /*
14608 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
14609 */
14610 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
14611 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
14612 return ADV_ERROR;
14613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014614
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014615 warn_code = 0;
14616 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014617
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014618 /*
14619 * Save the RISC memory BIOS region before writing the microcode.
14620 * The BIOS may already be loaded and using its RISC LRAM region
14621 * so its region must be saved and restored.
14622 *
14623 * Note: This code makes the assumption, which is currently true,
14624 * that a chip reset does not clear RISC LRAM.
14625 */
14626 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14627 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14628 bios_mem[i]);
14629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014630
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014631 /*
14632 * Save current per TID negotiated values.
14633 */
14634 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14635 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14636 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14637 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14638 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14639 max_cmd[tid]);
14640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014641
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014642 /*
14643 * RAM BIST (RAM Built-In Self Test)
14644 *
14645 * Address : I/O base + offset 0x38h register (byte).
14646 * Function: Bit 7-6(RW) : RAM mode
14647 * Normal Mode : 0x00
14648 * Pre-test Mode : 0x40
14649 * RAM Test Mode : 0x80
14650 * Bit 5 : unused
14651 * Bit 4(RO) : Done bit
14652 * Bit 3-0(RO) : Status
14653 * Host Error : 0x08
14654 * Int_RAM Error : 0x04
14655 * RISC Error : 0x02
14656 * SCSI Error : 0x01
14657 * No Error : 0x00
14658 *
14659 * Note: RAM BIST code should be put right here, before loading the
14660 * microcode and after saving the RISC memory BIOS region.
14661 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014662
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014663 /*
14664 * LRAM Pre-test
14665 *
14666 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
14667 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
14668 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
14669 * to NORMAL_MODE, return an error too.
14670 */
14671 for (i = 0; i < 2; i++) {
14672 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
14673 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14674 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14675 if ((byte & RAM_TEST_DONE) == 0
14676 || (byte & 0x0F) != PRE_TEST_VALUE) {
14677 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14678 return ADV_ERROR;
14679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014680
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014681 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
14682 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14683 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
14684 != NORMAL_VALUE) {
14685 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
14686 return ADV_ERROR;
14687 }
14688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014689
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014690 /*
14691 * LRAM Test - It takes about 1.5 ms to run through the test.
14692 *
14693 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
14694 * If Done bit not set or Status not 0, save register byte, set the
14695 * err_code, and return an error.
14696 */
14697 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
14698 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014699
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014700 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14701 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
14702 /* Get here if Done bit not set or Status not 0. */
14703 asc_dvc->bist_err_code = byte; /* for BIOS display message */
14704 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
14705 return ADV_ERROR;
14706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014707
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014708 /* We need to reset back to normal mode after LRAM test passes. */
14709 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014710
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014711 /*
14712 * Load the Microcode
14713 *
14714 * Write the microcode image to RISC memory starting at address 0.
14715 *
14716 */
14717 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014718
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014719 /* Assume the following compressed format of the microcode buffer:
14720 *
14721 * 254 word (508 byte) table indexed by byte code followed
14722 * by the following byte codes:
14723 *
14724 * 1-Byte Code:
14725 * 00: Emit word 0 in table.
14726 * 01: Emit word 1 in table.
14727 * .
14728 * FD: Emit word 253 in table.
14729 *
14730 * Multi-Byte Code:
14731 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
14732 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
14733 */
14734 word = 0;
14735 for (i = 253 * 2; i < _adv_asc38C0800_size; i++) {
14736 if (_adv_asc38C0800_buf[i] == 0xff) {
14737 for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) {
14738 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14739 _adv_asc38C0800_buf
14740 [i +
14741 3] << 8) |
14742 _adv_asc38C0800_buf
14743 [i + 2]));
14744 word++;
14745 }
14746 i += 3;
14747 } else if (_adv_asc38C0800_buf[i] == 0xfe) {
14748 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14749 _adv_asc38C0800_buf
14750 [i +
14751 2] << 8) |
14752 _adv_asc38C0800_buf[i
14753 +
14754 1]));
14755 i += 2;
14756 word++;
14757 } else {
14758 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14759 _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
14760 word++;
14761 }
14762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014763
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014764 /*
14765 * Set 'word' for later use to clear the rest of memory and save
14766 * the expanded mcode size.
14767 */
14768 word *= 2;
14769 adv_asc38C0800_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014770
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014771 /*
14772 * Clear the rest of ASC-38C0800 Internal RAM (16KB).
14773 */
14774 for (; word < ADV_38C0800_MEMSIZE; word += 2) {
14775 AdvWriteWordAutoIncLram(iop_base, 0);
14776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014777
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014778 /*
14779 * Verify the microcode checksum.
14780 */
14781 sum = 0;
14782 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014783
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014784 for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) {
14785 sum += AdvReadWordAutoIncLram(iop_base);
14786 }
14787 ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014788
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014789 ASC_DBG2(1,
14790 "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n",
14791 (ulong)sum, (ulong)_adv_asc38C0800_chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014792
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014793 if (sum != _adv_asc38C0800_chksum) {
14794 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14795 return ADV_ERROR;
14796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014797
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014798 /*
14799 * Restore the RISC memory BIOS region.
14800 */
14801 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
14802 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
14803 bios_mem[i]);
14804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014805
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014806 /*
14807 * Calculate and write the microcode code checksum to the microcode
14808 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14809 */
14810 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14811 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14812 code_sum = 0;
14813 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
14814 for (word = begin_addr; word < end_addr; word += 2) {
14815 code_sum += AdvReadWordAutoIncLram(iop_base);
14816 }
14817 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014818
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014819 /*
14820 * Read microcode version and date.
14821 */
14822 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
14823 asc_dvc->cfg->mcode_date);
14824 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
14825 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014826
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014827 /*
14828 * Set the chip type to indicate the ASC38C0800.
14829 */
14830 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014831
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014832 /*
14833 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
14834 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
14835 * cable detection and then we are able to read C_DET[3:0].
14836 *
14837 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
14838 * Microcode Default Value' section below.
14839 */
14840 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14841 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
14842 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014843
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014844 /*
14845 * If the PCI Configuration Command Register "Parity Error Response
14846 * Control" Bit was clear (0), then set the microcode variable
14847 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14848 * to ignore DMA parity errors.
14849 */
14850 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
14851 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14852 word |= CONTROL_FLAG_IGNORE_PERR;
14853 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014855
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014856 /*
14857 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
14858 * bits for the default FIFO threshold.
14859 *
14860 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
14861 *
14862 * For DMA Errata #4 set the BC_THRESH_ENB bit.
14863 */
14864 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14865 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
14866 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014867
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014868 /*
14869 * Microcode operating variables for WDTR, SDTR, and command tag
14870 * queuing will be set in AdvInquiryHandling() based on what a
14871 * device reports it is capable of in Inquiry byte 7.
14872 *
14873 * If SCSI Bus Resets have been disabled, then directly set
14874 * SDTR and WDTR from the EEPROM configuration. This will allow
14875 * the BIOS and warm boot to work without a SCSI bus hang on
14876 * the Inquiry caused by host and target mismatched DTR values.
14877 * Without the SCSI Bus Reset, before an Inquiry a device can't
14878 * be assumed to be in Asynchronous, Narrow mode.
14879 */
14880 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
14881 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
14882 asc_dvc->wdtr_able);
14883 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
14884 asc_dvc->sdtr_able);
14885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014887 /*
14888 * Set microcode operating variables for DISC and SDTR_SPEED1,
14889 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
14890 * configuration values.
14891 *
14892 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
14893 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
14894 * without determining here whether the device supports SDTR.
14895 */
14896 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
14897 asc_dvc->cfg->disc_enable);
14898 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
14899 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
14900 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
14901 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014902
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014903 /*
14904 * Set SCSI_CFG0 Microcode Default Value.
14905 *
14906 * The microcode will set the SCSI_CFG0 register using this value
14907 * after it is started below.
14908 */
14909 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14910 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
14911 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014912
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014913 /*
14914 * Determine SCSI_CFG1 Microcode Default Value.
14915 *
14916 * The microcode will set the SCSI_CFG1 register using this value
14917 * after it is started below.
14918 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014919
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014920 /* Read current SCSI_CFG1 Register value. */
14921 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014922
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014923 /*
14924 * If the internal narrow cable is reversed all of the SCSI_CTRL
14925 * register signals will be set. Check for and return an error if
14926 * this condition is found.
14927 */
14928 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
14929 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14930 return ADV_ERROR;
14931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014932
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014933 /*
14934 * All kind of combinations of devices attached to one of four connectors
14935 * are acceptable except HVD device attached. For example, LVD device can
14936 * be attached to SE connector while SE device attached to LVD connector.
14937 * If LVD device attached to SE connector, it only runs up to Ultra speed.
14938 *
14939 * If an HVD device is attached to one of LVD connectors, return an error.
14940 * However, there is no way to detect HVD device attached to SE connectors.
14941 */
14942 if (scsi_cfg1 & HVD) {
14943 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
14944 return ADV_ERROR;
14945 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014946
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014947 /*
14948 * If either SE or LVD automatic termination control is enabled, then
14949 * set the termination value based on a table listed in a_condor.h.
14950 *
14951 * If manual termination was specified with an EEPROM setting then
14952 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to
14953 * be 'ored' into SCSI_CFG1.
14954 */
14955 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
14956 /* SE automatic termination control is enabled. */
14957 switch (scsi_cfg1 & C_DET_SE) {
14958 /* TERM_SE_HI: on, TERM_SE_LO: on */
14959 case 0x1:
14960 case 0x2:
14961 case 0x3:
14962 asc_dvc->cfg->termination |= TERM_SE;
14963 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014964
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014965 /* TERM_SE_HI: on, TERM_SE_LO: off */
14966 case 0x0:
14967 asc_dvc->cfg->termination |= TERM_SE_HI;
14968 break;
14969 }
14970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014971
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014972 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
14973 /* LVD automatic termination control is enabled. */
14974 switch (scsi_cfg1 & C_DET_LVD) {
14975 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
14976 case 0x4:
14977 case 0x8:
14978 case 0xC:
14979 asc_dvc->cfg->termination |= TERM_LVD;
14980 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014981
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014982 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
14983 case 0x0:
14984 break;
14985 }
14986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014987
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014988 /*
14989 * Clear any set TERM_SE and TERM_LVD bits.
14990 */
14991 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014992
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014993 /*
14994 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
14995 */
14996 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014997
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014998 /*
14999 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits
15000 * and set possibly modified termination control bits in the Microcode
15001 * SCSI_CFG1 Register Value.
15002 */
15003 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015004
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015005 /*
15006 * Set SCSI_CFG1 Microcode Default Value
15007 *
15008 * Set possibly modified termination control and reset DIS_TERM_DRV
15009 * bits in the Microcode SCSI_CFG1 Register Value.
15010 *
15011 * The microcode will set the SCSI_CFG1 register using this value
15012 * after it is started below.
15013 */
15014 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015015
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015016 /*
15017 * Set MEM_CFG Microcode Default Value
15018 *
15019 * The microcode will set the MEM_CFG register using this value
15020 * after it is started below.
15021 *
15022 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
15023 * are defined.
15024 *
15025 * ASC-38C0800 has 16KB internal memory.
15026 */
15027 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15028 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015029
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015030 /*
15031 * Set SEL_MASK Microcode Default Value
15032 *
15033 * The microcode will set the SEL_MASK register using this value
15034 * after it is started below.
15035 */
15036 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
15037 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015038
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015039 /*
15040 * Build the carrier freelist.
15041 *
15042 * Driver must have already allocated memory and set 'carrier_buf'.
15043 */
15044 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015045
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015046 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
15047 asc_dvc->carr_freelist = NULL;
15048 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
15049 buf_size = ADV_CARRIER_BUFSIZE;
15050 } else {
15051 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
15052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015053
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015054 do {
15055 /*
15056 * Get physical address for the carrier 'carrp'.
15057 */
15058 contig_len = sizeof(ADV_CARR_T);
15059 carr_paddr =
15060 cpu_to_le32(DvcGetPhyAddr
15061 (asc_dvc, NULL, (uchar *)carrp,
15062 (ADV_SDCNT *)&contig_len,
15063 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015064
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015065 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015066
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015067 /*
15068 * If the current carrier is not physically contiguous, then
15069 * maybe there was a page crossing. Try the next carrier aligned
15070 * start address.
15071 */
15072 if (contig_len < sizeof(ADV_CARR_T)) {
15073 carrp++;
15074 continue;
15075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015076
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015077 carrp->carr_pa = carr_paddr;
15078 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015080 /*
15081 * Insert the carrier at the beginning of the freelist.
15082 */
15083 carrp->next_vpa =
15084 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
15085 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015086
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015087 carrp++;
15088 }
15089 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015090
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015091 /*
15092 * Set-up the Host->RISC Initiator Command Queue (ICQ).
15093 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015094
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015095 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
15096 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15097 return ADV_ERROR;
15098 }
15099 asc_dvc->carr_freelist = (ADV_CARR_T *)
15100 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015102 /*
15103 * The first command issued will be placed in the stopper carrier.
15104 */
15105 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015106
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015107 /*
15108 * Set RISC ICQ physical address start value.
15109 * carr_pa is LE, must be native before write
15110 */
15111 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015112
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015113 /*
15114 * Set-up the RISC->Host Initiator Response Queue (IRQ).
15115 */
15116 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
15117 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15118 return ADV_ERROR;
15119 }
15120 asc_dvc->carr_freelist = (ADV_CARR_T *)
15121 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015122
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015123 /*
15124 * The first command completed by the RISC will be placed in
15125 * the stopper.
15126 *
15127 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
15128 * completed the RISC will set the ASC_RQ_STOPPER bit.
15129 */
15130 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015131
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015132 /*
15133 * Set RISC IRQ physical address start value.
15134 *
15135 * carr_pa is LE, must be native before write *
15136 */
15137 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
15138 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015140 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
15141 (ADV_INTR_ENABLE_HOST_INTR |
15142 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015144 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
15145 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015146
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015147 /* finally, finally, gentlemen, start your engine */
15148 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015149
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015150 /*
15151 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
15152 * Resets should be performed. The RISC has to be running
15153 * to issue a SCSI Bus Reset.
15154 */
15155 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
15156 /*
15157 * If the BIOS Signature is present in memory, restore the
15158 * BIOS Handshake Configuration Table and do not perform
15159 * a SCSI Bus Reset.
15160 */
15161 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
15162 0x55AA) {
15163 /*
15164 * Restore per TID negotiated values.
15165 */
15166 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15167 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15168 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
15169 tagqng_able);
15170 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
15171 AdvWriteByteLram(iop_base,
15172 ASC_MC_NUMBER_OF_MAX_CMD + tid,
15173 max_cmd[tid]);
15174 }
15175 } else {
15176 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
15177 warn_code = ASC_WARN_BUSRESET_ERROR;
15178 }
15179 }
15180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015181
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015182 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015183}
15184
15185/*
15186 * Initialize the ASC-38C1600.
15187 *
15188 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
15189 *
15190 * For a non-fatal error return a warning code. If there are no warnings
15191 * then 0 is returned.
15192 *
15193 * Needed after initialization for error recovery.
15194 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015195static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015196{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015197 AdvPortAddr iop_base;
15198 ushort warn_code;
15199 ADV_DCNT sum;
15200 int begin_addr;
15201 int end_addr;
15202 ushort code_sum;
15203 long word;
15204 int j;
15205 int adv_asc38C1600_expanded_size;
15206 ADV_CARR_T *carrp;
15207 ADV_DCNT contig_len;
15208 ADV_SDCNT buf_size;
15209 ADV_PADDR carr_paddr;
15210 int i;
15211 ushort scsi_cfg1;
15212 uchar byte;
15213 uchar tid;
15214 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
15215 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
15216 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070015217
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015218 /* If there is already an error, don't continue. */
15219 if (asc_dvc->err_code != 0) {
15220 return ADV_ERROR;
15221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015222
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015223 /*
15224 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
15225 */
15226 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
15227 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
15228 return ADV_ERROR;
15229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015230
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015231 warn_code = 0;
15232 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015233
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015234 /*
15235 * Save the RISC memory BIOS region before writing the microcode.
15236 * The BIOS may already be loaded and using its RISC LRAM region
15237 * so its region must be saved and restored.
15238 *
15239 * Note: This code makes the assumption, which is currently true,
15240 * that a chip reset does not clear RISC LRAM.
15241 */
15242 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
15243 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
15244 bios_mem[i]);
15245 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015246
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015247 /*
15248 * Save current per TID negotiated values.
15249 */
15250 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15251 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15252 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
15253 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
15254 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
15255 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
15256 max_cmd[tid]);
15257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015258
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015259 /*
15260 * RAM BIST (Built-In Self Test)
15261 *
15262 * Address : I/O base + offset 0x38h register (byte).
15263 * Function: Bit 7-6(RW) : RAM mode
15264 * Normal Mode : 0x00
15265 * Pre-test Mode : 0x40
15266 * RAM Test Mode : 0x80
15267 * Bit 5 : unused
15268 * Bit 4(RO) : Done bit
15269 * Bit 3-0(RO) : Status
15270 * Host Error : 0x08
15271 * Int_RAM Error : 0x04
15272 * RISC Error : 0x02
15273 * SCSI Error : 0x01
15274 * No Error : 0x00
15275 *
15276 * Note: RAM BIST code should be put right here, before loading the
15277 * microcode and after saving the RISC memory BIOS region.
15278 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015279
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015280 /*
15281 * LRAM Pre-test
15282 *
15283 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
15284 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
15285 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
15286 * to NORMAL_MODE, return an error too.
15287 */
15288 for (i = 0; i < 2; i++) {
15289 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
15290 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
15291 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
15292 if ((byte & RAM_TEST_DONE) == 0
15293 || (byte & 0x0F) != PRE_TEST_VALUE) {
15294 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
15295 return ADV_ERROR;
15296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015298 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
15299 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
15300 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
15301 != NORMAL_VALUE) {
15302 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
15303 return ADV_ERROR;
15304 }
15305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015306
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015307 /*
15308 * LRAM Test - It takes about 1.5 ms to run through the test.
15309 *
15310 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
15311 * If Done bit not set or Status not 0, save register byte, set the
15312 * err_code, and return an error.
15313 */
15314 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
15315 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015316
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015317 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
15318 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
15319 /* Get here if Done bit not set or Status not 0. */
15320 asc_dvc->bist_err_code = byte; /* for BIOS display message */
15321 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
15322 return ADV_ERROR;
15323 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015324
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015325 /* We need to reset back to normal mode after LRAM test passes. */
15326 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015328 /*
15329 * Load the Microcode
15330 *
15331 * Write the microcode image to RISC memory starting at address 0.
15332 *
15333 */
15334 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015335
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015336 /*
15337 * Assume the following compressed format of the microcode buffer:
15338 *
15339 * 254 word (508 byte) table indexed by byte code followed
15340 * by the following byte codes:
15341 *
15342 * 1-Byte Code:
15343 * 00: Emit word 0 in table.
15344 * 01: Emit word 1 in table.
15345 * .
15346 * FD: Emit word 253 in table.
15347 *
15348 * Multi-Byte Code:
15349 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
15350 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
15351 */
15352 word = 0;
15353 for (i = 253 * 2; i < _adv_asc38C1600_size; i++) {
15354 if (_adv_asc38C1600_buf[i] == 0xff) {
15355 for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) {
15356 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15357 _adv_asc38C1600_buf
15358 [i +
15359 3] << 8) |
15360 _adv_asc38C1600_buf
15361 [i + 2]));
15362 word++;
15363 }
15364 i += 3;
15365 } else if (_adv_asc38C1600_buf[i] == 0xfe) {
15366 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15367 _adv_asc38C1600_buf
15368 [i +
15369 2] << 8) |
15370 _adv_asc38C1600_buf[i
15371 +
15372 1]));
15373 i += 2;
15374 word++;
15375 } else {
15376 AdvWriteWordAutoIncLram(iop_base, (((ushort)
15377 _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2]));
15378 word++;
15379 }
15380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015381
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015382 /*
15383 * Set 'word' for later use to clear the rest of memory and save
15384 * the expanded mcode size.
15385 */
15386 word *= 2;
15387 adv_asc38C1600_expanded_size = word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015388
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015389 /*
15390 * Clear the rest of ASC-38C1600 Internal RAM (32KB).
15391 */
15392 for (; word < ADV_38C1600_MEMSIZE; word += 2) {
15393 AdvWriteWordAutoIncLram(iop_base, 0);
15394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015396 /*
15397 * Verify the microcode checksum.
15398 */
15399 sum = 0;
15400 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015401
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015402 for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) {
15403 sum += AdvReadWordAutoIncLram(iop_base);
15404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015405
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015406 if (sum != _adv_asc38C1600_chksum) {
15407 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
15408 return ADV_ERROR;
15409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015410
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015411 /*
15412 * Restore the RISC memory BIOS region.
15413 */
15414 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
15415 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
15416 bios_mem[i]);
15417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015418
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015419 /*
15420 * Calculate and write the microcode code checksum to the microcode
15421 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
15422 */
15423 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
15424 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
15425 code_sum = 0;
15426 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
15427 for (word = begin_addr; word < end_addr; word += 2) {
15428 code_sum += AdvReadWordAutoIncLram(iop_base);
15429 }
15430 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015431
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015432 /*
15433 * Read microcode version and date.
15434 */
15435 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
15436 asc_dvc->cfg->mcode_date);
15437 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
15438 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015439
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015440 /*
15441 * Set the chip type to indicate the ASC38C1600.
15442 */
15443 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015444
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015445 /*
15446 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
15447 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
15448 * cable detection and then we are able to read C_DET[3:0].
15449 *
15450 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
15451 * Microcode Default Value' section below.
15452 */
15453 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
15454 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
15455 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015456
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015457 /*
15458 * If the PCI Configuration Command Register "Parity Error Response
15459 * Control" Bit was clear (0), then set the microcode variable
15460 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
15461 * to ignore DMA parity errors.
15462 */
15463 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
15464 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15465 word |= CONTROL_FLAG_IGNORE_PERR;
15466 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015468
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015469 /*
15470 * If the BIOS control flag AIPP (Asynchronous Information
15471 * Phase Protection) disable bit is not set, then set the firmware
15472 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
15473 * AIPP checking and encoding.
15474 */
15475 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
15476 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15477 word |= CONTROL_FLAG_ENABLE_AIPP;
15478 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015480
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015481 /*
15482 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
15483 * and START_CTL_TH [3:2].
15484 */
15485 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
15486 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015487
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015488 /*
15489 * Microcode operating variables for WDTR, SDTR, and command tag
15490 * queuing will be set in AdvInquiryHandling() based on what a
15491 * device reports it is capable of in Inquiry byte 7.
15492 *
15493 * If SCSI Bus Resets have been disabled, then directly set
15494 * SDTR and WDTR from the EEPROM configuration. This will allow
15495 * the BIOS and warm boot to work without a SCSI bus hang on
15496 * the Inquiry caused by host and target mismatched DTR values.
15497 * Without the SCSI Bus Reset, before an Inquiry a device can't
15498 * be assumed to be in Asynchronous, Narrow mode.
15499 */
15500 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
15501 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
15502 asc_dvc->wdtr_able);
15503 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
15504 asc_dvc->sdtr_able);
15505 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015506
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015507 /*
15508 * Set microcode operating variables for DISC and SDTR_SPEED1,
15509 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
15510 * configuration values.
15511 *
15512 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
15513 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
15514 * without determining here whether the device supports SDTR.
15515 */
15516 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
15517 asc_dvc->cfg->disc_enable);
15518 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
15519 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
15520 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
15521 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015522
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015523 /*
15524 * Set SCSI_CFG0 Microcode Default Value.
15525 *
15526 * The microcode will set the SCSI_CFG0 register using this value
15527 * after it is started below.
15528 */
15529 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
15530 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
15531 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015532
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015533 /*
15534 * Calculate SCSI_CFG1 Microcode Default Value.
15535 *
15536 * The microcode will set the SCSI_CFG1 register using this value
15537 * after it is started below.
15538 *
15539 * Each ASC-38C1600 function has only two cable detect bits.
15540 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
15541 */
15542 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015543
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015544 /*
15545 * If the cable is reversed all of the SCSI_CTRL register signals
15546 * will be set. Check for and return an error if this condition is
15547 * found.
15548 */
15549 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
15550 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
15551 return ADV_ERROR;
15552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015553
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015554 /*
15555 * Each ASC-38C1600 function has two connectors. Only an HVD device
15556 * can not be connected to either connector. An LVD device or SE device
15557 * may be connected to either connecor. If an SE device is connected,
15558 * then at most Ultra speed (20 Mhz) can be used on both connectors.
15559 *
15560 * If an HVD device is attached, return an error.
15561 */
15562 if (scsi_cfg1 & HVD) {
15563 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
15564 return ADV_ERROR;
15565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015566
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015567 /*
15568 * Each function in the ASC-38C1600 uses only the SE cable detect and
15569 * termination because there are two connectors for each function. Each
15570 * function may use either LVD or SE mode. Corresponding the SE automatic
15571 * termination control EEPROM bits are used for each function. Each
15572 * function has its own EEPROM. If SE automatic control is enabled for
15573 * the function, then set the termination value based on a table listed
15574 * in a_condor.h.
15575 *
15576 * If manual termination is specified in the EEPROM for the function,
15577 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
15578 * ready to be 'ored' into SCSI_CFG1.
15579 */
15580 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
15581 /* SE automatic termination control is enabled. */
15582 switch (scsi_cfg1 & C_DET_SE) {
15583 /* TERM_SE_HI: on, TERM_SE_LO: on */
15584 case 0x1:
15585 case 0x2:
15586 case 0x3:
15587 asc_dvc->cfg->termination |= TERM_SE;
15588 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015589
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015590 case 0x0:
15591 if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) {
15592 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
15593 } else {
15594 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
15595 asc_dvc->cfg->termination |= TERM_SE_HI;
15596 }
15597 break;
15598 }
15599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015601 /*
15602 * Clear any set TERM_SE bits.
15603 */
15604 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015605
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015606 /*
15607 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
15608 */
15609 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015610
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015611 /*
15612 * Clear Big Endian and Terminator Polarity bits and set possibly
15613 * modified termination control bits in the Microcode SCSI_CFG1
15614 * Register Value.
15615 *
15616 * Big Endian bit is not used even on big endian machines.
15617 */
15618 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015619
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015620 /*
15621 * Set SCSI_CFG1 Microcode Default Value
15622 *
15623 * Set possibly modified termination control bits in the Microcode
15624 * SCSI_CFG1 Register Value.
15625 *
15626 * The microcode will set the SCSI_CFG1 register using this value
15627 * after it is started below.
15628 */
15629 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015630
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015631 /*
15632 * Set MEM_CFG Microcode Default Value
15633 *
15634 * The microcode will set the MEM_CFG register using this value
15635 * after it is started below.
15636 *
15637 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
15638 * are defined.
15639 *
15640 * ASC-38C1600 has 32KB internal memory.
15641 *
15642 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
15643 * out a special 16K Adv Library and Microcode version. After the issue
15644 * resolved, we should turn back to the 32K support. Both a_condor.h and
15645 * mcode.sas files also need to be updated.
15646 *
15647 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15648 * BIOS_EN | RAM_SZ_32KB);
15649 */
15650 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
15651 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015652
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015653 /*
15654 * Set SEL_MASK Microcode Default Value
15655 *
15656 * The microcode will set the SEL_MASK register using this value
15657 * after it is started below.
15658 */
15659 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
15660 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015661
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015662 /*
15663 * Build the carrier freelist.
15664 *
15665 * Driver must have already allocated memory and set 'carrier_buf'.
15666 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070015667
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015668 ASC_ASSERT(asc_dvc->carrier_buf != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015669
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015670 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
15671 asc_dvc->carr_freelist = NULL;
15672 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
15673 buf_size = ADV_CARRIER_BUFSIZE;
15674 } else {
15675 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
15676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015677
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015678 do {
15679 /*
15680 * Get physical address for the carrier 'carrp'.
15681 */
15682 contig_len = sizeof(ADV_CARR_T);
15683 carr_paddr =
15684 cpu_to_le32(DvcGetPhyAddr
15685 (asc_dvc, NULL, (uchar *)carrp,
15686 (ADV_SDCNT *)&contig_len,
15687 ADV_IS_CARRIER_FLAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015688
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015689 buf_size -= sizeof(ADV_CARR_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015690
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015691 /*
15692 * If the current carrier is not physically contiguous, then
15693 * maybe there was a page crossing. Try the next carrier aligned
15694 * start address.
15695 */
15696 if (contig_len < sizeof(ADV_CARR_T)) {
15697 carrp++;
15698 continue;
15699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015700
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015701 carrp->carr_pa = carr_paddr;
15702 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015703
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015704 /*
15705 * Insert the carrier at the beginning of the freelist.
15706 */
15707 carrp->next_vpa =
15708 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
15709 asc_dvc->carr_freelist = carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015710
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015711 carrp++;
15712 }
15713 while (buf_size > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015714
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015715 /*
15716 * Set-up the Host->RISC Initiator Command Queue (ICQ).
15717 */
15718 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
15719 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15720 return ADV_ERROR;
15721 }
15722 asc_dvc->carr_freelist = (ADV_CARR_T *)
15723 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015724
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015725 /*
15726 * The first command issued will be placed in the stopper carrier.
15727 */
15728 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015729
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015730 /*
15731 * Set RISC ICQ physical address start value. Initialize the
15732 * COMMA register to the same value otherwise the RISC will
15733 * prematurely detect a command is available.
15734 */
15735 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
15736 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
15737 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015738
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015739 /*
15740 * Set-up the RISC->Host Initiator Response Queue (IRQ).
15741 */
15742 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
15743 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
15744 return ADV_ERROR;
15745 }
15746 asc_dvc->carr_freelist = (ADV_CARR_T *)
15747 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070015748
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015749 /*
15750 * The first command completed by the RISC will be placed in
15751 * the stopper.
15752 *
15753 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
15754 * completed the RISC will set the ASC_RQ_STOPPER bit.
15755 */
15756 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015758 /*
15759 * Set RISC IRQ physical address start value.
15760 */
15761 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
15762 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015763
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015764 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
15765 (ADV_INTR_ENABLE_HOST_INTR |
15766 ADV_INTR_ENABLE_GLOBAL_INTR));
15767 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
15768 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015769
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015770 /* finally, finally, gentlemen, start your engine */
15771 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015772
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015773 /*
15774 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
15775 * Resets should be performed. The RISC has to be running
15776 * to issue a SCSI Bus Reset.
15777 */
15778 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
15779 /*
15780 * If the BIOS Signature is present in memory, restore the
15781 * per TID microcode operating variables.
15782 */
15783 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
15784 0x55AA) {
15785 /*
15786 * Restore per TID negotiated values.
15787 */
15788 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15789 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15790 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
15791 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
15792 tagqng_able);
15793 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
15794 AdvWriteByteLram(iop_base,
15795 ASC_MC_NUMBER_OF_MAX_CMD + tid,
15796 max_cmd[tid]);
15797 }
15798 } else {
15799 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
15800 warn_code = ASC_WARN_BUSRESET_ERROR;
15801 }
15802 }
15803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015804
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015805 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015806}
15807
15808/*
15809 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
15810 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
15811 * all of this is done.
15812 *
15813 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
15814 *
15815 * For a non-fatal error return a warning code. If there are no warnings
15816 * then 0 is returned.
15817 *
15818 * Note: Chip is stopped on entry.
15819 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015820static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015821{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015822 AdvPortAddr iop_base;
15823 ushort warn_code;
15824 ADVEEP_3550_CONFIG eep_config;
15825 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015826
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015827 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015828
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015829 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015831 /*
15832 * Read the board's EEPROM configuration.
15833 *
15834 * Set default values if a bad checksum is found.
15835 */
15836 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
15837 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015838
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015839 /*
15840 * Set EEPROM default values.
15841 */
15842 for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) {
15843 *((uchar *)&eep_config + i) =
15844 *((uchar *)&Default_3550_EEPROM_Config + i);
15845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015847 /*
15848 * Assume the 6 byte board serial number that was read
15849 * from EEPROM is correct even if the EEPROM checksum
15850 * failed.
15851 */
15852 eep_config.serial_number_word3 =
15853 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015854
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015855 eep_config.serial_number_word2 =
15856 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015857
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015858 eep_config.serial_number_word1 =
15859 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070015860
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015861 AdvSet3550EEPConfig(iop_base, &eep_config);
15862 }
15863 /*
15864 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
15865 * EEPROM configuration that was read.
15866 *
15867 * This is the mapping of EEPROM fields to Adv Library fields.
15868 */
15869 asc_dvc->wdtr_able = eep_config.wdtr_able;
15870 asc_dvc->sdtr_able = eep_config.sdtr_able;
15871 asc_dvc->ultra_able = eep_config.ultra_able;
15872 asc_dvc->tagqng_able = eep_config.tagqng_able;
15873 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
15874 asc_dvc->max_host_qng = eep_config.max_host_qng;
15875 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
15876 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
15877 asc_dvc->start_motor = eep_config.start_motor;
15878 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
15879 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
15880 asc_dvc->no_scam = eep_config.scam_tolerant;
15881 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
15882 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
15883 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015884
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015885 /*
15886 * Set the host maximum queuing (max. 253, min. 16) and the per device
15887 * maximum queuing (max. 63, min. 4).
15888 */
15889 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
15890 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15891 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
15892 /* If the value is zero, assume it is uninitialized. */
15893 if (eep_config.max_host_qng == 0) {
15894 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
15895 } else {
15896 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
15897 }
15898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015899
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015900 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
15901 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15902 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
15903 /* If the value is zero, assume it is uninitialized. */
15904 if (eep_config.max_dvc_qng == 0) {
15905 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
15906 } else {
15907 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
15908 }
15909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015910
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015911 /*
15912 * If 'max_dvc_qng' is greater than 'max_host_qng', then
15913 * set 'max_dvc_qng' to 'max_host_qng'.
15914 */
15915 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
15916 eep_config.max_dvc_qng = eep_config.max_host_qng;
15917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015918
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015919 /*
15920 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
15921 * values based on possibly adjusted EEPROM values.
15922 */
15923 asc_dvc->max_host_qng = eep_config.max_host_qng;
15924 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015925
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015926 /*
15927 * If the EEPROM 'termination' field is set to automatic (0), then set
15928 * the ADV_DVC_CFG 'termination' field to automatic also.
15929 *
15930 * If the termination is specified with a non-zero 'termination'
15931 * value check that a legal value is set and set the ADV_DVC_CFG
15932 * 'termination' field appropriately.
15933 */
15934 if (eep_config.termination == 0) {
15935 asc_dvc->cfg->termination = 0; /* auto termination */
15936 } else {
15937 /* Enable manual control with low off / high off. */
15938 if (eep_config.termination == 1) {
15939 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015940
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015941 /* Enable manual control with low off / high on. */
15942 } else if (eep_config.termination == 2) {
15943 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015944
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015945 /* Enable manual control with low on / high on. */
15946 } else if (eep_config.termination == 3) {
15947 asc_dvc->cfg->termination =
15948 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
15949 } else {
15950 /*
15951 * The EEPROM 'termination' field contains a bad value. Use
15952 * automatic termination instead.
15953 */
15954 asc_dvc->cfg->termination = 0;
15955 warn_code |= ASC_WARN_EEPROM_TERMINATION;
15956 }
15957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070015958
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015959 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015960}
15961
15962/*
15963 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
15964 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
15965 * all of this is done.
15966 *
15967 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
15968 *
15969 * For a non-fatal error return a warning code. If there are no warnings
15970 * then 0 is returned.
15971 *
15972 * Note: Chip is stopped on entry.
15973 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015974static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070015975{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015976 AdvPortAddr iop_base;
15977 ushort warn_code;
15978 ADVEEP_38C0800_CONFIG eep_config;
15979 int i;
15980 uchar tid, termination;
15981 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015982
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015983 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015984
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015985 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015986
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015987 /*
15988 * Read the board's EEPROM configuration.
15989 *
15990 * Set default values if a bad checksum is found.
15991 */
15992 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
15993 eep_config.check_sum) {
15994 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070015995
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015996 /*
15997 * Set EEPROM default values.
15998 */
15999 for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) {
16000 *((uchar *)&eep_config + i) =
16001 *((uchar *)&Default_38C0800_EEPROM_Config + i);
16002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016003
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016004 /*
16005 * Assume the 6 byte board serial number that was read
16006 * from EEPROM is correct even if the EEPROM checksum
16007 * failed.
16008 */
16009 eep_config.serial_number_word3 =
16010 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016011
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016012 eep_config.serial_number_word2 =
16013 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016014
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016015 eep_config.serial_number_word1 =
16016 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016017
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016018 AdvSet38C0800EEPConfig(iop_base, &eep_config);
16019 }
16020 /*
16021 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
16022 * EEPROM configuration that was read.
16023 *
16024 * This is the mapping of EEPROM fields to Adv Library fields.
16025 */
16026 asc_dvc->wdtr_able = eep_config.wdtr_able;
16027 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
16028 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
16029 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
16030 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
16031 asc_dvc->tagqng_able = eep_config.tagqng_able;
16032 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
16033 asc_dvc->max_host_qng = eep_config.max_host_qng;
16034 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16035 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
16036 asc_dvc->start_motor = eep_config.start_motor;
16037 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
16038 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
16039 asc_dvc->no_scam = eep_config.scam_tolerant;
16040 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
16041 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
16042 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016043
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016044 /*
16045 * For every Target ID if any of its 'sdtr_speed[1234]' bits
16046 * are set, then set an 'sdtr_able' bit for it.
16047 */
16048 asc_dvc->sdtr_able = 0;
16049 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
16050 if (tid == 0) {
16051 sdtr_speed = asc_dvc->sdtr_speed1;
16052 } else if (tid == 4) {
16053 sdtr_speed = asc_dvc->sdtr_speed2;
16054 } else if (tid == 8) {
16055 sdtr_speed = asc_dvc->sdtr_speed3;
16056 } else if (tid == 12) {
16057 sdtr_speed = asc_dvc->sdtr_speed4;
16058 }
16059 if (sdtr_speed & ADV_MAX_TID) {
16060 asc_dvc->sdtr_able |= (1 << tid);
16061 }
16062 sdtr_speed >>= 4;
16063 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016064
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016065 /*
16066 * Set the host maximum queuing (max. 253, min. 16) and the per device
16067 * maximum queuing (max. 63, min. 4).
16068 */
16069 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
16070 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16071 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
16072 /* If the value is zero, assume it is uninitialized. */
16073 if (eep_config.max_host_qng == 0) {
16074 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16075 } else {
16076 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
16077 }
16078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016080 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
16081 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16082 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
16083 /* If the value is zero, assume it is uninitialized. */
16084 if (eep_config.max_dvc_qng == 0) {
16085 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16086 } else {
16087 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
16088 }
16089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016090
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016091 /*
16092 * If 'max_dvc_qng' is greater than 'max_host_qng', then
16093 * set 'max_dvc_qng' to 'max_host_qng'.
16094 */
16095 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
16096 eep_config.max_dvc_qng = eep_config.max_host_qng;
16097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016098
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016099 /*
16100 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
16101 * values based on possibly adjusted EEPROM values.
16102 */
16103 asc_dvc->max_host_qng = eep_config.max_host_qng;
16104 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016105
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016106 /*
16107 * If the EEPROM 'termination' field is set to automatic (0), then set
16108 * the ADV_DVC_CFG 'termination' field to automatic also.
16109 *
16110 * If the termination is specified with a non-zero 'termination'
16111 * value check that a legal value is set and set the ADV_DVC_CFG
16112 * 'termination' field appropriately.
16113 */
16114 if (eep_config.termination_se == 0) {
16115 termination = 0; /* auto termination for SE */
16116 } else {
16117 /* Enable manual control with low off / high off. */
16118 if (eep_config.termination_se == 1) {
16119 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016120
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016121 /* Enable manual control with low off / high on. */
16122 } else if (eep_config.termination_se == 2) {
16123 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016124
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016125 /* Enable manual control with low on / high on. */
16126 } else if (eep_config.termination_se == 3) {
16127 termination = TERM_SE;
16128 } else {
16129 /*
16130 * The EEPROM 'termination_se' field contains a bad value.
16131 * Use automatic termination instead.
16132 */
16133 termination = 0;
16134 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16135 }
16136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016137
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016138 if (eep_config.termination_lvd == 0) {
16139 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
16140 } else {
16141 /* Enable manual control with low off / high off. */
16142 if (eep_config.termination_lvd == 1) {
16143 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016144
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016145 /* Enable manual control with low off / high on. */
16146 } else if (eep_config.termination_lvd == 2) {
16147 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016148
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016149 /* Enable manual control with low on / high on. */
16150 } else if (eep_config.termination_lvd == 3) {
16151 asc_dvc->cfg->termination = termination | TERM_LVD;
16152 } else {
16153 /*
16154 * The EEPROM 'termination_lvd' field contains a bad value.
16155 * Use automatic termination instead.
16156 */
16157 asc_dvc->cfg->termination = termination;
16158 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16159 }
16160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016161
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016162 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016163}
16164
16165/*
16166 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
16167 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
16168 * all of this is done.
16169 *
16170 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
16171 *
16172 * For a non-fatal error return a warning code. If there are no warnings
16173 * then 0 is returned.
16174 *
16175 * Note: Chip is stopped on entry.
16176 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016177static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016178{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016179 AdvPortAddr iop_base;
16180 ushort warn_code;
16181 ADVEEP_38C1600_CONFIG eep_config;
16182 int i;
16183 uchar tid, termination;
16184 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016185
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016186 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016187
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016188 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016189
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016190 /*
16191 * Read the board's EEPROM configuration.
16192 *
16193 * Set default values if a bad checksum is found.
16194 */
16195 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
16196 eep_config.check_sum) {
16197 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016198
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016199 /*
16200 * Set EEPROM default values.
16201 */
16202 for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) {
16203 if (i == 1
16204 && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) !=
16205 0) {
16206 /*
16207 * Set Function 1 EEPROM Word 0 MSB
16208 *
16209 * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11)
16210 * EEPROM bits.
16211 *
16212 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and
16213 * old Mac system booting problem. The Expansion ROM must
16214 * be disabled in Function 1 for these systems.
16215 *
16216 */
16217 *((uchar *)&eep_config + i) =
16218 ((*
16219 ((uchar *)&Default_38C1600_EEPROM_Config
16220 +
16221 i)) &
16222 (~
16223 (((ADV_EEPROM_BIOS_ENABLE |
16224 ADV_EEPROM_INTAB) >> 8) & 0xFF)));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016225
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016226 /*
16227 * Set the INTAB (bit 11) if the GPIO 0 input indicates
16228 * the Function 1 interrupt line is wired to INTA.
16229 *
16230 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
16231 * 1 - Function 1 interrupt line wired to INT A.
16232 * 0 - Function 1 interrupt line wired to INT B.
16233 *
16234 * Note: Adapter boards always have Function 0 wired to INTA.
16235 * Put all 5 GPIO bits in input mode and then read
16236 * their input values.
16237 */
16238 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL,
16239 0);
16240 if (AdvReadByteRegister
16241 (iop_base, IOPB_GPIO_DATA) & 0x01) {
16242 /* Function 1 interrupt wired to INTA; Set EEPROM bit. */
16243 *((uchar *)&eep_config + i) |=
16244 ((ADV_EEPROM_INTAB >> 8) & 0xFF);
16245 }
16246 } else {
16247 *((uchar *)&eep_config + i) =
16248 *((uchar *)&Default_38C1600_EEPROM_Config
16249 + i);
16250 }
16251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016252
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016253 /*
16254 * Assume the 6 byte board serial number that was read
16255 * from EEPROM is correct even if the EEPROM checksum
16256 * failed.
16257 */
16258 eep_config.serial_number_word3 =
16259 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016260
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016261 eep_config.serial_number_word2 =
16262 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016263
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016264 eep_config.serial_number_word1 =
16265 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016266
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016267 AdvSet38C1600EEPConfig(iop_base, &eep_config);
16268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016269
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016270 /*
16271 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
16272 * EEPROM configuration that was read.
16273 *
16274 * This is the mapping of EEPROM fields to Adv Library fields.
16275 */
16276 asc_dvc->wdtr_able = eep_config.wdtr_able;
16277 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
16278 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
16279 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
16280 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
16281 asc_dvc->ppr_able = 0;
16282 asc_dvc->tagqng_able = eep_config.tagqng_able;
16283 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
16284 asc_dvc->max_host_qng = eep_config.max_host_qng;
16285 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16286 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
16287 asc_dvc->start_motor = eep_config.start_motor;
16288 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
16289 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
16290 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016291
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016292 /*
16293 * For every Target ID if any of its 'sdtr_speed[1234]' bits
16294 * are set, then set an 'sdtr_able' bit for it.
16295 */
16296 asc_dvc->sdtr_able = 0;
16297 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
16298 if (tid == 0) {
16299 sdtr_speed = asc_dvc->sdtr_speed1;
16300 } else if (tid == 4) {
16301 sdtr_speed = asc_dvc->sdtr_speed2;
16302 } else if (tid == 8) {
16303 sdtr_speed = asc_dvc->sdtr_speed3;
16304 } else if (tid == 12) {
16305 sdtr_speed = asc_dvc->sdtr_speed4;
16306 }
16307 if (sdtr_speed & ASC_MAX_TID) {
16308 asc_dvc->sdtr_able |= (1 << tid);
16309 }
16310 sdtr_speed >>= 4;
16311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016312
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016313 /*
16314 * Set the host maximum queuing (max. 253, min. 16) and the per device
16315 * maximum queuing (max. 63, min. 4).
16316 */
16317 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
16318 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16319 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
16320 /* If the value is zero, assume it is uninitialized. */
16321 if (eep_config.max_host_qng == 0) {
16322 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16323 } else {
16324 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
16325 }
16326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016328 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
16329 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16330 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
16331 /* If the value is zero, assume it is uninitialized. */
16332 if (eep_config.max_dvc_qng == 0) {
16333 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16334 } else {
16335 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
16336 }
16337 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016338
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016339 /*
16340 * If 'max_dvc_qng' is greater than 'max_host_qng', then
16341 * set 'max_dvc_qng' to 'max_host_qng'.
16342 */
16343 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
16344 eep_config.max_dvc_qng = eep_config.max_host_qng;
16345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016346
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016347 /*
16348 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
16349 * values based on possibly adjusted EEPROM values.
16350 */
16351 asc_dvc->max_host_qng = eep_config.max_host_qng;
16352 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016353
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016354 /*
16355 * If the EEPROM 'termination' field is set to automatic (0), then set
16356 * the ASC_DVC_CFG 'termination' field to automatic also.
16357 *
16358 * If the termination is specified with a non-zero 'termination'
16359 * value check that a legal value is set and set the ASC_DVC_CFG
16360 * 'termination' field appropriately.
16361 */
16362 if (eep_config.termination_se == 0) {
16363 termination = 0; /* auto termination for SE */
16364 } else {
16365 /* Enable manual control with low off / high off. */
16366 if (eep_config.termination_se == 1) {
16367 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016368
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016369 /* Enable manual control with low off / high on. */
16370 } else if (eep_config.termination_se == 2) {
16371 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016372
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016373 /* Enable manual control with low on / high on. */
16374 } else if (eep_config.termination_se == 3) {
16375 termination = TERM_SE;
16376 } else {
16377 /*
16378 * The EEPROM 'termination_se' field contains a bad value.
16379 * Use automatic termination instead.
16380 */
16381 termination = 0;
16382 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16383 }
16384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016385
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016386 if (eep_config.termination_lvd == 0) {
16387 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
16388 } else {
16389 /* Enable manual control with low off / high off. */
16390 if (eep_config.termination_lvd == 1) {
16391 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016392
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016393 /* Enable manual control with low off / high on. */
16394 } else if (eep_config.termination_lvd == 2) {
16395 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016396
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016397 /* Enable manual control with low on / high on. */
16398 } else if (eep_config.termination_lvd == 3) {
16399 asc_dvc->cfg->termination = termination | TERM_LVD;
16400 } else {
16401 /*
16402 * The EEPROM 'termination_lvd' field contains a bad value.
16403 * Use automatic termination instead.
16404 */
16405 asc_dvc->cfg->termination = termination;
16406 warn_code |= ASC_WARN_EEPROM_TERMINATION;
16407 }
16408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016409
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016410 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016411}
16412
16413/*
16414 * Read EEPROM configuration into the specified buffer.
16415 *
16416 * Return a checksum based on the EEPROM configuration read.
16417 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016418static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070016419AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
16420{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016421 ushort wval, chksum;
16422 ushort *wbuf;
16423 int eep_addr;
16424 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016425
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016426 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
16427 wbuf = (ushort *)cfg_buf;
16428 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016429
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016430 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16431 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16432 wval = AdvReadEEPWord(iop_base, eep_addr);
16433 chksum += wval; /* Checksum is calculated from word values. */
16434 if (*charfields++) {
16435 *wbuf = le16_to_cpu(wval);
16436 } else {
16437 *wbuf = wval;
16438 }
16439 }
16440 /* Read checksum word. */
16441 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16442 wbuf++;
16443 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016444
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016445 /* Read rest of EEPROM not covered by the checksum. */
16446 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16447 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16448 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16449 if (*charfields++) {
16450 *wbuf = le16_to_cpu(*wbuf);
16451 }
16452 }
16453 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016454}
16455
16456/*
16457 * Read EEPROM configuration into the specified buffer.
16458 *
16459 * Return a checksum based on the EEPROM configuration read.
16460 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016461static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016462AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016463{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016464 ushort wval, chksum;
16465 ushort *wbuf;
16466 int eep_addr;
16467 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016468
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016469 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
16470 wbuf = (ushort *)cfg_buf;
16471 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016472
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016473 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16474 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16475 wval = AdvReadEEPWord(iop_base, eep_addr);
16476 chksum += wval; /* Checksum is calculated from word values. */
16477 if (*charfields++) {
16478 *wbuf = le16_to_cpu(wval);
16479 } else {
16480 *wbuf = wval;
16481 }
16482 }
16483 /* Read checksum word. */
16484 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16485 wbuf++;
16486 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016487
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016488 /* Read rest of EEPROM not covered by the checksum. */
16489 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16490 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16491 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16492 if (*charfields++) {
16493 *wbuf = le16_to_cpu(*wbuf);
16494 }
16495 }
16496 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016497}
16498
16499/*
16500 * Read EEPROM configuration into the specified buffer.
16501 *
16502 * Return a checksum based on the EEPROM configuration read.
16503 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016504static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016505AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016506{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016507 ushort wval, chksum;
16508 ushort *wbuf;
16509 int eep_addr;
16510 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016511
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016512 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
16513 wbuf = (ushort *)cfg_buf;
16514 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016515
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016516 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
16517 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
16518 wval = AdvReadEEPWord(iop_base, eep_addr);
16519 chksum += wval; /* Checksum is calculated from word values. */
16520 if (*charfields++) {
16521 *wbuf = le16_to_cpu(wval);
16522 } else {
16523 *wbuf = wval;
16524 }
16525 }
16526 /* Read checksum word. */
16527 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16528 wbuf++;
16529 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016530
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016531 /* Read rest of EEPROM not covered by the checksum. */
16532 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
16533 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
16534 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
16535 if (*charfields++) {
16536 *wbuf = le16_to_cpu(*wbuf);
16537 }
16538 }
16539 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016540}
16541
16542/*
16543 * Read the EEPROM from specified location
16544 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016545static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016546{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016547 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16548 ASC_EEP_CMD_READ | eep_word_addr);
16549 AdvWaitEEPCmd(iop_base);
16550 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016551}
16552
16553/*
16554 * Wait for EEPROM command to complete
16555 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016556static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016557{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016558 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016559
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016560 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
16561 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
16562 ASC_EEP_CMD_DONE) {
16563 break;
16564 }
16565 DvcSleepMilliSecond(1);
16566 }
16567 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
16568 0) {
16569 ASC_ASSERT(0);
16570 }
16571 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016572}
16573
16574/*
16575 * Write the EEPROM from 'cfg_buf'.
16576 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016577void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070016578AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
16579{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016580 ushort *wbuf;
16581 ushort addr, chksum;
16582 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016583
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016584 wbuf = (ushort *)cfg_buf;
16585 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
16586 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016588 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16589 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016590
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016591 /*
16592 * Write EEPROM from word 0 to word 20.
16593 */
16594 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16595 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16596 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016597
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016598 if (*charfields++) {
16599 word = cpu_to_le16(*wbuf);
16600 } else {
16601 word = *wbuf;
16602 }
16603 chksum += *wbuf; /* Checksum is calculated from word values. */
16604 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16605 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16606 ASC_EEP_CMD_WRITE | addr);
16607 AdvWaitEEPCmd(iop_base);
16608 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016610
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016611 /*
16612 * Write EEPROM checksum at word 21.
16613 */
16614 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16615 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16616 AdvWaitEEPCmd(iop_base);
16617 wbuf++;
16618 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016619
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016620 /*
16621 * Write EEPROM OEM name at words 22 to 29.
16622 */
16623 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16624 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16625 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016626
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016627 if (*charfields++) {
16628 word = cpu_to_le16(*wbuf);
16629 } else {
16630 word = *wbuf;
16631 }
16632 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16633 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16634 ASC_EEP_CMD_WRITE | addr);
16635 AdvWaitEEPCmd(iop_base);
16636 }
16637 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16638 AdvWaitEEPCmd(iop_base);
16639 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016640}
16641
16642/*
16643 * Write the EEPROM from 'cfg_buf'.
16644 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016645void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016646AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016647{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016648 ushort *wbuf;
16649 ushort *charfields;
16650 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016651
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016652 wbuf = (ushort *)cfg_buf;
16653 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
16654 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016655
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016656 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16657 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016658
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016659 /*
16660 * Write EEPROM from word 0 to word 20.
16661 */
16662 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16663 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16664 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016665
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016666 if (*charfields++) {
16667 word = cpu_to_le16(*wbuf);
16668 } else {
16669 word = *wbuf;
16670 }
16671 chksum += *wbuf; /* Checksum is calculated from word values. */
16672 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16673 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16674 ASC_EEP_CMD_WRITE | addr);
16675 AdvWaitEEPCmd(iop_base);
16676 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016678
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016679 /*
16680 * Write EEPROM checksum at word 21.
16681 */
16682 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16683 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16684 AdvWaitEEPCmd(iop_base);
16685 wbuf++;
16686 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016687
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016688 /*
16689 * Write EEPROM OEM name at words 22 to 29.
16690 */
16691 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16692 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16693 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016694
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016695 if (*charfields++) {
16696 word = cpu_to_le16(*wbuf);
16697 } else {
16698 word = *wbuf;
16699 }
16700 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16701 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16702 ASC_EEP_CMD_WRITE | addr);
16703 AdvWaitEEPCmd(iop_base);
16704 }
16705 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16706 AdvWaitEEPCmd(iop_base);
16707 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016708}
16709
16710/*
16711 * Write the EEPROM from 'cfg_buf'.
16712 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060016713void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016714AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016715{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016716 ushort *wbuf;
16717 ushort *charfields;
16718 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016719
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016720 wbuf = (ushort *)cfg_buf;
16721 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
16722 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016723
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016724 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
16725 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016726
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016727 /*
16728 * Write EEPROM from word 0 to word 20.
16729 */
16730 for (addr = ADV_EEP_DVC_CFG_BEGIN;
16731 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
16732 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016733
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016734 if (*charfields++) {
16735 word = cpu_to_le16(*wbuf);
16736 } else {
16737 word = *wbuf;
16738 }
16739 chksum += *wbuf; /* Checksum is calculated from word values. */
16740 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16741 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16742 ASC_EEP_CMD_WRITE | addr);
16743 AdvWaitEEPCmd(iop_base);
16744 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
16745 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016746
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016747 /*
16748 * Write EEPROM checksum at word 21.
16749 */
16750 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
16751 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
16752 AdvWaitEEPCmd(iop_base);
16753 wbuf++;
16754 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016755
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016756 /*
16757 * Write EEPROM OEM name at words 22 to 29.
16758 */
16759 for (addr = ADV_EEP_DVC_CTL_BEGIN;
16760 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
16761 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016762
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016763 if (*charfields++) {
16764 word = cpu_to_le16(*wbuf);
16765 } else {
16766 word = *wbuf;
16767 }
16768 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
16769 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
16770 ASC_EEP_CMD_WRITE | addr);
16771 AdvWaitEEPCmd(iop_base);
16772 }
16773 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
16774 AdvWaitEEPCmd(iop_base);
16775 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016776}
16777
16778/* a_advlib.c */
16779/*
16780 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
16781 *
16782 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
16783 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
16784 * RISC to notify it a new command is ready to be executed.
16785 *
16786 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
16787 * set to SCSI_MAX_RETRY.
16788 *
16789 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
16790 * for DMA addresses or math operations are byte swapped to little-endian
16791 * order.
16792 *
16793 * Return:
16794 * ADV_SUCCESS(1) - The request was successfully queued.
16795 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
16796 * request completes.
16797 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
16798 * host IC error.
16799 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016800static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016801{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016802 ulong last_int_level;
16803 AdvPortAddr iop_base;
16804 ADV_DCNT req_size;
16805 ADV_PADDR req_paddr;
16806 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016807
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016808 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070016809
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016810 /*
16811 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
16812 */
16813 if (scsiq->target_id > ADV_MAX_TID) {
16814 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
16815 scsiq->done_status = QD_WITH_ERROR;
16816 return ADV_ERROR;
16817 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016818
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016819 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016820
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016821 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070016822
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016823 /*
16824 * Allocate a carrier ensuring at least one carrier always
16825 * remains on the freelist and initialize fields.
16826 */
16827 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
16828 DvcLeaveCritical(last_int_level);
16829 return ADV_BUSY;
16830 }
16831 asc_dvc->carr_freelist = (ADV_CARR_T *)
16832 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
16833 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016834
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016835 /*
16836 * Set the carrier to be a stopper by setting 'next_vpa'
16837 * to the stopper value. The current stopper will be changed
16838 * below to point to the new stopper.
16839 */
16840 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016841
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016842 /*
16843 * Clear the ADV_SCSI_REQ_Q done flag.
16844 */
16845 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016847 req_size = sizeof(ADV_SCSI_REQ_Q);
16848 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
16849 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016850
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016851 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
16852 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070016853
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016854 /* Wait for assertion before making little-endian */
16855 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016857 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
16858 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
16859 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016860
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016861 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
16862 /*
16863 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
16864 * order during initialization.
16865 */
16866 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016867
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016868 /*
16869 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
16870 * the microcode. The newly allocated stopper will become the new
16871 * stopper.
16872 */
16873 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016874
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016875 /*
16876 * Set the 'next_vpa' pointer for the old stopper to be the
16877 * physical address of the new stopper. The RISC can only
16878 * follow physical addresses.
16879 */
16880 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016881
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016882 /*
16883 * Set the host adapter stopper pointer to point to the new carrier.
16884 */
16885 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016887 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
16888 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
16889 /*
16890 * Tickle the RISC to tell it to read its Command Queue Head pointer.
16891 */
16892 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
16893 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
16894 /*
16895 * Clear the tickle value. In the ASC-3550 the RISC flag
16896 * command 'clr_tickle_a' does not work unless the host
16897 * value is cleared.
16898 */
16899 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
16900 ADV_TICKLE_NOP);
16901 }
16902 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
16903 /*
16904 * Notify the RISC a carrier is ready by writing the physical
16905 * address of the new carrier stopper to the COMMA register.
16906 */
16907 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
16908 le32_to_cpu(new_carrp->carr_pa));
16909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016910
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016911 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016912
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016913 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016914}
16915
16916/*
16917 * Reset SCSI Bus and purge all outstanding requests.
16918 *
16919 * Return Value:
16920 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
16921 * ADV_FALSE(0) - Microcode command failed.
16922 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
16923 * may be hung which requires driver recovery.
16924 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016925static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016926{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016927 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016928
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016929 /*
16930 * Send the SCSI Bus Reset idle start idle command which asserts
16931 * the SCSI Bus Reset signal.
16932 */
16933 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
16934 if (status != ADV_TRUE) {
16935 return status;
16936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016937
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016938 /*
16939 * Delay for the specified SCSI Bus Reset hold time.
16940 *
16941 * The hold time delay is done on the host because the RISC has no
16942 * microsecond accurate timer.
16943 */
16944 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016945
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016946 /*
16947 * Send the SCSI Bus Reset end idle command which de-asserts
16948 * the SCSI Bus Reset signal and purges any pending requests.
16949 */
16950 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
16951 if (status != ADV_TRUE) {
16952 return status;
16953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016954
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016955 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070016956
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016957 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016958}
16959
16960/*
16961 * Reset chip and SCSI Bus.
16962 *
16963 * Return Value:
16964 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
16965 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
16966 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016967static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070016968{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016969 int status;
16970 ushort wdtr_able, sdtr_able, tagqng_able;
16971 ushort ppr_able = 0;
16972 uchar tid, max_cmd[ADV_MAX_TID + 1];
16973 AdvPortAddr iop_base;
16974 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016975
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016976 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016977
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016978 /*
16979 * Save current per TID negotiated values.
16980 */
16981 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16982 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16983 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
16984 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
16985 }
16986 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
16987 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
16988 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
16989 max_cmd[tid]);
16990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070016991
Matthew Wilcox27c868c2007-07-26 10:56:23 -040016992 /*
16993 * Force the AdvInitAsc3550/38C0800Driver() function to
16994 * perform a SCSI Bus Reset by clearing the BIOS signature word.
16995 * The initialization functions assumes a SCSI Bus Reset is not
16996 * needed if the BIOS signature word is present.
16997 */
16998 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
16999 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017000
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017001 /*
17002 * Stop chip and reset it.
17003 */
17004 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
17005 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
17006 DvcSleepMilliSecond(100);
17007 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
17008 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017009
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017010 /*
17011 * Reset Adv Library error code, if any, and try
17012 * re-initializing the chip.
17013 */
17014 asc_dvc->err_code = 0;
17015 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
17016 status = AdvInitAsc38C1600Driver(asc_dvc);
17017 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
17018 status = AdvInitAsc38C0800Driver(asc_dvc);
17019 } else {
17020 status = AdvInitAsc3550Driver(asc_dvc);
17021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017022
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017023 /* Translate initialization return value to status value. */
17024 if (status == 0) {
17025 status = ADV_TRUE;
17026 } else {
17027 status = ADV_FALSE;
17028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017029
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017030 /*
17031 * Restore the BIOS signature word.
17032 */
17033 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017034
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017035 /*
17036 * Restore per TID negotiated values.
17037 */
17038 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
17039 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
17040 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
17041 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
17042 }
17043 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
17044 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
17045 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
17046 max_cmd[tid]);
17047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017049 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017050}
17051
17052/*
17053 * Adv Library Interrupt Service Routine
17054 *
17055 * This function is called by a driver's interrupt service routine.
17056 * The function disables and re-enables interrupts.
17057 *
17058 * When a microcode idle command is completed, the ADV_DVC_VAR
17059 * 'idle_cmd_done' field is set to ADV_TRUE.
17060 *
17061 * Note: AdvISR() can be called when interrupts are disabled or even
17062 * when there is no hardware interrupt condition present. It will
17063 * always check for completed idle commands and microcode requests.
17064 * This is an important feature that shouldn't be changed because it
17065 * allows commands to be completed from polling mode loops.
17066 *
17067 * Return:
17068 * ADV_TRUE(1) - interrupt was pending
17069 * ADV_FALSE(0) - no interrupt was pending
17070 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017071static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017072{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017073 AdvPortAddr iop_base;
17074 uchar int_stat;
17075 ushort target_bit;
17076 ADV_CARR_T *free_carrp;
17077 ADV_VADDR irq_next_vpa;
17078 int flags;
17079 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017080
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017081 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070017082
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017083 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017084
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017085 /* Reading the register clears the interrupt. */
17086 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017087
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017088 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
17089 ADV_INTR_STATUS_INTRC)) == 0) {
17090 DvcLeaveCritical(flags);
17091 return ADV_FALSE;
17092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017093
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017094 /*
17095 * Notify the driver of an asynchronous microcode condition by
17096 * calling the ADV_DVC_VAR.async_callback function. The function
17097 * is passed the microcode ASC_MC_INTRB_CODE byte value.
17098 */
17099 if (int_stat & ADV_INTR_STATUS_INTRB) {
17100 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017102 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017103
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017104 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
17105 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
17106 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
17107 asc_dvc->carr_pending_cnt != 0) {
17108 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
17109 ADV_TICKLE_A);
17110 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
17111 AdvWriteByteRegister(iop_base,
17112 IOPB_TICKLE,
17113 ADV_TICKLE_NOP);
17114 }
17115 }
17116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017117
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017118 if (asc_dvc->async_callback != 0) {
17119 (*asc_dvc->async_callback) (asc_dvc, intrb_code);
17120 }
17121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017122
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017123 /*
17124 * Check if the IRQ stopper carrier contains a completed request.
17125 */
17126 while (((irq_next_vpa =
17127 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
17128 /*
17129 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
17130 * The RISC will have set 'areq_vpa' to a virtual address.
17131 *
17132 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
17133 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
17134 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
17135 * in AdvExeScsiQueue().
17136 */
17137 scsiq = (ADV_SCSI_REQ_Q *)
17138 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070017139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017140 /*
17141 * Request finished with good status and the queue was not
17142 * DMAed to host memory by the firmware. Set all status fields
17143 * to indicate good status.
17144 */
17145 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
17146 scsiq->done_status = QD_NO_ERROR;
17147 scsiq->host_status = scsiq->scsi_status = 0;
17148 scsiq->data_cnt = 0L;
17149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017150
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017151 /*
17152 * Advance the stopper pointer to the next carrier
17153 * ignoring the lower four bits. Free the previous
17154 * stopper carrier.
17155 */
17156 free_carrp = asc_dvc->irq_sp;
17157 asc_dvc->irq_sp = (ADV_CARR_T *)
17158 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070017159
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017160 free_carrp->next_vpa =
17161 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
17162 asc_dvc->carr_freelist = free_carrp;
17163 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017164
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017165 ASC_ASSERT(scsiq != NULL);
17166 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017167
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017168 /*
17169 * Clear request microcode control flag.
17170 */
17171 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017172
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017173 /*
17174 * If the command that completed was a SCSI INQUIRY and
17175 * LUN 0 was sent the command, then process the INQUIRY
17176 * command information for the device.
17177 *
17178 * Note: If data returned were either VPD or CmdDt data,
17179 * don't process the INQUIRY command information for
17180 * the device, otherwise may erroneously set *_able bits.
17181 */
17182 if (scsiq->done_status == QD_NO_ERROR &&
17183 scsiq->cdb[0] == INQUIRY &&
17184 scsiq->target_lun == 0 &&
17185 (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT)
17186 == ADV_INQ_RTN_STD_INQUIRY_DATA) {
17187 AdvInquiryHandling(asc_dvc, scsiq);
17188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017189
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017190 /*
17191 * Notify the driver of the completed request by passing
17192 * the ADV_SCSI_REQ_Q pointer to its callback function.
17193 */
17194 scsiq->a_flag |= ADV_SCSIQ_DONE;
17195 (*asc_dvc->isr_callback) (asc_dvc, scsiq);
17196 /*
17197 * Note: After the driver callback function is called, 'scsiq'
17198 * can no longer be referenced.
17199 *
17200 * Fall through and continue processing other completed
17201 * requests...
17202 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017203
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017204 /*
17205 * Disable interrupts again in case the driver inadvertently
17206 * enabled interrupts in its callback function.
17207 *
17208 * The DvcEnterCritical() return value is ignored, because
17209 * the 'flags' saved when AdvISR() was first entered will be
17210 * used to restore the interrupt flag on exit.
17211 */
17212 (void)DvcEnterCritical();
17213 }
17214 DvcLeaveCritical(flags);
17215 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017216}
17217
17218/*
17219 * Send an idle command to the chip and wait for completion.
17220 *
17221 * Command completion is polled for once per microsecond.
17222 *
17223 * The function can be called from anywhere including an interrupt handler.
17224 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
17225 * functions to prevent reentrancy.
17226 *
17227 * Return Values:
17228 * ADV_TRUE - command completed successfully
17229 * ADV_FALSE - command failed
17230 * ADV_ERROR - command timed out
17231 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017232static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070017233AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017234 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017235{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017236 ulong last_int_level;
17237 int result;
17238 ADV_DCNT i, j;
17239 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017241 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070017242
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017243 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017244
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017245 /*
17246 * Clear the idle command status which is set by the microcode
17247 * to a non-zero value to indicate when the command is completed.
17248 * The non-zero result is one of the IDLE_CMD_STATUS_* values
17249 * defined in a_advlib.h.
17250 */
17251 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017252
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017253 /*
17254 * Write the idle command value after the idle command parameter
17255 * has been written to avoid a race condition. If the order is not
17256 * followed, the microcode may process the idle command before the
17257 * parameters have been written to LRAM.
17258 */
17259 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
17260 cpu_to_le32(idle_cmd_parameter));
17261 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017262
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017263 /*
17264 * Tickle the RISC to tell it to process the idle command.
17265 */
17266 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
17267 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
17268 /*
17269 * Clear the tickle value. In the ASC-3550 the RISC flag
17270 * command 'clr_tickle_b' does not work unless the host
17271 * value is cleared.
17272 */
17273 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
17274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017275
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017276 /* Wait for up to 100 millisecond for the idle command to timeout. */
17277 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
17278 /* Poll once each microsecond for command completion. */
17279 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
17280 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
17281 result);
17282 if (result != 0) {
17283 DvcLeaveCritical(last_int_level);
17284 return result;
17285 }
17286 DvcDelayMicroSecond(asc_dvc, (ushort)1);
17287 }
17288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017289
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017290 ASC_ASSERT(0); /* The idle command should never timeout. */
17291 DvcLeaveCritical(last_int_level);
17292 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017293}
17294
17295/*
17296 * Inquiry Information Byte 7 Handling
17297 *
17298 * Handle SCSI Inquiry Command information for a device by setting
17299 * microcode operating variables that affect WDTR, SDTR, and Tag
17300 * Queuing.
17301 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017302static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017303{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017304 AdvPortAddr iop_base;
17305 uchar tid;
17306 ADV_SCSI_INQUIRY *inq;
17307 ushort tidmask;
17308 ushort cfg_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017309
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017310 /*
17311 * AdvInquiryHandling() requires up to INQUIRY information Byte 7
17312 * to be available.
17313 *
17314 * If less than 8 bytes of INQUIRY information were requested or less
17315 * than 8 bytes were transferred, then return. cdb[4] is the request
17316 * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
17317 * microcode to the transfer residual count.
17318 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017319
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017320 if (scsiq->cdb[4] < 8 ||
17321 (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) {
17322 return;
17323 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017324
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017325 iop_base = asc_dvc->iop_base;
17326 tid = scsiq->target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017328 inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070017329
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017330 /*
17331 * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
17332 */
17333 if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) {
17334 return;
17335 } else {
17336 /*
17337 * INQUIRY Byte 7 Handling
17338 *
17339 * Use a device's INQUIRY byte 7 to determine whether it
17340 * supports WDTR, SDTR, and Tag Queuing. If the feature
17341 * is enabled in the EEPROM and the device supports the
17342 * feature, then enable it in the microcode.
17343 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070017344
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017345 tidmask = ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017346
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017347 /*
17348 * Wide Transfers
17349 *
17350 * If the EEPROM enabled WDTR for the device and the device
17351 * supports wide bus (16 bit) transfers, then turn on the
17352 * device's 'wdtr_able' bit and write the new value to the
17353 * microcode.
17354 */
17355 if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) {
17356 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
17357 if ((cfg_word & tidmask) == 0) {
17358 cfg_word |= tidmask;
17359 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
17360 cfg_word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017362 /*
17363 * Clear the microcode "SDTR negotiation" and "WDTR
17364 * negotiation" done indicators for the target to cause
17365 * it to negotiate with the new setting set above.
17366 * WDTR when accepted causes the target to enter
17367 * asynchronous mode, so SDTR must be negotiated.
17368 */
17369 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE,
17370 cfg_word);
17371 cfg_word &= ~tidmask;
17372 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE,
17373 cfg_word);
17374 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE,
17375 cfg_word);
17376 cfg_word &= ~tidmask;
17377 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE,
17378 cfg_word);
17379 }
17380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017381
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017382 /*
17383 * Synchronous Transfers
17384 *
17385 * If the EEPROM enabled SDTR for the device and the device
17386 * supports synchronous transfers, then turn on the device's
17387 * 'sdtr_able' bit. Write the new value to the microcode.
17388 */
17389 if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) {
17390 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
17391 if ((cfg_word & tidmask) == 0) {
17392 cfg_word |= tidmask;
17393 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
17394 cfg_word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017396 /*
17397 * Clear the microcode "SDTR negotiation" done indicator
17398 * for the target to cause it to negotiate with the new
17399 * setting set above.
17400 */
17401 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE,
17402 cfg_word);
17403 cfg_word &= ~tidmask;
17404 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE,
17405 cfg_word);
17406 }
17407 }
17408 /*
17409 * If the Inquiry data included enough space for the SPI-3
17410 * Clocking field, then check if DT mode is supported.
17411 */
17412 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 &&
17413 (scsiq->cdb[4] >= 57 ||
17414 (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) {
17415 /*
17416 * PPR (Parallel Protocol Request) Capable
17417 *
17418 * If the device supports DT mode, then it must be PPR capable.
17419 * The PPR message will be used in place of the SDTR and WDTR
17420 * messages to negotiate synchronous speed and offset, transfer
17421 * width, and protocol options.
17422 */
17423 if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) {
17424 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE,
17425 asc_dvc->ppr_able);
17426 asc_dvc->ppr_able |= tidmask;
17427 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE,
17428 asc_dvc->ppr_able);
17429 }
17430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017431
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017432 /*
17433 * If the EEPROM enabled Tag Queuing for the device and the
17434 * device supports Tag Queueing, then turn on the device's
17435 * 'tagqng_enable' bit in the microcode and set the microcode
17436 * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
17437 * value.
17438 *
17439 * Tag Queuing is disabled for the BIOS which runs in polled
17440 * mode and would see no benefit from Tag Queuing. Also by
17441 * disabling Tag Queuing in the BIOS devices with Tag Queuing
17442 * bugs will at least work with the BIOS.
17443 */
17444 if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) {
17445 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
17446 cfg_word |= tidmask;
17447 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
17448 cfg_word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070017449
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017450 AdvWriteByteLram(iop_base,
17451 ASC_MC_NUMBER_OF_MAX_CMD + tid,
17452 asc_dvc->max_dvc_qng);
17453 }
17454 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070017455}
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017456
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017457static int __devinit
17458advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
17459{
17460 int req_cnt = 0;
17461 adv_req_t *reqp = NULL;
17462 int sg_cnt = 0;
17463 adv_sgblk_t *sgp;
17464 int warn_code, err_code;
17465
17466 /*
17467 * Allocate buffer carrier structures. The total size
17468 * is about 4 KB, so allocate all at once.
17469 */
17470 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
17471 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
17472
17473 if (!boardp->carrp)
17474 goto kmalloc_failed;
17475
17476 /*
17477 * Allocate up to 'max_host_qng' request structures for the Wide
17478 * board. The total size is about 16 KB, so allocate all at once.
17479 * If the allocation fails decrement and try again.
17480 */
17481 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
17482 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
17483
17484 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
17485 "bytes %lu\n", reqp, req_cnt,
17486 (ulong)sizeof(adv_req_t) * req_cnt);
17487
17488 if (reqp)
17489 break;
17490 }
17491
17492 if (!reqp)
17493 goto kmalloc_failed;
17494
17495 boardp->orig_reqp = reqp;
17496
17497 /*
17498 * Allocate up to ADV_TOT_SG_BLOCK request structures for
17499 * the Wide board. Each structure is about 136 bytes.
17500 */
17501 boardp->adv_sgblkp = NULL;
17502 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
17503 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
17504
17505 if (!sgp)
17506 break;
17507
17508 sgp->next_sgblkp = boardp->adv_sgblkp;
17509 boardp->adv_sgblkp = sgp;
17510
17511 }
17512
17513 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
17514 sg_cnt, sizeof(adv_sgblk_t),
17515 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
17516
17517 if (!boardp->adv_sgblkp)
17518 goto kmalloc_failed;
17519
17520 adv_dvc_varp->carrier_buf = boardp->carrp;
17521
17522 /*
17523 * Point 'adv_reqp' to the request structures and
17524 * link them together.
17525 */
17526 req_cnt--;
17527 reqp[req_cnt].next_reqp = NULL;
17528 for (; req_cnt > 0; req_cnt--) {
17529 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
17530 }
17531 boardp->adv_reqp = &reqp[0];
17532
17533 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
17534 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
17535 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
17536 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
17537 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
17538 "\n");
17539 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
17540 } else {
17541 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
17542 "\n");
17543 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
17544 }
17545 err_code = adv_dvc_varp->err_code;
17546
17547 if (warn_code || err_code) {
17548 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
17549 " error 0x%x\n", boardp->id, warn_code, err_code);
17550 }
17551
17552 goto exit;
17553
17554 kmalloc_failed:
17555 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
17556 "failed\n", boardp->id);
17557 err_code = ADV_ERROR;
17558 exit:
17559 return err_code;
17560}
17561
17562static void advansys_wide_free_mem(asc_board_t *boardp)
17563{
17564 kfree(boardp->carrp);
17565 boardp->carrp = NULL;
17566 kfree(boardp->orig_reqp);
17567 boardp->orig_reqp = boardp->adv_reqp = NULL;
17568 while (boardp->adv_sgblkp) {
17569 adv_sgblk_t *sgp = boardp->adv_sgblkp;
17570 boardp->adv_sgblkp = sgp->next_sgblkp;
17571 kfree(sgp);
17572 }
17573}
17574
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017575static struct Scsi_Host *__devinit
17576advansys_board_found(int iop, struct device *dev, int bus_type)
17577{
17578 struct Scsi_Host *shost;
17579 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
17580 asc_board_t *boardp;
17581 ASC_DVC_VAR *asc_dvc_varp = NULL;
17582 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017583 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017584 int iolen = 0;
17585 ADV_PADDR pci_memory_address;
17586 int warn_code, err_code;
17587 int ret;
17588
17589 /*
17590 * Adapter found.
17591 *
17592 * Register the adapter, get its configuration, and
17593 * initialize it.
17594 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060017595 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
17596 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017597
17598 if (!shost)
17599 return NULL;
17600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017601 /* Initialize private per board data */
17602 boardp = ASC_BOARDP(shost);
17603 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060017604 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017605
17606 /* Initialize spinlock. */
17607 spin_lock_init(&boardp->lock);
17608
17609 /*
17610 * Handle both narrow and wide boards.
17611 *
17612 * If a Wide board was detected, set the board structure
17613 * wide board flag. Set-up the board structure based on
17614 * the board type.
17615 */
17616#ifdef CONFIG_PCI
17617 if (bus_type == ASC_IS_PCI &&
17618 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
17619 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
17620 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
17621 boardp->flags |= ASC_IS_WIDE_BOARD;
17622 }
17623#endif /* CONFIG_PCI */
17624
17625 if (ASC_NARROW_BOARD(boardp)) {
17626 ASC_DBG(1, "advansys_board_found: narrow board\n");
17627 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
17628 asc_dvc_varp->bus_type = bus_type;
17629 asc_dvc_varp->drv_ptr = boardp;
17630 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
17631 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
17632 asc_dvc_varp->iop_base = iop;
17633 asc_dvc_varp->isr_callback = asc_isr_callback;
17634 } else {
17635 ASC_DBG(1, "advansys_board_found: wide board\n");
17636 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
17637 adv_dvc_varp->drv_ptr = boardp;
17638 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
17639 adv_dvc_varp->isr_callback = adv_isr_callback;
17640 adv_dvc_varp->async_callback = adv_async_callback;
17641#ifdef CONFIG_PCI
17642 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
17643 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
17644 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
17645 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
17646 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
17647 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
17648 } else {
17649 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
17650 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
17651 }
17652#endif /* CONFIG_PCI */
17653
17654 /*
17655 * Map the board's registers into virtual memory for
17656 * PCI slave access. Only memory accesses are used to
17657 * access the board's registers.
17658 *
17659 * Note: The PCI register base address is not always
17660 * page aligned, but the address passed to ioremap()
17661 * must be page aligned. It is guaranteed that the
17662 * PCI register base address will not cross a page
17663 * boundary.
17664 */
17665 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
17666 iolen = ADV_3550_IOLEN;
17667 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
17668 iolen = ADV_38C0800_IOLEN;
17669 } else {
17670 iolen = ADV_38C1600_IOLEN;
17671 }
17672#ifdef CONFIG_PCI
17673 pci_memory_address = pci_resource_start(pdev, 1);
17674 ASC_DBG1(1,
17675 "advansys_board_found: pci_memory_address: 0x%lx\n",
17676 (ulong)pci_memory_address);
17677 if ((boardp->ioremap_addr =
17678 ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) {
17679 ASC_PRINT3
17680 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
17681 boardp->id, pci_memory_address, iolen);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017682 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017683 }
17684 ASC_DBG1(1,
17685 "advansys_board_found: ioremap_addr: 0x%lx\n",
17686 (ulong)boardp->ioremap_addr);
17687 adv_dvc_varp->iop_base = (AdvPortAddr)
17688 (boardp->ioremap_addr +
17689 (pci_memory_address - (pci_memory_address & PAGE_MASK)));
17690 ASC_DBG1(1,
17691 "advansys_board_found: iop_base: 0x%lx\n",
17692 adv_dvc_varp->iop_base);
17693#endif /* CONFIG_PCI */
17694
17695 /*
17696 * Even though it isn't used to access wide boards, other
17697 * than for the debug line below, save I/O Port address so
17698 * that it can be reported.
17699 */
17700 boardp->ioport = iop;
17701
17702 ASC_DBG2(1,
17703 "advansys_board_found: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
17704 (ushort)inp(iop + 1), (ushort)inpw(iop));
17705 }
17706
17707#ifdef CONFIG_PROC_FS
17708 /*
17709 * Allocate buffer for printing information from
17710 * /proc/scsi/advansys/[0...].
17711 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017712 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
17713 if (!boardp->prtbuf) {
17714 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
17715 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
17716 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017717 }
17718#endif /* CONFIG_PROC_FS */
17719
17720 if (ASC_NARROW_BOARD(boardp)) {
17721 asc_dvc_varp->cfg->dev = dev;
17722 /*
17723 * Set the board bus type and PCI IRQ before
17724 * calling AscInitGetConfig().
17725 */
17726 switch (asc_dvc_varp->bus_type) {
17727#ifdef CONFIG_ISA
17728 case ASC_IS_ISA:
17729 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017730 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017731 break;
17732 case ASC_IS_VL:
17733 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017734 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017735 break;
17736 case ASC_IS_EISA:
17737 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017738 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017739 break;
17740#endif /* CONFIG_ISA */
17741#ifdef CONFIG_PCI
17742 case ASC_IS_PCI:
17743 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
17744 asc_dvc_varp->cfg->pci_slot_info =
17745 ASC_PCI_MKID(pdev->bus->number,
17746 PCI_SLOT(pdev->devfn),
17747 PCI_FUNC(pdev->devfn));
17748 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017749 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017750 break;
17751#endif /* CONFIG_PCI */
17752 default:
17753 ASC_PRINT2
17754 ("advansys_board_found: board %d: unknown adapter type: %d\n",
17755 boardp->id, asc_dvc_varp->bus_type);
17756 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017757 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017758 break;
17759 }
17760 } else {
17761 adv_dvc_varp->cfg->dev = dev;
17762 /*
17763 * For Wide boards set PCI information before calling
17764 * AdvInitGetConfig().
17765 */
17766#ifdef CONFIG_PCI
17767 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
17768 adv_dvc_varp->cfg->pci_slot_info =
17769 ASC_PCI_MKID(pdev->bus->number,
17770 PCI_SLOT(pdev->devfn),
17771 PCI_FUNC(pdev->devfn));
17772 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060017773 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017774#endif /* CONFIG_PCI */
17775 }
17776
17777 /*
17778 * Read the board configuration.
17779 */
17780 if (ASC_NARROW_BOARD(boardp)) {
17781 /*
17782 * NOTE: AscInitGetConfig() may change the board's
17783 * bus_type value. The bus_type value should no
17784 * longer be used. If the bus_type field must be
17785 * referenced only use the bit-wise AND operator "&".
17786 */
17787 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
17788 switch (ret = AscInitGetConfig(asc_dvc_varp)) {
17789 case 0: /* No error */
17790 break;
17791 case ASC_WARN_IO_PORT_ROTATE:
17792 ASC_PRINT1
17793 ("AscInitGetConfig: board %d: I/O port address modified\n",
17794 boardp->id);
17795 break;
17796 case ASC_WARN_AUTO_CONFIG:
17797 ASC_PRINT1
17798 ("AscInitGetConfig: board %d: I/O port increment switch enabled\n",
17799 boardp->id);
17800 break;
17801 case ASC_WARN_EEPROM_CHKSUM:
17802 ASC_PRINT1
17803 ("AscInitGetConfig: board %d: EEPROM checksum error\n",
17804 boardp->id);
17805 break;
17806 case ASC_WARN_IRQ_MODIFIED:
17807 ASC_PRINT1
17808 ("AscInitGetConfig: board %d: IRQ modified\n",
17809 boardp->id);
17810 break;
17811 case ASC_WARN_CMD_QNG_CONFLICT:
17812 ASC_PRINT1
17813 ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
17814 boardp->id);
17815 break;
17816 default:
17817 ASC_PRINT2
17818 ("AscInitGetConfig: board %d: unknown warning: 0x%x\n",
17819 boardp->id, ret);
17820 break;
17821 }
17822 if ((err_code = asc_dvc_varp->err_code) != 0) {
17823 ASC_PRINT3
17824 ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
17825 boardp->id,
17826 asc_dvc_varp->init_state, asc_dvc_varp->err_code);
17827 }
17828 } else {
17829 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
17830 if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
17831 ASC_PRINT2
17832 ("AdvInitGetConfig: board %d: warning: 0x%x\n",
17833 boardp->id, ret);
17834 }
17835 if ((err_code = adv_dvc_varp->err_code) != 0) {
17836 ASC_PRINT2
17837 ("AdvInitGetConfig: board %d error: err_code 0x%x\n",
17838 boardp->id, adv_dvc_varp->err_code);
17839 }
17840 }
17841
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017842 if (err_code != 0)
17843 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017844
17845 /*
17846 * Save the EEPROM configuration so that it can be displayed
17847 * from /proc/scsi/advansys/[0...].
17848 */
17849 if (ASC_NARROW_BOARD(boardp)) {
17850
17851 ASCEEP_CONFIG *ep;
17852
17853 /*
17854 * Set the adapter's target id bit in the 'init_tidmask' field.
17855 */
17856 boardp->init_tidmask |=
17857 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
17858
17859 /*
17860 * Save EEPROM settings for the board.
17861 */
17862 ep = &boardp->eep_config.asc_eep;
17863
17864 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
17865 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
17866 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
17867 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
17868 ep->start_motor = asc_dvc_varp->start_motor;
17869 ep->cntl = asc_dvc_varp->dvc_cntl;
17870 ep->no_scam = asc_dvc_varp->no_scam;
17871 ep->max_total_qng = asc_dvc_varp->max_total_qng;
17872 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
17873 /* 'max_tag_qng' is set to the same value for every device. */
17874 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
17875 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
17876 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
17877 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
17878 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
17879 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
17880 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
17881
17882 /*
17883 * Modify board configuration.
17884 */
17885 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
17886 switch (ret = AscInitSetConfig(asc_dvc_varp)) {
17887 case 0: /* No error. */
17888 break;
17889 case ASC_WARN_IO_PORT_ROTATE:
17890 ASC_PRINT1
17891 ("AscInitSetConfig: board %d: I/O port address modified\n",
17892 boardp->id);
17893 break;
17894 case ASC_WARN_AUTO_CONFIG:
17895 ASC_PRINT1
17896 ("AscInitSetConfig: board %d: I/O port increment switch enabled\n",
17897 boardp->id);
17898 break;
17899 case ASC_WARN_EEPROM_CHKSUM:
17900 ASC_PRINT1
17901 ("AscInitSetConfig: board %d: EEPROM checksum error\n",
17902 boardp->id);
17903 break;
17904 case ASC_WARN_IRQ_MODIFIED:
17905 ASC_PRINT1
17906 ("AscInitSetConfig: board %d: IRQ modified\n",
17907 boardp->id);
17908 break;
17909 case ASC_WARN_CMD_QNG_CONFLICT:
17910 ASC_PRINT1
17911 ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
17912 boardp->id);
17913 break;
17914 default:
17915 ASC_PRINT2
17916 ("AscInitSetConfig: board %d: unknown warning: 0x%x\n",
17917 boardp->id, ret);
17918 break;
17919 }
17920 if (asc_dvc_varp->err_code != 0) {
17921 ASC_PRINT3
17922 ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
17923 boardp->id,
17924 asc_dvc_varp->init_state, asc_dvc_varp->err_code);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060017925 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040017926 }
17927
17928 /*
17929 * Finish initializing the 'Scsi_Host' structure.
17930 */
17931 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
17932 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
17933 shost->irq = asc_dvc_varp->irq_no;
17934 }
17935 } else {
17936 ADVEEP_3550_CONFIG *ep_3550;
17937 ADVEEP_38C0800_CONFIG *ep_38C0800;
17938 ADVEEP_38C1600_CONFIG *ep_38C1600;
17939
17940 /*
17941 * Save Wide EEP Configuration Information.
17942 */
17943 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
17944 ep_3550 = &boardp->eep_config.adv_3550_eep;
17945
17946 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
17947 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
17948 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
17949 ep_3550->termination = adv_dvc_varp->cfg->termination;
17950 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
17951 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
17952 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
17953 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
17954 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
17955 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
17956 ep_3550->start_motor = adv_dvc_varp->start_motor;
17957 ep_3550->scsi_reset_delay =
17958 adv_dvc_varp->scsi_reset_wait;
17959 ep_3550->serial_number_word1 =
17960 adv_dvc_varp->cfg->serial1;
17961 ep_3550->serial_number_word2 =
17962 adv_dvc_varp->cfg->serial2;
17963 ep_3550->serial_number_word3 =
17964 adv_dvc_varp->cfg->serial3;
17965 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
17966 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
17967
17968 ep_38C0800->adapter_scsi_id =
17969 adv_dvc_varp->chip_scsi_id;
17970 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
17971 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
17972 ep_38C0800->termination_lvd =
17973 adv_dvc_varp->cfg->termination;
17974 ep_38C0800->disc_enable =
17975 adv_dvc_varp->cfg->disc_enable;
17976 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
17977 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
17978 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
17979 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
17980 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
17981 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
17982 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
17983 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
17984 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
17985 ep_38C0800->scsi_reset_delay =
17986 adv_dvc_varp->scsi_reset_wait;
17987 ep_38C0800->serial_number_word1 =
17988 adv_dvc_varp->cfg->serial1;
17989 ep_38C0800->serial_number_word2 =
17990 adv_dvc_varp->cfg->serial2;
17991 ep_38C0800->serial_number_word3 =
17992 adv_dvc_varp->cfg->serial3;
17993 } else {
17994 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
17995
17996 ep_38C1600->adapter_scsi_id =
17997 adv_dvc_varp->chip_scsi_id;
17998 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
17999 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
18000 ep_38C1600->termination_lvd =
18001 adv_dvc_varp->cfg->termination;
18002 ep_38C1600->disc_enable =
18003 adv_dvc_varp->cfg->disc_enable;
18004 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
18005 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
18006 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
18007 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
18008 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
18009 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
18010 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
18011 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
18012 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
18013 ep_38C1600->scsi_reset_delay =
18014 adv_dvc_varp->scsi_reset_wait;
18015 ep_38C1600->serial_number_word1 =
18016 adv_dvc_varp->cfg->serial1;
18017 ep_38C1600->serial_number_word2 =
18018 adv_dvc_varp->cfg->serial2;
18019 ep_38C1600->serial_number_word3 =
18020 adv_dvc_varp->cfg->serial3;
18021 }
18022
18023 /*
18024 * Set the adapter's target id bit in the 'init_tidmask' field.
18025 */
18026 boardp->init_tidmask |=
18027 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
18028
18029 /*
18030 * Finish initializing the 'Scsi_Host' structure.
18031 */
18032 shost->irq = adv_dvc_varp->irq_no;
18033 }
18034
18035 /*
18036 * Channels are numbered beginning with 0. For AdvanSys one host
18037 * structure supports one channel. Multi-channel boards have a
18038 * separate host structure for each channel.
18039 */
18040 shost->max_channel = 0;
18041 if (ASC_NARROW_BOARD(boardp)) {
18042 shost->max_id = ASC_MAX_TID + 1;
18043 shost->max_lun = ASC_MAX_LUN + 1;
18044
18045 shost->io_port = asc_dvc_varp->iop_base;
18046 boardp->asc_n_io_port = ASC_IOADR_GAP;
18047 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
18048
18049 /* Set maximum number of queues the adapter can handle. */
18050 shost->can_queue = asc_dvc_varp->max_total_qng;
18051 } else {
18052 shost->max_id = ADV_MAX_TID + 1;
18053 shost->max_lun = ADV_MAX_LUN + 1;
18054
18055 /*
18056 * Save the I/O Port address and length even though
18057 * I/O ports are not used to access Wide boards.
18058 * Instead the Wide boards are accessed with
18059 * PCI Memory Mapped I/O.
18060 */
18061 shost->io_port = iop;
18062 boardp->asc_n_io_port = iolen;
18063
18064 shost->this_id = adv_dvc_varp->chip_scsi_id;
18065
18066 /* Set maximum number of queues the adapter can handle. */
18067 shost->can_queue = adv_dvc_varp->max_host_qng;
18068 }
18069
18070 /*
18071 * 'n_io_port' currently is one byte.
18072 *
18073 * Set a value to 'n_io_port', but never referenced it because
18074 * it may be truncated.
18075 */
18076 shost->n_io_port = boardp->asc_n_io_port <= 255 ?
18077 boardp->asc_n_io_port : 255;
18078
18079 /*
18080 * Following v1.3.89, 'cmd_per_lun' is no longer needed
18081 * and should be set to zero.
18082 *
18083 * But because of a bug introduced in v1.3.89 if the driver is
18084 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
18085 * SCSI function 'allocate_device' will panic. To allow the driver
18086 * to work as a module in these kernels set 'cmd_per_lun' to 1.
18087 *
18088 * Note: This is wrong. cmd_per_lun should be set to the depth
18089 * you want on untagged devices always.
18090 #ifdef MODULE
18091 */
18092 shost->cmd_per_lun = 1;
18093/* #else
18094 shost->cmd_per_lun = 0;
18095#endif */
18096
18097 /*
18098 * Set the maximum number of scatter-gather elements the
18099 * adapter can handle.
18100 */
18101 if (ASC_NARROW_BOARD(boardp)) {
18102 /*
18103 * Allow two commands with 'sg_tablesize' scatter-gather
18104 * elements to be executed simultaneously. This value is
18105 * the theoretical hardware limit. It may be decreased
18106 * below.
18107 */
18108 shost->sg_tablesize =
18109 (((asc_dvc_varp->max_total_qng - 2) / 2) *
18110 ASC_SG_LIST_PER_Q) + 1;
18111 } else {
18112 shost->sg_tablesize = ADV_MAX_SG_LIST;
18113 }
18114
18115 /*
18116 * The value of 'sg_tablesize' can not exceed the SCSI
18117 * mid-level driver definition of SG_ALL. SG_ALL also
18118 * must not be exceeded, because it is used to define the
18119 * size of the scatter-gather table in 'struct asc_sg_head'.
18120 */
18121 if (shost->sg_tablesize > SG_ALL) {
18122 shost->sg_tablesize = SG_ALL;
18123 }
18124
18125 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
18126
18127 /* BIOS start address. */
18128 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018129 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
18130 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018131 } else {
18132 /*
18133 * Fill-in BIOS board variables. The Wide BIOS saves
18134 * information in LRAM that is used by the driver.
18135 */
18136 AdvReadWordLram(adv_dvc_varp->iop_base,
18137 BIOS_SIGNATURE, boardp->bios_signature);
18138 AdvReadWordLram(adv_dvc_varp->iop_base,
18139 BIOS_VERSION, boardp->bios_version);
18140 AdvReadWordLram(adv_dvc_varp->iop_base,
18141 BIOS_CODESEG, boardp->bios_codeseg);
18142 AdvReadWordLram(adv_dvc_varp->iop_base,
18143 BIOS_CODELEN, boardp->bios_codelen);
18144
18145 ASC_DBG2(1,
18146 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
18147 boardp->bios_signature, boardp->bios_version);
18148
18149 ASC_DBG2(1,
18150 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
18151 boardp->bios_codeseg, boardp->bios_codelen);
18152
18153 /*
18154 * If the BIOS saved a valid signature, then fill in
18155 * the BIOS code segment base address.
18156 */
18157 if (boardp->bios_signature == 0x55AA) {
18158 /*
18159 * Convert x86 realmode code segment to a linear
18160 * address by shifting left 4.
18161 */
18162 shost->base = ((ulong)boardp->bios_codeseg << 4);
18163 } else {
18164 shost->base = 0;
18165 }
18166 }
18167
18168 /*
18169 * Register Board Resources - I/O Port, DMA, IRQ
18170 */
18171
18172 /*
18173 * Register I/O port range.
18174 *
18175 * For Wide boards the I/O ports are not used to access
18176 * the board, but request the region anyway.
18177 *
18178 * 'shost->n_io_port' is not referenced, because it may be truncated.
18179 */
18180 ASC_DBG2(2,
18181 "advansys_board_found: request_region port 0x%lx, len 0x%x\n",
18182 (ulong)shost->io_port, boardp->asc_n_io_port);
18183 if (request_region(shost->io_port, boardp->asc_n_io_port,
18184 "advansys") == NULL) {
18185 ASC_PRINT3
18186 ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n",
18187 boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018188 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018189 }
18190
18191 /* Register DMA Channel for Narrow boards. */
18192 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
18193#ifdef CONFIG_ISA
18194 if (ASC_NARROW_BOARD(boardp)) {
18195 /* Register DMA channel for ISA bus. */
18196 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
18197 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018198 ret = request_dma(shost->dma_channel, "advansys");
18199 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018200 ASC_PRINT3
18201 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
18202 boardp->id, shost->dma_channel, ret);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018203 goto err_free_region;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018204 }
18205 AscEnableIsaDma(shost->dma_channel);
18206 }
18207 }
18208#endif /* CONFIG_ISA */
18209
18210 /* Register IRQ Number. */
18211 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060018212
18213 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
18214 "advansys", shost);
18215
18216 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018217 if (ret == -EBUSY) {
18218 ASC_PRINT2
18219 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
18220 boardp->id, shost->irq);
18221 } else if (ret == -EINVAL) {
18222 ASC_PRINT2
18223 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
18224 boardp->id, shost->irq);
18225 } else {
18226 ASC_PRINT3
18227 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
18228 boardp->id, shost->irq, ret);
18229 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018230 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018231 }
18232
18233 /*
18234 * Initialize board RISC chip and enable interrupts.
18235 */
18236 if (ASC_NARROW_BOARD(boardp)) {
18237 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
18238 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
18239 err_code = asc_dvc_varp->err_code;
18240
18241 if (warn_code || err_code) {
18242 ASC_PRINT4
18243 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
18244 boardp->id,
18245 asc_dvc_varp->init_state, warn_code, err_code);
18246 }
18247 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018248 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018249 }
18250
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018251 if (err_code != 0)
18252 goto err_free_wide_mem;
18253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018254 ASC_DBG_PRT_SCSI_HOST(2, shost);
18255
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018256 ret = scsi_add_host(shost, dev);
18257 if (ret)
18258 goto err_free_wide_mem;
18259
18260 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018261 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018262
18263 err_free_wide_mem:
18264 advansys_wide_free_mem(boardp);
18265 free_irq(shost->irq, shost);
18266 err_free_dma:
18267 if (shost->dma_channel != NO_ISA_DMA)
18268 free_dma(shost->dma_channel);
18269 err_free_region:
18270 release_region(shost->io_port, boardp->asc_n_io_port);
18271 err_free_proc:
18272 kfree(boardp->prtbuf);
18273 err_unmap:
18274 if (boardp->ioremap_addr)
18275 iounmap(boardp->ioremap_addr);
18276 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018277 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018278 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018279}
18280
18281/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018282 * advansys_release()
18283 *
18284 * Release resources allocated for a single AdvanSys adapter.
18285 */
18286static int advansys_release(struct Scsi_Host *shost)
18287{
18288 asc_board_t *boardp;
18289
18290 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018291 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018292 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060018293 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018294 if (shost->dma_channel != NO_ISA_DMA) {
18295 ASC_DBG(1, "advansys_release: free_dma()\n");
18296 free_dma(shost->dma_channel);
18297 }
18298 release_region(shost->io_port, boardp->asc_n_io_port);
18299 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018300 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060018301 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018302 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018303 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018304 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018305 ASC_DBG(1, "advansys_release: end\n");
18306 return 0;
18307}
18308
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060018309static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
18310 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
18311 0x0210, 0x0230, 0x0250, 0x0330
18312};
18313
18314static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
18315{
18316 PortAddr iop_base = _asc_def_iop_base[id];
18317 struct Scsi_Host *shost;
18318
18319 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
18320 ASC_DBG1(1, "advansys_isa_match: check_region() failed "
18321 "I/O port 0x%x\n", iop_base);
18322 return -ENODEV;
18323 }
18324 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
18325 release_region(iop_base, ASC_IOADR_GAP);
18326 if (!AscFindSignature(iop_base))
18327 goto nodev;
18328 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
18329 goto nodev;
18330
18331 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
18332
18333 if (!shost)
18334 goto nodev;
18335
18336 dev_set_drvdata(dev, shost);
18337 return 0;
18338
18339 nodev:
18340 return -ENODEV;
18341}
18342
18343static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
18344{
18345 advansys_release(dev_get_drvdata(dev));
18346 return 0;
18347}
18348
18349static struct isa_driver advansys_isa_driver = {
18350 .probe = advansys_isa_probe,
18351 .remove = __devexit_p(advansys_isa_remove),
18352 .driver = {
18353 .owner = THIS_MODULE,
18354 .name = "advansys",
18355 },
18356};
18357
18358static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
18359{
18360 PortAddr iop_base = _asc_def_iop_base[id];
18361 struct Scsi_Host *shost;
18362
18363 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
18364 ASC_DBG1(1, "advansys_vlb_match: check_region() failed "
18365 "I/O port 0x%x\n", iop_base);
18366 return -ENODEV;
18367 }
18368 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
18369 release_region(iop_base, ASC_IOADR_GAP);
18370 if (!AscFindSignature(iop_base))
18371 goto nodev;
18372 /*
18373 * I don't think this condition can actually happen, but the old
18374 * driver did it, and the chances of finding a VLB setup in 2007
18375 * to do testing with is slight to none.
18376 */
18377 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
18378 goto nodev;
18379
18380 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
18381
18382 if (!shost)
18383 goto nodev;
18384
18385 dev_set_drvdata(dev, shost);
18386 return 0;
18387
18388 nodev:
18389 return -ENODEV;
18390}
18391
18392static struct isa_driver advansys_vlb_driver = {
18393 .probe = advansys_vlb_probe,
18394 .remove = __devexit_p(advansys_isa_remove),
18395 .driver = {
18396 .owner = THIS_MODULE,
18397 .name = "advansys",
18398 },
18399};
18400
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060018401static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
18402 { "ABP7401" },
18403 { "ABP7501" },
18404 { "" }
18405};
18406
18407MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
18408
18409/*
18410 * EISA is a little more tricky than PCI; each EISA device may have two
18411 * channels, and this driver is written to make each channel its own Scsi_Host
18412 */
18413struct eisa_scsi_data {
18414 struct Scsi_Host *host[2];
18415};
18416
18417static int __devinit advansys_eisa_probe(struct device *dev)
18418{
18419 int i, ioport;
18420 int err;
18421 struct eisa_device *edev = to_eisa_device(dev);
18422 struct eisa_scsi_data *data;
18423
18424 err = -ENOMEM;
18425 data = kzalloc(sizeof(*data), GFP_KERNEL);
18426 if (!data)
18427 goto fail;
18428 ioport = edev->base_addr + 0xc30;
18429
18430 err = -ENODEV;
18431 for (i = 0; i < 2; i++, ioport += 0x20) {
18432 if (!AscFindSignature(ioport))
18433 continue;
18434 /*
18435 * I don't know why we need to do this for EISA chips, but
18436 * not for any others. It looks to be equivalent to
18437 * AscGetChipCfgMsw, but I may have overlooked something,
18438 * so I'm not converting it until I get an EISA board to
18439 * test with.
18440 */
18441 inw(ioport + 4);
18442 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
18443 if (data->host[i])
18444 err = 0;
18445 }
18446
18447 if (err) {
18448 kfree(data);
18449 } else {
18450 dev_set_drvdata(dev, data);
18451 }
18452
18453 fail:
18454 return err;
18455}
18456
18457static __devexit int advansys_eisa_remove(struct device *dev)
18458{
18459 int i;
18460 struct eisa_scsi_data *data = dev_get_drvdata(dev);
18461
18462 for (i = 0; i < 2; i++) {
18463 struct Scsi_Host *shost = data->host[i];
18464 if (!shost)
18465 continue;
18466 advansys_release(shost);
18467 }
18468
18469 kfree(data);
18470 return 0;
18471}
18472
18473static struct eisa_driver advansys_eisa_driver = {
18474 .id_table = advansys_eisa_table,
18475 .driver = {
18476 .name = "advansys",
18477 .probe = advansys_eisa_probe,
18478 .remove = __devexit_p(advansys_eisa_remove),
18479 }
18480};
18481
Dave Jones2672ea82006-08-02 17:11:49 -040018482/* PCI Devices supported by this driver */
18483static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018484 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
18485 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
18486 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
18487 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
18488 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
18489 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
18490 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
18491 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
18492 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
18493 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
18494 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
18495 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
18496 {}
Dave Jones2672ea82006-08-02 17:11:49 -040018497};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040018498
Dave Jones2672ea82006-08-02 17:11:49 -040018499MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060018500
18501static int __devinit
18502advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
18503{
18504 int err, ioport;
18505 struct Scsi_Host *shost;
18506
18507 err = pci_enable_device(pdev);
18508 if (err)
18509 goto fail;
18510
18511 if (pci_resource_len(pdev, 0) == 0)
18512 goto nodev;
18513
18514 ioport = pci_resource_start(pdev, 0);
18515 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
18516
18517 if (!shost)
18518 goto nodev;
18519
18520 pci_set_drvdata(pdev, shost);
18521 return 0;
18522
18523 nodev:
18524 err = -ENODEV;
18525 pci_disable_device(pdev);
18526 fail:
18527 return err;
18528}
18529
18530static void __devexit advansys_pci_remove(struct pci_dev *pdev)
18531{
18532 advansys_release(pci_get_drvdata(pdev));
18533 pci_disable_device(pdev);
18534}
18535
18536static struct pci_driver advansys_pci_driver = {
18537 .name = "advansys",
18538 .id_table = advansys_pci_tbl,
18539 .probe = advansys_pci_probe,
18540 .remove = __devexit_p(advansys_pci_remove),
18541};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040018542
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018543static int __init advansys_init(void)
18544{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060018545 int error;
18546
18547 error = isa_register_driver(&advansys_isa_driver,
18548 ASC_IOADR_TABLE_MAX_IX);
18549 if (error)
18550 goto fail;
18551
18552 error = isa_register_driver(&advansys_vlb_driver,
18553 ASC_IOADR_TABLE_MAX_IX);
18554 if (error)
18555 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060018556
18557 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060018558 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060018559 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018560
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060018561 error = pci_register_driver(&advansys_pci_driver);
18562 if (error)
18563 goto unregister_eisa;
18564
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018565 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060018566
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060018567 unregister_eisa:
18568 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060018569 unregister_vlb:
18570 isa_unregister_driver(&advansys_vlb_driver);
18571 unregister_isa:
18572 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060018573 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060018574 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018575}
18576
18577static void __exit advansys_exit(void)
18578{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060018579 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060018580 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060018581 isa_unregister_driver(&advansys_vlb_driver);
18582 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060018583}
18584
18585module_init(advansys_init);
18586module_exit(advansys_exit);
18587
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040018588MODULE_LICENSE("GPL");