blob: 67cdfe6201cea2210eb81092cb39ca4d22d92870 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/string.h>
25#include <linux/kernel.h>
26#include <linux/types.h>
27#include <linux/ioport.h>
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <linux/slab.h>
31#include <linux/mm.h>
32#include <linux/proc_fs.h>
33#include <linux/init.h>
34#include <linux/blkdev.h>
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060035#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060036#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040037#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/spinlock.h>
39#include <linux/dma-mapping.h>
40
41#include <asm/io.h>
42#include <asm/system.h>
43#include <asm/dma.h>
44
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040045#include <scsi/scsi_cmnd.h>
46#include <scsi/scsi_device.h>
47#include <scsi/scsi_tcq.h>
48#include <scsi/scsi.h>
49#include <scsi/scsi_host.h>
50
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060051/* FIXME:
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 *
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060053 * 1. Although all of the necessary command mapping places have the
54 * appropriate dma_map.. APIs, the driver still processes its internal
55 * queue using bus_to_virt() and virt_to_bus() which are illegal under
56 * the API. The entire queue processing structure will need to be
57 * altered to fix this.
58 * 2. Need to add memory mapping workaround. Test the memory mapping.
59 * If it doesn't work revert to I/O port access. Can a test be done
60 * safely?
61 * 3. Handle an interrupt not working. Keep an interrupt counter in
62 * the interrupt handler. In the timeout function if the interrupt
63 * has not occurred then print a message and run in polled mode.
64 * 4. Need to add support for target mode commands, cf. CAM XPT.
65 * 5. check DMA mapping functions for failure
Matthew Wilcox349d2c42007-09-09 08:56:34 -060066 * 6. Use scsi_transport_spi
67 * 7. advansys_info is not safe against multiple simultaneous callers
68 * 8. Kill boardp->id
69 * 9. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 */
71#warning this driver is still not properly converted to the DMA API
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073/* Enable driver assertions. */
74#define ADVANSYS_ASSERT
75
76/* Enable driver /proc statistics. */
77#define ADVANSYS_STATS
78
79/* Enable driver tracing. */
80/* #define ADVANSYS_DEBUG */
81
Linus Torvalds1da177e2005-04-16 15:20:36 -070082/*
83 * --- Asc Library Constants and Macros
84 */
85
86#define ASC_LIB_VERSION_MAJOR 1
87#define ASC_LIB_VERSION_MINOR 24
88#define ASC_LIB_SERIAL_NUMBER 123
89
90/*
91 * Portable Data Types
92 *
93 * Any instance where a 32-bit long or pointer type is assumed
94 * for precision or HW defined structures, the following define
95 * types must be used. In Linux the char, short, and int types
96 * are all consistent at 8, 16, and 32 bits respectively. Pointers
97 * and long types are 64 bits on Alpha and UltraSPARC.
98 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040099#define ASC_PADDR __u32 /* Physical/Bus address data type. */
100#define ASC_VADDR __u32 /* Virtual address data type. */
101#define ASC_DCNT __u32 /* Unsigned Data count type. */
102#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104/*
105 * These macros are used to convert a virtual address to a
106 * 32-bit value. This currently can be used on Linux Alpha
107 * which uses 64-bit virtual address but a 32-bit bus address.
108 * This is likely to break in the future, but doing this now
109 * will give us time to change the HW and FW to handle 64-bit
110 * addresses.
111 */
112#define ASC_VADDR_TO_U32 virt_to_bus
113#define ASC_U32_TO_VADDR bus_to_virt
114
115typedef unsigned char uchar;
116
117#ifndef TRUE
118#define TRUE (1)
119#endif
120#ifndef FALSE
121#define FALSE (0)
122#endif
123
124#define EOF (-1)
125#define ERR (-1)
126#define UW_ERR (uint)(0xFFFF)
127#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
129#define ASC_DVCLIB_CALL_DONE (1)
130#define ASC_DVCLIB_CALL_FAILED (0)
131#define ASC_DVCLIB_CALL_ERROR (-1)
132
Dave Jones2672ea82006-08-02 17:11:49 -0400133#define PCI_VENDOR_ID_ASP 0x10cd
134#define PCI_DEVICE_ID_ASP_1200A 0x1100
135#define PCI_DEVICE_ID_ASP_ABP940 0x1200
136#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
137#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
138#define PCI_DEVICE_ID_38C0800_REV1 0x2500
139#define PCI_DEVICE_ID_38C1600_REV1 0x2700
140
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141/*
142 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
143 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
144 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
145 * SRB structure.
146 */
147#define CC_VERY_LONG_SG_LIST 0
148#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
149
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400150#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151#define inp(port) inb(port)
152#define outp(port, byte) outb((byte), (port))
153
154#define inpw(port) inw(port)
155#define outpw(port, word) outw((word), (port))
156
157#define ASC_MAX_SG_QUEUE 7
158#define ASC_MAX_SG_LIST 255
159
160#define ASC_CS_TYPE unsigned short
161
162#define ASC_IS_ISA (0x0001)
163#define ASC_IS_ISAPNP (0x0081)
164#define ASC_IS_EISA (0x0002)
165#define ASC_IS_PCI (0x0004)
166#define ASC_IS_PCI_ULTRA (0x0104)
167#define ASC_IS_PCMCIA (0x0008)
168#define ASC_IS_MCA (0x0020)
169#define ASC_IS_VL (0x0040)
170#define ASC_ISA_PNP_PORT_ADDR (0x279)
171#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
172#define ASC_IS_WIDESCSI_16 (0x0100)
173#define ASC_IS_WIDESCSI_32 (0x0200)
174#define ASC_IS_BIG_ENDIAN (0x8000)
175#define ASC_CHIP_MIN_VER_VL (0x01)
176#define ASC_CHIP_MAX_VER_VL (0x07)
177#define ASC_CHIP_MIN_VER_PCI (0x09)
178#define ASC_CHIP_MAX_VER_PCI (0x0F)
179#define ASC_CHIP_VER_PCI_BIT (0x08)
180#define ASC_CHIP_MIN_VER_ISA (0x11)
181#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
182#define ASC_CHIP_MAX_VER_ISA (0x27)
183#define ASC_CHIP_VER_ISA_BIT (0x30)
184#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
185#define ASC_CHIP_VER_ASYN_BUG (0x21)
186#define ASC_CHIP_VER_PCI 0x08
187#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
188#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
189#define ASC_CHIP_MIN_VER_EISA (0x41)
190#define ASC_CHIP_MAX_VER_EISA (0x47)
191#define ASC_CHIP_VER_EISA_BIT (0x40)
192#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
193#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
194#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
195#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
196#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
197#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
198#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
199#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
200#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
201#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
202#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
203
204#define ASC_SCSI_ID_BITS 3
205#define ASC_SCSI_TIX_TYPE uchar
206#define ASC_ALL_DEVICE_BIT_SET 0xFF
207#define ASC_SCSI_BIT_ID_TYPE uchar
208#define ASC_MAX_TID 7
209#define ASC_MAX_LUN 7
210#define ASC_SCSI_WIDTH_BIT_SET 0xFF
211#define ASC_MAX_SENSE_LEN 32
212#define ASC_MIN_SENSE_LEN 14
213#define ASC_MAX_CDB_LEN 12
214#define ASC_SCSI_RESET_HOLD_TIME_US 60
215
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216/*
217 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
218 * and CmdDt (Command Support Data) field bit definitions.
219 */
220#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
221#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
222#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
223#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
224
225#define ASC_SCSIDIR_NOCHK 0x00
226#define ASC_SCSIDIR_T2H 0x08
227#define ASC_SCSIDIR_H2T 0x10
228#define ASC_SCSIDIR_NODATA 0x18
229#define SCSI_ASC_NOMEDIA 0x3A
230#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
231#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
232#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
233#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237#define ASC_SG_LIST_PER_Q 7
238#define QS_FREE 0x00
239#define QS_READY 0x01
240#define QS_DISC1 0x02
241#define QS_DISC2 0x04
242#define QS_BUSY 0x08
243#define QS_ABORTED 0x40
244#define QS_DONE 0x80
245#define QC_NO_CALLBACK 0x01
246#define QC_SG_SWAP_QUEUE 0x02
247#define QC_SG_HEAD 0x04
248#define QC_DATA_IN 0x08
249#define QC_DATA_OUT 0x10
250#define QC_URGENT 0x20
251#define QC_MSG_OUT 0x40
252#define QC_REQ_SENSE 0x80
253#define QCSG_SG_XFER_LIST 0x02
254#define QCSG_SG_XFER_MORE 0x04
255#define QCSG_SG_XFER_END 0x08
256#define QD_IN_PROGRESS 0x00
257#define QD_NO_ERROR 0x01
258#define QD_ABORTED_BY_HOST 0x02
259#define QD_WITH_ERROR 0x04
260#define QD_INVALID_REQUEST 0x80
261#define QD_INVALID_HOST_NUM 0x81
262#define QD_INVALID_DEVICE 0x82
263#define QD_ERR_INTERNAL 0xFF
264#define QHSTA_NO_ERROR 0x00
265#define QHSTA_M_SEL_TIMEOUT 0x11
266#define QHSTA_M_DATA_OVER_RUN 0x12
267#define QHSTA_M_DATA_UNDER_RUN 0x12
268#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
269#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
270#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
271#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
272#define QHSTA_D_HOST_ABORT_FAILED 0x23
273#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
274#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
275#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
276#define QHSTA_M_WTM_TIMEOUT 0x41
277#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
278#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
279#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
280#define QHSTA_M_TARGET_STATUS_BUSY 0x45
281#define QHSTA_M_BAD_TAG_CODE 0x46
282#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
283#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
284#define QHSTA_D_LRAM_CMP_ERROR 0x81
285#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
286#define ASC_FLAG_SCSIQ_REQ 0x01
287#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
288#define ASC_FLAG_BIOS_ASYNC_IO 0x04
289#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
290#define ASC_FLAG_WIN16 0x10
291#define ASC_FLAG_WIN32 0x20
292#define ASC_FLAG_ISA_OVER_16MB 0x40
293#define ASC_FLAG_DOS_VM_CALLBACK 0x80
294#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
295#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
296#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
297#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
298#define ASC_SCSIQ_CPY_BEG 4
299#define ASC_SCSIQ_SGHD_CPY_BEG 2
300#define ASC_SCSIQ_B_FWD 0
301#define ASC_SCSIQ_B_BWD 1
302#define ASC_SCSIQ_B_STATUS 2
303#define ASC_SCSIQ_B_QNO 3
304#define ASC_SCSIQ_B_CNTL 4
305#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
306#define ASC_SCSIQ_D_DATA_ADDR 8
307#define ASC_SCSIQ_D_DATA_CNT 12
308#define ASC_SCSIQ_B_SENSE_LEN 20
309#define ASC_SCSIQ_DONE_INFO_BEG 22
310#define ASC_SCSIQ_D_SRBPTR 22
311#define ASC_SCSIQ_B_TARGET_IX 26
312#define ASC_SCSIQ_B_CDB_LEN 28
313#define ASC_SCSIQ_B_TAG_CODE 29
314#define ASC_SCSIQ_W_VM_ID 30
315#define ASC_SCSIQ_DONE_STATUS 32
316#define ASC_SCSIQ_HOST_STATUS 33
317#define ASC_SCSIQ_SCSI_STATUS 34
318#define ASC_SCSIQ_CDB_BEG 36
319#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
320#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
321#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
322#define ASC_SCSIQ_B_SG_WK_QP 49
323#define ASC_SCSIQ_B_SG_WK_IX 50
324#define ASC_SCSIQ_W_ALT_DC1 52
325#define ASC_SCSIQ_B_LIST_CNT 6
326#define ASC_SCSIQ_B_CUR_LIST_CNT 7
327#define ASC_SGQ_B_SG_CNTL 4
328#define ASC_SGQ_B_SG_HEAD_QP 5
329#define ASC_SGQ_B_SG_LIST_CNT 6
330#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
331#define ASC_SGQ_LIST_BEG 8
332#define ASC_DEF_SCSI1_QNG 4
333#define ASC_MAX_SCSI1_QNG 4
334#define ASC_DEF_SCSI2_QNG 16
335#define ASC_MAX_SCSI2_QNG 32
336#define ASC_TAG_CODE_MASK 0x23
337#define ASC_STOP_REQ_RISC_STOP 0x01
338#define ASC_STOP_ACK_RISC_STOP 0x03
339#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
340#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
341#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
342#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
343#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
344#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
345#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
346#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
347#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
348#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
349
350typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400351 uchar status;
352 uchar q_no;
353 uchar cntl;
354 uchar sg_queue_cnt;
355 uchar target_id;
356 uchar target_lun;
357 ASC_PADDR data_addr;
358 ASC_DCNT data_cnt;
359 ASC_PADDR sense_addr;
360 uchar sense_len;
361 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362} ASC_SCSIQ_1;
363
364typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400365 ASC_VADDR srb_ptr;
366 uchar target_ix;
367 uchar flag;
368 uchar cdb_len;
369 uchar tag_code;
370 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371} ASC_SCSIQ_2;
372
373typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400374 uchar done_stat;
375 uchar host_stat;
376 uchar scsi_stat;
377 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378} ASC_SCSIQ_3;
379
380typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400381 uchar cdb[ASC_MAX_CDB_LEN];
382 uchar y_first_sg_list_qp;
383 uchar y_working_sg_qp;
384 uchar y_working_sg_ix;
385 uchar y_res;
386 ushort x_req_count;
387 ushort x_reconnect_rtn;
388 ASC_PADDR x_saved_data_addr;
389 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390} ASC_SCSIQ_4;
391
392typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400393 ASC_SCSIQ_2 d2;
394 ASC_SCSIQ_3 d3;
395 uchar q_status;
396 uchar q_no;
397 uchar cntl;
398 uchar sense_len;
399 uchar extra_bytes;
400 uchar res;
401 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402} ASC_QDONE_INFO;
403
404typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400405 ASC_PADDR addr;
406 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407} ASC_SG_LIST;
408
409typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400410 ushort entry_cnt;
411 ushort queue_cnt;
412 ushort entry_to_copy;
413 ushort res;
414 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415} ASC_SG_HEAD;
416
417#define ASC_MIN_SG_LIST 2
418
419typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400420 ushort entry_cnt;
421 ushort queue_cnt;
422 ushort entry_to_copy;
423 ushort res;
424 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425} ASC_MIN_SG_HEAD;
426
427#define QCX_SORT (0x0001)
428#define QCX_COALEASE (0x0002)
429
430typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400431 ASC_SCSIQ_1 q1;
432 ASC_SCSIQ_2 q2;
433 uchar *cdbptr;
434 ASC_SG_HEAD *sg_head;
435 ushort remain_sg_entry_cnt;
436 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437} ASC_SCSI_Q;
438
439typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400440 ASC_SCSIQ_1 r1;
441 ASC_SCSIQ_2 r2;
442 uchar *cdbptr;
443 ASC_SG_HEAD *sg_head;
444 uchar *sense_ptr;
445 ASC_SCSIQ_3 r3;
446 uchar cdb[ASC_MAX_CDB_LEN];
447 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448} ASC_SCSI_REQ_Q;
449
450typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400451 ASC_SCSIQ_1 r1;
452 ASC_SCSIQ_2 r2;
453 uchar *cdbptr;
454 ASC_SG_HEAD *sg_head;
455 uchar *sense_ptr;
456 ASC_SCSIQ_3 r3;
457 uchar cdb[ASC_MAX_CDB_LEN];
458 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459} ASC_SCSI_BIOS_REQ_Q;
460
461typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400462 uchar fwd;
463 uchar bwd;
464 ASC_SCSIQ_1 i1;
465 ASC_SCSIQ_2 i2;
466 ASC_SCSIQ_3 i3;
467 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468} ASC_RISC_Q;
469
470typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400471 uchar seq_no;
472 uchar q_no;
473 uchar cntl;
474 uchar sg_head_qp;
475 uchar sg_list_cnt;
476 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477} ASC_SG_LIST_Q;
478
479typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400480 uchar fwd;
481 uchar bwd;
482 ASC_SG_LIST_Q sg;
483 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484} ASC_RISC_SG_LIST_Q;
485
486#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
487#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
488#define ASCQ_ERR_NO_ERROR 0
489#define ASCQ_ERR_IO_NOT_FOUND 1
490#define ASCQ_ERR_LOCAL_MEM 2
491#define ASCQ_ERR_CHKSUM 3
492#define ASCQ_ERR_START_CHIP 4
493#define ASCQ_ERR_INT_TARGET_ID 5
494#define ASCQ_ERR_INT_LOCAL_MEM 6
495#define ASCQ_ERR_HALT_RISC 7
496#define ASCQ_ERR_GET_ASPI_ENTRY 8
497#define ASCQ_ERR_CLOSE_ASPI 9
498#define ASCQ_ERR_HOST_INQUIRY 0x0A
499#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
500#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
501#define ASCQ_ERR_Q_STATUS 0x0D
502#define ASCQ_ERR_WR_SCSIQ 0x0E
503#define ASCQ_ERR_PC_ADDR 0x0F
504#define ASCQ_ERR_SYN_OFFSET 0x10
505#define ASCQ_ERR_SYN_XFER_TIME 0x11
506#define ASCQ_ERR_LOCK_DMA 0x12
507#define ASCQ_ERR_UNLOCK_DMA 0x13
508#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
509#define ASCQ_ERR_MICRO_CODE_HALT 0x15
510#define ASCQ_ERR_SET_LRAM_ADDR 0x16
511#define ASCQ_ERR_CUR_QNG 0x17
512#define ASCQ_ERR_SG_Q_LINKS 0x18
513#define ASCQ_ERR_SCSIQ_PTR 0x19
514#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
515#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
516#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
517#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
518#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
519#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
520#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
521#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
522#define ASCQ_ERR_SEND_SCSI_Q 0x22
523#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
524#define ASCQ_ERR_RESET_SDTR 0x24
525
526/*
527 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
528 */
529#define ASC_WARN_NO_ERROR 0x0000
530#define ASC_WARN_IO_PORT_ROTATE 0x0001
531#define ASC_WARN_EEPROM_CHKSUM 0x0002
532#define ASC_WARN_IRQ_MODIFIED 0x0004
533#define ASC_WARN_AUTO_CONFIG 0x0008
534#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
535#define ASC_WARN_EEPROM_RECOVER 0x0020
536#define ASC_WARN_CFG_MSW_RECOVER 0x0040
537#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
538
539/*
540 * Error code values are set in ASC_DVC_VAR 'err_code'.
541 */
542#define ASC_IERR_WRITE_EEPROM 0x0001
543#define ASC_IERR_MCODE_CHKSUM 0x0002
544#define ASC_IERR_SET_PC_ADDR 0x0004
545#define ASC_IERR_START_STOP_CHIP 0x0008
546#define ASC_IERR_IRQ_NO 0x0010
547#define ASC_IERR_SET_IRQ_NO 0x0020
548#define ASC_IERR_CHIP_VERSION 0x0040
549#define ASC_IERR_SET_SCSI_ID 0x0080
550#define ASC_IERR_GET_PHY_ADDR 0x0100
551#define ASC_IERR_BAD_SIGNATURE 0x0200
552#define ASC_IERR_NO_BUS_TYPE 0x0400
553#define ASC_IERR_SCAM 0x0800
554#define ASC_IERR_SET_SDTR 0x1000
555#define ASC_IERR_RW_LRAM 0x8000
556
557#define ASC_DEF_IRQ_NO 10
558#define ASC_MAX_IRQ_NO 15
559#define ASC_MIN_IRQ_NO 10
560#define ASC_MIN_REMAIN_Q (0x02)
561#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
562#define ASC_MIN_TAG_Q_PER_DVC (0x04)
563#define ASC_DEF_TAG_Q_PER_DVC (0x04)
564#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
565#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
566#define ASC_MAX_TOTAL_QNG 240
567#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
568#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
569#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
570#define ASC_MAX_INRAM_TAG_QNG 16
571#define ASC_IOADR_TABLE_MAX_IX 11
572#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573#define ASC_LIB_SCSIQ_WK_SP 256
574#define ASC_MAX_SYN_XFER_NO 16
575#define ASC_SYN_MAX_OFFSET 0x0F
576#define ASC_DEF_SDTR_OFFSET 0x0F
577#define ASC_DEF_SDTR_INDEX 0x00
578#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
579#define SYN_XFER_NS_0 25
580#define SYN_XFER_NS_1 30
581#define SYN_XFER_NS_2 35
582#define SYN_XFER_NS_3 40
583#define SYN_XFER_NS_4 50
584#define SYN_XFER_NS_5 60
585#define SYN_XFER_NS_6 70
586#define SYN_XFER_NS_7 85
587#define SYN_ULTRA_XFER_NS_0 12
588#define SYN_ULTRA_XFER_NS_1 19
589#define SYN_ULTRA_XFER_NS_2 25
590#define SYN_ULTRA_XFER_NS_3 32
591#define SYN_ULTRA_XFER_NS_4 38
592#define SYN_ULTRA_XFER_NS_5 44
593#define SYN_ULTRA_XFER_NS_6 50
594#define SYN_ULTRA_XFER_NS_7 57
595#define SYN_ULTRA_XFER_NS_8 63
596#define SYN_ULTRA_XFER_NS_9 69
597#define SYN_ULTRA_XFER_NS_10 75
598#define SYN_ULTRA_XFER_NS_11 82
599#define SYN_ULTRA_XFER_NS_12 88
600#define SYN_ULTRA_XFER_NS_13 94
601#define SYN_ULTRA_XFER_NS_14 100
602#define SYN_ULTRA_XFER_NS_15 107
603
604typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400605 uchar msg_type;
606 uchar msg_len;
607 uchar msg_req;
608 union {
609 struct {
610 uchar sdtr_xfer_period;
611 uchar sdtr_req_ack_offset;
612 } sdtr;
613 struct {
614 uchar wdtr_width;
615 } wdtr;
616 struct {
617 uchar mdp_b3;
618 uchar mdp_b2;
619 uchar mdp_b1;
620 uchar mdp_b0;
621 } mdp;
622 } u_ext_msg;
623 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624} EXT_MSG;
625
626#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
627#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
628#define wdtr_width u_ext_msg.wdtr.wdtr_width
629#define mdp_b3 u_ext_msg.mdp_b3
630#define mdp_b2 u_ext_msg.mdp_b2
631#define mdp_b1 u_ext_msg.mdp_b1
632#define mdp_b0 u_ext_msg.mdp_b0
633
634typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400635 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
636 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
637 ASC_SCSI_BIT_ID_TYPE disc_enable;
638 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
639 uchar chip_scsi_id;
640 uchar isa_dma_speed;
641 uchar isa_dma_channel;
642 uchar chip_version;
643 ushort lib_serial_no;
644 ushort lib_version;
645 ushort mcode_date;
646 ushort mcode_version;
647 uchar max_tag_qng[ASC_MAX_TID + 1];
648 uchar *overrun_buf;
649 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400650 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651} ASC_DVC_CFG;
652
653#define ASC_DEF_DVC_CNTL 0xFFFF
654#define ASC_DEF_CHIP_SCSI_ID 7
655#define ASC_DEF_ISA_DMA_SPEED 4
656#define ASC_INIT_STATE_NULL 0x0000
657#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
658#define ASC_INIT_STATE_END_GET_CFG 0x0002
659#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
660#define ASC_INIT_STATE_END_SET_CFG 0x0008
661#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
662#define ASC_INIT_STATE_END_LOAD_MC 0x0020
663#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
664#define ASC_INIT_STATE_END_INQUIRY 0x0080
665#define ASC_INIT_RESET_SCSI_DONE 0x0100
666#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
668#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
669#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
670#define ASC_MIN_TAGGED_CMD 7
671#define ASC_MAX_SCSI_RESET_WAIT 30
672
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400673struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400676 PortAddr iop_base;
677 ushort err_code;
678 ushort dvc_cntl;
679 ushort bug_fix_cntl;
680 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400681 ASC_SCSI_BIT_ID_TYPE init_sdtr;
682 ASC_SCSI_BIT_ID_TYPE sdtr_done;
683 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
684 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
685 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
686 ASC_SCSI_BIT_ID_TYPE start_motor;
687 uchar scsi_reset_wait;
688 uchar chip_no;
689 char is_in_int;
690 uchar max_total_qng;
691 uchar cur_total_qng;
692 uchar in_critical_cnt;
693 uchar irq_no;
694 uchar last_q_shortage;
695 ushort init_state;
696 uchar cur_dvc_qng[ASC_MAX_TID + 1];
697 uchar max_dvc_qng[ASC_MAX_TID + 1];
698 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
699 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
700 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
701 ASC_DVC_CFG *cfg;
702 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
703 char redo_scam;
704 ushort res2;
705 uchar dos_int13_table[ASC_MAX_TID + 1];
706 ASC_DCNT max_dma_count;
707 ASC_SCSI_BIT_ID_TYPE no_scam;
708 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
709 uchar max_sdtr_index;
710 uchar host_init_sdtr_index;
711 struct asc_board *drv_ptr;
712 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713} ASC_DVC_VAR;
714
715typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400716 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717} ASC_DVC_INQ_INFO;
718
719typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400720 ASC_DCNT lba;
721 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722} ASC_CAP_INFO;
723
724typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400725 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726} ASC_CAP_INFO_ARRAY;
727
728#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
729#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
730#define ASC_CNTL_INITIATOR (ushort)0x0001
731#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
732#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
733#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
734#define ASC_CNTL_NO_SCAM (ushort)0x0010
735#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
736#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
737#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
738#define ASC_CNTL_RESET_SCSI (ushort)0x0200
739#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
740#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
741#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
742#define ASC_CNTL_BURST_MODE (ushort)0x2000
743#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
744#define ASC_EEP_DVC_CFG_BEG_VL 2
745#define ASC_EEP_MAX_DVC_ADDR_VL 15
746#define ASC_EEP_DVC_CFG_BEG 32
747#define ASC_EEP_MAX_DVC_ADDR 45
748#define ASC_EEP_DEFINED_WORDS 10
749#define ASC_EEP_MAX_ADDR 63
750#define ASC_EEP_RES_WORDS 0
751#define ASC_EEP_MAX_RETRY 20
752#define ASC_MAX_INIT_BUSY_RETRY 8
753#define ASC_EEP_ISA_PNP_WSIZE 16
754
755/*
756 * These macros keep the chip SCSI id and ISA DMA speed
757 * bitfields in board order. C bitfields aren't portable
758 * between big and little-endian platforms so they are
759 * not used.
760 */
761
762#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
763#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
764#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
765 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
766#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
767 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
768
769typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400770 ushort cfg_lsw;
771 ushort cfg_msw;
772 uchar init_sdtr;
773 uchar disc_enable;
774 uchar use_cmd_qng;
775 uchar start_motor;
776 uchar max_total_qng;
777 uchar max_tag_qng;
778 uchar bios_scan;
779 uchar power_up_wait;
780 uchar no_scam;
781 uchar id_speed; /* low order 4 bits is chip scsi id */
782 /* high order 4 bits is isa dma speed */
783 uchar dos_int13_table[ASC_MAX_TID + 1];
784 uchar adapter_info[6];
785 ushort cntl;
786 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787} ASCEEP_CONFIG;
788
789#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
790#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
791#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
792
793#define ASC_EEP_CMD_READ 0x80
794#define ASC_EEP_CMD_WRITE 0x40
795#define ASC_EEP_CMD_WRITE_ABLE 0x30
796#define ASC_EEP_CMD_WRITE_DISABLE 0x00
797#define ASC_OVERRUN_BSIZE 0x00000048UL
798#define ASC_CTRL_BREAK_ONCE 0x0001
799#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
800#define ASCV_MSGOUT_BEG 0x0000
801#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
802#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
803#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
804#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
805#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
806#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
807#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
808#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
809#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
810#define ASCV_BREAK_ADDR (ushort)0x0028
811#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
812#define ASCV_BREAK_CONTROL (ushort)0x002C
813#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
814
815#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
816#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
817#define ASCV_MCODE_SIZE_W (ushort)0x0034
818#define ASCV_STOP_CODE_B (ushort)0x0036
819#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
820#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
821#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
822#define ASCV_HALTCODE_W (ushort)0x0040
823#define ASCV_CHKSUM_W (ushort)0x0042
824#define ASCV_MC_DATE_W (ushort)0x0044
825#define ASCV_MC_VER_W (ushort)0x0046
826#define ASCV_NEXTRDY_B (ushort)0x0048
827#define ASCV_DONENEXT_B (ushort)0x0049
828#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
829#define ASCV_SCSIBUSY_B (ushort)0x004B
830#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
831#define ASCV_CURCDB_B (ushort)0x004D
832#define ASCV_RCLUN_B (ushort)0x004E
833#define ASCV_BUSY_QHEAD_B (ushort)0x004F
834#define ASCV_DISC1_QHEAD_B (ushort)0x0050
835#define ASCV_DISC_ENABLE_B (ushort)0x0052
836#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
837#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
838#define ASCV_MCODE_CNTL_B (ushort)0x0056
839#define ASCV_NULL_TARGET_B (ushort)0x0057
840#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
841#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
842#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
843#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
844#define ASCV_HOST_FLAG_B (ushort)0x005D
845#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
846#define ASCV_VER_SERIAL_B (ushort)0x0065
847#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
848#define ASCV_WTM_FLAG_B (ushort)0x0068
849#define ASCV_RISC_FLAG_B (ushort)0x006A
850#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
851#define ASC_HOST_FLAG_IN_ISR 0x01
852#define ASC_HOST_FLAG_ACK_INT 0x02
853#define ASC_RISC_FLAG_GEN_INT 0x01
854#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
855#define IOP_CTRL (0x0F)
856#define IOP_STATUS (0x0E)
857#define IOP_INT_ACK IOP_STATUS
858#define IOP_REG_IFC (0x0D)
859#define IOP_SYN_OFFSET (0x0B)
860#define IOP_EXTRA_CONTROL (0x0D)
861#define IOP_REG_PC (0x0C)
862#define IOP_RAM_ADDR (0x0A)
863#define IOP_RAM_DATA (0x08)
864#define IOP_EEP_DATA (0x06)
865#define IOP_EEP_CMD (0x07)
866#define IOP_VERSION (0x03)
867#define IOP_CONFIG_HIGH (0x04)
868#define IOP_CONFIG_LOW (0x02)
869#define IOP_SIG_BYTE (0x01)
870#define IOP_SIG_WORD (0x00)
871#define IOP_REG_DC1 (0x0E)
872#define IOP_REG_DC0 (0x0C)
873#define IOP_REG_SB (0x0B)
874#define IOP_REG_DA1 (0x0A)
875#define IOP_REG_DA0 (0x08)
876#define IOP_REG_SC (0x09)
877#define IOP_DMA_SPEED (0x07)
878#define IOP_REG_FLAG (0x07)
879#define IOP_FIFO_H (0x06)
880#define IOP_FIFO_L (0x04)
881#define IOP_REG_ID (0x05)
882#define IOP_REG_QP (0x03)
883#define IOP_REG_IH (0x02)
884#define IOP_REG_IX (0x01)
885#define IOP_REG_AX (0x00)
886#define IFC_REG_LOCK (0x00)
887#define IFC_REG_UNLOCK (0x09)
888#define IFC_WR_EN_FILTER (0x10)
889#define IFC_RD_NO_EEPROM (0x10)
890#define IFC_SLEW_RATE (0x20)
891#define IFC_ACT_NEG (0x40)
892#define IFC_INP_FILTER (0x80)
893#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
894#define SC_SEL (uchar)(0x80)
895#define SC_BSY (uchar)(0x40)
896#define SC_ACK (uchar)(0x20)
897#define SC_REQ (uchar)(0x10)
898#define SC_ATN (uchar)(0x08)
899#define SC_IO (uchar)(0x04)
900#define SC_CD (uchar)(0x02)
901#define SC_MSG (uchar)(0x01)
902#define SEC_SCSI_CTL (uchar)(0x80)
903#define SEC_ACTIVE_NEGATE (uchar)(0x40)
904#define SEC_SLEW_RATE (uchar)(0x20)
905#define SEC_ENABLE_FILTER (uchar)(0x10)
906#define ASC_HALT_EXTMSG_IN (ushort)0x8000
907#define ASC_HALT_CHK_CONDITION (ushort)0x8100
908#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
909#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
910#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
911#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
912#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
913#define ASC_MAX_QNO 0xF8
914#define ASC_DATA_SEC_BEG (ushort)0x0080
915#define ASC_DATA_SEC_END (ushort)0x0080
916#define ASC_CODE_SEC_BEG (ushort)0x0080
917#define ASC_CODE_SEC_END (ushort)0x0080
918#define ASC_QADR_BEG (0x4000)
919#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
920#define ASC_QADR_END (ushort)0x7FFF
921#define ASC_QLAST_ADR (ushort)0x7FC0
922#define ASC_QBLK_SIZE 0x40
923#define ASC_BIOS_DATA_QBEG 0xF8
924#define ASC_MIN_ACTIVE_QNO 0x01
925#define ASC_QLINK_END 0xFF
926#define ASC_EEPROM_WORDS 0x10
927#define ASC_MAX_MGS_LEN 0x10
928#define ASC_BIOS_ADDR_DEF 0xDC00
929#define ASC_BIOS_SIZE 0x3800
930#define ASC_BIOS_RAM_OFF 0x3800
931#define ASC_BIOS_RAM_SIZE 0x800
932#define ASC_BIOS_MIN_ADDR 0xC000
933#define ASC_BIOS_MAX_ADDR 0xEC00
934#define ASC_BIOS_BANK_SIZE 0x0400
935#define ASC_MCODE_START_ADDR 0x0080
936#define ASC_CFG0_HOST_INT_ON 0x0020
937#define ASC_CFG0_BIOS_ON 0x0040
938#define ASC_CFG0_VERA_BURST_ON 0x0080
939#define ASC_CFG0_SCSI_PARITY_ON 0x0800
940#define ASC_CFG1_SCSI_TARGET_ON 0x0080
941#define ASC_CFG1_LRAM_8BITS_ON 0x0800
942#define ASC_CFG_MSW_CLR_MASK 0x3080
943#define CSW_TEST1 (ASC_CS_TYPE)0x8000
944#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
945#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
946#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
947#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
948#define CSW_TEST2 (ASC_CS_TYPE)0x0400
949#define CSW_TEST3 (ASC_CS_TYPE)0x0200
950#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
951#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
952#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
953#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
954#define CSW_HALTED (ASC_CS_TYPE)0x0010
955#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
956#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
957#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
958#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
959#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
960#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
961#define CIW_TEST1 (ASC_CS_TYPE)0x0200
962#define CIW_TEST2 (ASC_CS_TYPE)0x0400
963#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
964#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
965#define CC_CHIP_RESET (uchar)0x80
966#define CC_SCSI_RESET (uchar)0x40
967#define CC_HALT (uchar)0x20
968#define CC_SINGLE_STEP (uchar)0x10
969#define CC_DMA_ABLE (uchar)0x08
970#define CC_TEST (uchar)0x04
971#define CC_BANK_ONE (uchar)0x02
972#define CC_DIAG (uchar)0x01
973#define ASC_1000_ID0W 0x04C1
974#define ASC_1000_ID0W_FIX 0x00C1
975#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976#define ASC_EISA_REV_IOP_MASK (0x0C83)
977#define ASC_EISA_PID_IOP_MASK (0x0C80)
978#define ASC_EISA_CFG_IOP_MASK (0x0C86)
979#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980#define INS_HALTINT (ushort)0x6281
981#define INS_HALT (ushort)0x6280
982#define INS_SINT (ushort)0x6200
983#define INS_RFLAG_WTM (ushort)0x7380
984#define ASC_MC_SAVE_CODE_WSIZE 0x500
985#define ASC_MC_SAVE_DATA_WSIZE 0x40
986
987typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400988 ushort data[ASC_MC_SAVE_DATA_WSIZE];
989 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990} ASC_MC_SAVED;
991
992#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
993#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
994#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
995#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
996#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
997#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
998#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
999#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1000#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1001#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1002#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1003#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1004#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1005#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1006#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1007#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1008#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1009#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1010#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1011#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1012#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1013#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1014#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1015#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1016#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1017#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1018#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1019#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1020#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1021#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1022#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1023#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1024#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1025#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1026#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1027#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1028#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1029#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1030#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1031#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1032#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1033#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1034#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1035#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1036#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1037#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1038#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1039#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1040#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1041#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1042#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1043#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1044#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1045#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1046#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1047#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1048#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1049#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1050#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1051#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1052#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1053#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1054#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1055#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1056#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1057#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1058#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1059#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001061static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1062static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1063static void AscWaitEEPRead(void);
1064static void AscWaitEEPWrite(void);
1065static ushort AscReadEEPWord(PortAddr, uchar);
1066static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1067static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1068static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1069static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1070static int AscStartChip(PortAddr);
1071static int AscStopChip(PortAddr);
1072static void AscSetChipIH(PortAddr, ushort);
1073static int AscIsChipHalted(PortAddr);
1074static void AscAckInterrupt(PortAddr);
1075static void AscDisableInterrupt(PortAddr);
1076static void AscEnableInterrupt(PortAddr);
1077static void AscSetBank(PortAddr, uchar);
1078static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001080static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001082static uchar AscReadLramByte(PortAddr, ushort);
1083static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001085static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001087static void AscWriteLramWord(PortAddr, ushort, ushort);
1088static void AscWriteLramByte(PortAddr, ushort, uchar);
1089static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1090static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1091static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1092static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1093static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1094static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1095static ushort AscInitFromEEP(ASC_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001096static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1097static int AscTestExternalLram(ASC_DVC_VAR *);
1098static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1099static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1100static void AscSetChipSDTR(PortAddr, uchar, uchar);
1101static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1102static uchar AscAllocFreeQueue(PortAddr, uchar);
1103static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1104static int AscHostReqRiscHalt(PortAddr);
1105static int AscStopQueueExe(PortAddr);
1106static int AscSendScsiQueue(ASC_DVC_VAR *,
1107 ASC_SCSI_Q *scsiq, uchar n_q_required);
1108static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1109static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1110static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1111static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1112static ushort AscInitLram(ASC_DVC_VAR *);
1113static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1114static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1115static int AscIsrChipHalted(ASC_DVC_VAR *);
1116static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1117 ASC_QDONE_INFO *, ASC_DCNT);
1118static int AscIsrQDone(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001120static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001122static uchar AscGetChipScsiCtrl(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001123static uchar AscGetChipVersion(PortAddr, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001124static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001125static void AscToggleIRQAct(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001126static inline ulong DvcEnterCritical(void);
1127static inline void DvcLeaveCritical(ulong);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001128static void DvcSleepMilliSecond(ASC_DCNT);
1129static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1130static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1131static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001132static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04001133static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001134static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1135static int AscISR(ASC_DVC_VAR *);
1136static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1137static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001139static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001141static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143/*
1144 * --- Adv Library Constants and Macros
1145 */
1146
1147#define ADV_LIB_VERSION_MAJOR 5
1148#define ADV_LIB_VERSION_MINOR 14
1149
1150/*
1151 * Define Adv Library required special types.
1152 */
1153
1154/*
1155 * Portable Data Types
1156 *
1157 * Any instance where a 32-bit long or pointer type is assumed
1158 * for precision or HW defined structures, the following define
1159 * types must be used. In Linux the char, short, and int types
1160 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1161 * and long types are 64 bits on Alpha and UltraSPARC.
1162 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001163#define ADV_PADDR __u32 /* Physical address data type. */
1164#define ADV_VADDR __u32 /* Virtual address data type. */
1165#define ADV_DCNT __u32 /* Unsigned Data count type. */
1166#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
1168/*
1169 * These macros are used to convert a virtual address to a
1170 * 32-bit value. This currently can be used on Linux Alpha
1171 * which uses 64-bit virtual address but a 32-bit bus address.
1172 * This is likely to break in the future, but doing this now
1173 * will give us time to change the HW and FW to handle 64-bit
1174 * addresses.
1175 */
1176#define ADV_VADDR_TO_U32 virt_to_bus
1177#define ADV_U32_TO_VADDR bus_to_virt
1178
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001179#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
1181/*
1182 * Define Adv Library required memory access macros.
1183 */
1184#define ADV_MEM_READB(addr) readb(addr)
1185#define ADV_MEM_READW(addr) readw(addr)
1186#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1187#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1188#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1189
1190#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1191
1192/*
1193 * For wide boards a CDB length maximum of 16 bytes
1194 * is supported.
1195 */
1196#define ADV_MAX_CDB_LEN 16
1197
1198/*
1199 * Define total number of simultaneous maximum element scatter-gather
1200 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1201 * maximum number of outstanding commands per wide host adapter. Each
1202 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1203 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1204 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1205 * structures or 255 scatter-gather elements.
1206 *
1207 */
1208#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1209
1210/*
1211 * Define Adv Library required maximum number of scatter-gather
1212 * elements per request.
1213 */
1214#define ADV_MAX_SG_LIST 255
1215
1216/* Number of SG blocks needed. */
1217#define ADV_NUM_SG_BLOCK \
1218 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1219
1220/* Total contiguous memory needed for SG blocks. */
1221#define ADV_SG_TOTAL_MEM_SIZE \
1222 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1223
1224#define ADV_PAGE_SIZE PAGE_SIZE
1225
1226#define ADV_NUM_PAGE_CROSSING \
1227 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1230#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001231#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1233
1234#define ADV_EEP_DELAY_MS 100
1235
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001236#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1237#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238/*
1239 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1240 * For later ICs Bit 13 controls whether the CIS (Card Information
1241 * Service Section) is loaded from EEPROM.
1242 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001243#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1244#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245/*
1246 * ASC38C1600 Bit 11
1247 *
1248 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1249 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1250 * Function 0 will specify INT B.
1251 *
1252 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1253 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1254 * Function 1 will specify INT A.
1255 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001256#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001258typedef struct adveep_3550_config {
1259 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001261 ushort cfg_lsw; /* 00 power up initialization */
1262 /* bit 13 set - Term Polarity Control */
1263 /* bit 14 set - BIOS Enable */
1264 /* bit 15 set - Big Endian Mode */
1265 ushort cfg_msw; /* 01 unused */
1266 ushort disc_enable; /* 02 disconnect enable */
1267 ushort wdtr_able; /* 03 Wide DTR able */
1268 ushort sdtr_able; /* 04 Synchronous DTR able */
1269 ushort start_motor; /* 05 send start up motor */
1270 ushort tagqng_able; /* 06 tag queuing able */
1271 ushort bios_scan; /* 07 BIOS device control */
1272 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001274 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1275 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001277 uchar scsi_reset_delay; /* 10 reset delay */
1278 uchar bios_id_lun; /* first boot device scsi id & lun */
1279 /* high nibble is lun */
1280 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001282 uchar termination; /* 11 0 - automatic */
1283 /* 1 - low off / high off */
1284 /* 2 - low off / high on */
1285 /* 3 - low on / high on */
1286 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001288 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001290 ushort bios_ctrl; /* 12 BIOS control bits */
1291 /* bit 0 BIOS don't act as initiator. */
1292 /* bit 1 BIOS > 1 GB support */
1293 /* bit 2 BIOS > 2 Disk Support */
1294 /* bit 3 BIOS don't support removables */
1295 /* bit 4 BIOS support bootable CD */
1296 /* bit 5 BIOS scan enabled */
1297 /* bit 6 BIOS support multiple LUNs */
1298 /* bit 7 BIOS display of message */
1299 /* bit 8 SCAM disabled */
1300 /* bit 9 Reset SCSI bus during init. */
1301 /* bit 10 */
1302 /* bit 11 No verbose initialization. */
1303 /* bit 12 SCSI parity enabled */
1304 /* bit 13 */
1305 /* bit 14 */
1306 /* bit 15 */
1307 ushort ultra_able; /* 13 ULTRA speed able */
1308 ushort reserved2; /* 14 reserved */
1309 uchar max_host_qng; /* 15 maximum host queuing */
1310 uchar max_dvc_qng; /* maximum per device queuing */
1311 ushort dvc_cntl; /* 16 control bit for driver */
1312 ushort bug_fix; /* 17 control bit for bug fix */
1313 ushort serial_number_word1; /* 18 Board serial number word 1 */
1314 ushort serial_number_word2; /* 19 Board serial number word 2 */
1315 ushort serial_number_word3; /* 20 Board serial number word 3 */
1316 ushort check_sum; /* 21 EEP check sum */
1317 uchar oem_name[16]; /* 22 OEM name */
1318 ushort dvc_err_code; /* 30 last device driver error code */
1319 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1320 ushort adv_err_addr; /* 32 last uc error address */
1321 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1322 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1323 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1324 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325} ADVEEP_3550_CONFIG;
1326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001327typedef struct adveep_38C0800_config {
1328 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001330 ushort cfg_lsw; /* 00 power up initialization */
1331 /* bit 13 set - Load CIS */
1332 /* bit 14 set - BIOS Enable */
1333 /* bit 15 set - Big Endian Mode */
1334 ushort cfg_msw; /* 01 unused */
1335 ushort disc_enable; /* 02 disconnect enable */
1336 ushort wdtr_able; /* 03 Wide DTR able */
1337 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1338 ushort start_motor; /* 05 send start up motor */
1339 ushort tagqng_able; /* 06 tag queuing able */
1340 ushort bios_scan; /* 07 BIOS device control */
1341 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001343 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1344 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001346 uchar scsi_reset_delay; /* 10 reset delay */
1347 uchar bios_id_lun; /* first boot device scsi id & lun */
1348 /* high nibble is lun */
1349 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001351 uchar termination_se; /* 11 0 - automatic */
1352 /* 1 - low off / high off */
1353 /* 2 - low off / high on */
1354 /* 3 - low on / high on */
1355 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001357 uchar termination_lvd; /* 11 0 - automatic */
1358 /* 1 - low off / high off */
1359 /* 2 - low off / high on */
1360 /* 3 - low on / high on */
1361 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001363 ushort bios_ctrl; /* 12 BIOS control bits */
1364 /* bit 0 BIOS don't act as initiator. */
1365 /* bit 1 BIOS > 1 GB support */
1366 /* bit 2 BIOS > 2 Disk Support */
1367 /* bit 3 BIOS don't support removables */
1368 /* bit 4 BIOS support bootable CD */
1369 /* bit 5 BIOS scan enabled */
1370 /* bit 6 BIOS support multiple LUNs */
1371 /* bit 7 BIOS display of message */
1372 /* bit 8 SCAM disabled */
1373 /* bit 9 Reset SCSI bus during init. */
1374 /* bit 10 */
1375 /* bit 11 No verbose initialization. */
1376 /* bit 12 SCSI parity enabled */
1377 /* bit 13 */
1378 /* bit 14 */
1379 /* bit 15 */
1380 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1381 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1382 uchar max_host_qng; /* 15 maximum host queueing */
1383 uchar max_dvc_qng; /* maximum per device queuing */
1384 ushort dvc_cntl; /* 16 control bit for driver */
1385 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1386 ushort serial_number_word1; /* 18 Board serial number word 1 */
1387 ushort serial_number_word2; /* 19 Board serial number word 2 */
1388 ushort serial_number_word3; /* 20 Board serial number word 3 */
1389 ushort check_sum; /* 21 EEP check sum */
1390 uchar oem_name[16]; /* 22 OEM name */
1391 ushort dvc_err_code; /* 30 last device driver error code */
1392 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1393 ushort adv_err_addr; /* 32 last uc error address */
1394 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1395 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1396 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1397 ushort reserved36; /* 36 reserved */
1398 ushort reserved37; /* 37 reserved */
1399 ushort reserved38; /* 38 reserved */
1400 ushort reserved39; /* 39 reserved */
1401 ushort reserved40; /* 40 reserved */
1402 ushort reserved41; /* 41 reserved */
1403 ushort reserved42; /* 42 reserved */
1404 ushort reserved43; /* 43 reserved */
1405 ushort reserved44; /* 44 reserved */
1406 ushort reserved45; /* 45 reserved */
1407 ushort reserved46; /* 46 reserved */
1408 ushort reserved47; /* 47 reserved */
1409 ushort reserved48; /* 48 reserved */
1410 ushort reserved49; /* 49 reserved */
1411 ushort reserved50; /* 50 reserved */
1412 ushort reserved51; /* 51 reserved */
1413 ushort reserved52; /* 52 reserved */
1414 ushort reserved53; /* 53 reserved */
1415 ushort reserved54; /* 54 reserved */
1416 ushort reserved55; /* 55 reserved */
1417 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1418 ushort cisprt_msw; /* 57 CIS PTR MSW */
1419 ushort subsysvid; /* 58 SubSystem Vendor ID */
1420 ushort subsysid; /* 59 SubSystem ID */
1421 ushort reserved60; /* 60 reserved */
1422 ushort reserved61; /* 61 reserved */
1423 ushort reserved62; /* 62 reserved */
1424 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425} ADVEEP_38C0800_CONFIG;
1426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001427typedef struct adveep_38C1600_config {
1428 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001430 ushort cfg_lsw; /* 00 power up initialization */
1431 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1432 /* clear - Func. 0 INTA, Func. 1 INTB */
1433 /* bit 13 set - Load CIS */
1434 /* bit 14 set - BIOS Enable */
1435 /* bit 15 set - Big Endian Mode */
1436 ushort cfg_msw; /* 01 unused */
1437 ushort disc_enable; /* 02 disconnect enable */
1438 ushort wdtr_able; /* 03 Wide DTR able */
1439 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1440 ushort start_motor; /* 05 send start up motor */
1441 ushort tagqng_able; /* 06 tag queuing able */
1442 ushort bios_scan; /* 07 BIOS device control */
1443 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001445 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1446 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001448 uchar scsi_reset_delay; /* 10 reset delay */
1449 uchar bios_id_lun; /* first boot device scsi id & lun */
1450 /* high nibble is lun */
1451 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001453 uchar termination_se; /* 11 0 - automatic */
1454 /* 1 - low off / high off */
1455 /* 2 - low off / high on */
1456 /* 3 - low on / high on */
1457 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001459 uchar termination_lvd; /* 11 0 - automatic */
1460 /* 1 - low off / high off */
1461 /* 2 - low off / high on */
1462 /* 3 - low on / high on */
1463 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001465 ushort bios_ctrl; /* 12 BIOS control bits */
1466 /* bit 0 BIOS don't act as initiator. */
1467 /* bit 1 BIOS > 1 GB support */
1468 /* bit 2 BIOS > 2 Disk Support */
1469 /* bit 3 BIOS don't support removables */
1470 /* bit 4 BIOS support bootable CD */
1471 /* bit 5 BIOS scan enabled */
1472 /* bit 6 BIOS support multiple LUNs */
1473 /* bit 7 BIOS display of message */
1474 /* bit 8 SCAM disabled */
1475 /* bit 9 Reset SCSI bus during init. */
1476 /* bit 10 Basic Integrity Checking disabled */
1477 /* bit 11 No verbose initialization. */
1478 /* bit 12 SCSI parity enabled */
1479 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1480 /* bit 14 */
1481 /* bit 15 */
1482 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1483 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1484 uchar max_host_qng; /* 15 maximum host queueing */
1485 uchar max_dvc_qng; /* maximum per device queuing */
1486 ushort dvc_cntl; /* 16 control bit for driver */
1487 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1488 ushort serial_number_word1; /* 18 Board serial number word 1 */
1489 ushort serial_number_word2; /* 19 Board serial number word 2 */
1490 ushort serial_number_word3; /* 20 Board serial number word 3 */
1491 ushort check_sum; /* 21 EEP check sum */
1492 uchar oem_name[16]; /* 22 OEM name */
1493 ushort dvc_err_code; /* 30 last device driver error code */
1494 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1495 ushort adv_err_addr; /* 32 last uc error address */
1496 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1497 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1498 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1499 ushort reserved36; /* 36 reserved */
1500 ushort reserved37; /* 37 reserved */
1501 ushort reserved38; /* 38 reserved */
1502 ushort reserved39; /* 39 reserved */
1503 ushort reserved40; /* 40 reserved */
1504 ushort reserved41; /* 41 reserved */
1505 ushort reserved42; /* 42 reserved */
1506 ushort reserved43; /* 43 reserved */
1507 ushort reserved44; /* 44 reserved */
1508 ushort reserved45; /* 45 reserved */
1509 ushort reserved46; /* 46 reserved */
1510 ushort reserved47; /* 47 reserved */
1511 ushort reserved48; /* 48 reserved */
1512 ushort reserved49; /* 49 reserved */
1513 ushort reserved50; /* 50 reserved */
1514 ushort reserved51; /* 51 reserved */
1515 ushort reserved52; /* 52 reserved */
1516 ushort reserved53; /* 53 reserved */
1517 ushort reserved54; /* 54 reserved */
1518 ushort reserved55; /* 55 reserved */
1519 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1520 ushort cisprt_msw; /* 57 CIS PTR MSW */
1521 ushort subsysvid; /* 58 SubSystem Vendor ID */
1522 ushort subsysid; /* 59 SubSystem ID */
1523 ushort reserved60; /* 60 reserved */
1524 ushort reserved61; /* 61 reserved */
1525 ushort reserved62; /* 62 reserved */
1526 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527} ADVEEP_38C1600_CONFIG;
1528
1529/*
1530 * EEPROM Commands
1531 */
1532#define ASC_EEP_CMD_DONE 0x0200
1533#define ASC_EEP_CMD_DONE_ERR 0x0001
1534
1535/* cfg_word */
1536#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
1537
1538/* bios_ctrl */
1539#define BIOS_CTRL_BIOS 0x0001
1540#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1541#define BIOS_CTRL_GT_2_DISK 0x0004
1542#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1543#define BIOS_CTRL_BOOTABLE_CD 0x0010
1544#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1545#define BIOS_CTRL_DISPLAY_MSG 0x0080
1546#define BIOS_CTRL_NO_SCAM 0x0100
1547#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1548#define BIOS_CTRL_INIT_VERBOSE 0x0800
1549#define BIOS_CTRL_SCSI_PARITY 0x1000
1550#define BIOS_CTRL_AIPP_DIS 0x2000
1551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001552#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001554#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556/*
1557 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1558 * a special 16K Adv Library and Microcode version. After the issue is
1559 * resolved, should restore 32K support.
1560 *
1561 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1562 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001563#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
1565/*
1566 * Byte I/O register address from base of 'iop_base'.
1567 */
1568#define IOPB_INTR_STATUS_REG 0x00
1569#define IOPB_CHIP_ID_1 0x01
1570#define IOPB_INTR_ENABLES 0x02
1571#define IOPB_CHIP_TYPE_REV 0x03
1572#define IOPB_RES_ADDR_4 0x04
1573#define IOPB_RES_ADDR_5 0x05
1574#define IOPB_RAM_DATA 0x06
1575#define IOPB_RES_ADDR_7 0x07
1576#define IOPB_FLAG_REG 0x08
1577#define IOPB_RES_ADDR_9 0x09
1578#define IOPB_RISC_CSR 0x0A
1579#define IOPB_RES_ADDR_B 0x0B
1580#define IOPB_RES_ADDR_C 0x0C
1581#define IOPB_RES_ADDR_D 0x0D
1582#define IOPB_SOFT_OVER_WR 0x0E
1583#define IOPB_RES_ADDR_F 0x0F
1584#define IOPB_MEM_CFG 0x10
1585#define IOPB_RES_ADDR_11 0x11
1586#define IOPB_GPIO_DATA 0x12
1587#define IOPB_RES_ADDR_13 0x13
1588#define IOPB_FLASH_PAGE 0x14
1589#define IOPB_RES_ADDR_15 0x15
1590#define IOPB_GPIO_CNTL 0x16
1591#define IOPB_RES_ADDR_17 0x17
1592#define IOPB_FLASH_DATA 0x18
1593#define IOPB_RES_ADDR_19 0x19
1594#define IOPB_RES_ADDR_1A 0x1A
1595#define IOPB_RES_ADDR_1B 0x1B
1596#define IOPB_RES_ADDR_1C 0x1C
1597#define IOPB_RES_ADDR_1D 0x1D
1598#define IOPB_RES_ADDR_1E 0x1E
1599#define IOPB_RES_ADDR_1F 0x1F
1600#define IOPB_DMA_CFG0 0x20
1601#define IOPB_DMA_CFG1 0x21
1602#define IOPB_TICKLE 0x22
1603#define IOPB_DMA_REG_WR 0x23
1604#define IOPB_SDMA_STATUS 0x24
1605#define IOPB_SCSI_BYTE_CNT 0x25
1606#define IOPB_HOST_BYTE_CNT 0x26
1607#define IOPB_BYTE_LEFT_TO_XFER 0x27
1608#define IOPB_BYTE_TO_XFER_0 0x28
1609#define IOPB_BYTE_TO_XFER_1 0x29
1610#define IOPB_BYTE_TO_XFER_2 0x2A
1611#define IOPB_BYTE_TO_XFER_3 0x2B
1612#define IOPB_ACC_GRP 0x2C
1613#define IOPB_RES_ADDR_2D 0x2D
1614#define IOPB_DEV_ID 0x2E
1615#define IOPB_RES_ADDR_2F 0x2F
1616#define IOPB_SCSI_DATA 0x30
1617#define IOPB_RES_ADDR_31 0x31
1618#define IOPB_RES_ADDR_32 0x32
1619#define IOPB_SCSI_DATA_HSHK 0x33
1620#define IOPB_SCSI_CTRL 0x34
1621#define IOPB_RES_ADDR_35 0x35
1622#define IOPB_RES_ADDR_36 0x36
1623#define IOPB_RES_ADDR_37 0x37
1624#define IOPB_RAM_BIST 0x38
1625#define IOPB_PLL_TEST 0x39
1626#define IOPB_PCI_INT_CFG 0x3A
1627#define IOPB_RES_ADDR_3B 0x3B
1628#define IOPB_RFIFO_CNT 0x3C
1629#define IOPB_RES_ADDR_3D 0x3D
1630#define IOPB_RES_ADDR_3E 0x3E
1631#define IOPB_RES_ADDR_3F 0x3F
1632
1633/*
1634 * Word I/O register address from base of 'iop_base'.
1635 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001636#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1637#define IOPW_CTRL_REG 0x02 /* CC */
1638#define IOPW_RAM_ADDR 0x04 /* LA */
1639#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001641#define IOPW_RISC_CSR 0x0A /* CSR */
1642#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1643#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001645#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001647#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001649#define IOPW_EE_CMD 0x1A /* EC */
1650#define IOPW_EE_DATA 0x1C /* ED */
1651#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001653#define IOPW_Q_BASE 0x22 /* QB */
1654#define IOPW_QP 0x24 /* QP */
1655#define IOPW_IX 0x26 /* IX */
1656#define IOPW_SP 0x28 /* SP */
1657#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658#define IOPW_RES_ADDR_2C 0x2C
1659#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001660#define IOPW_SCSI_DATA 0x30 /* SD */
1661#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1662#define IOPW_SCSI_CTRL 0x34 /* SC */
1663#define IOPW_HSHK_CFG 0x36 /* HCFG */
1664#define IOPW_SXFR_STATUS 0x36 /* SXS */
1665#define IOPW_SXFR_CNTL 0x38 /* SXL */
1666#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001668#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670/*
1671 * Doubleword I/O register address from base of 'iop_base'.
1672 */
1673#define IOPDW_RES_ADDR_0 0x00
1674#define IOPDW_RAM_DATA 0x04
1675#define IOPDW_RES_ADDR_8 0x08
1676#define IOPDW_RES_ADDR_C 0x0C
1677#define IOPDW_RES_ADDR_10 0x10
1678#define IOPDW_COMMA 0x14
1679#define IOPDW_COMMB 0x18
1680#define IOPDW_RES_ADDR_1C 0x1C
1681#define IOPDW_SDMA_ADDR0 0x20
1682#define IOPDW_SDMA_ADDR1 0x24
1683#define IOPDW_SDMA_COUNT 0x28
1684#define IOPDW_SDMA_ERROR 0x2C
1685#define IOPDW_RDMA_ADDR0 0x30
1686#define IOPDW_RDMA_ADDR1 0x34
1687#define IOPDW_RDMA_COUNT 0x38
1688#define IOPDW_RDMA_ERROR 0x3C
1689
1690#define ADV_CHIP_ID_BYTE 0x25
1691#define ADV_CHIP_ID_WORD 0x04C1
1692
1693#define ADV_SC_SCSI_BUS_RESET 0x2000
1694
1695#define ADV_INTR_ENABLE_HOST_INTR 0x01
1696#define ADV_INTR_ENABLE_SEL_INTR 0x02
1697#define ADV_INTR_ENABLE_DPR_INTR 0x04
1698#define ADV_INTR_ENABLE_RTA_INTR 0x08
1699#define ADV_INTR_ENABLE_RMA_INTR 0x10
1700#define ADV_INTR_ENABLE_RST_INTR 0x20
1701#define ADV_INTR_ENABLE_DPE_INTR 0x40
1702#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1703
1704#define ADV_INTR_STATUS_INTRA 0x01
1705#define ADV_INTR_STATUS_INTRB 0x02
1706#define ADV_INTR_STATUS_INTRC 0x04
1707
1708#define ADV_RISC_CSR_STOP (0x0000)
1709#define ADV_RISC_TEST_COND (0x2000)
1710#define ADV_RISC_CSR_RUN (0x4000)
1711#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1712
1713#define ADV_CTRL_REG_HOST_INTR 0x0100
1714#define ADV_CTRL_REG_SEL_INTR 0x0200
1715#define ADV_CTRL_REG_DPR_INTR 0x0400
1716#define ADV_CTRL_REG_RTA_INTR 0x0800
1717#define ADV_CTRL_REG_RMA_INTR 0x1000
1718#define ADV_CTRL_REG_RES_BIT14 0x2000
1719#define ADV_CTRL_REG_DPE_INTR 0x4000
1720#define ADV_CTRL_REG_POWER_DONE 0x8000
1721#define ADV_CTRL_REG_ANY_INTR 0xFF00
1722
1723#define ADV_CTRL_REG_CMD_RESET 0x00C6
1724#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1725#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1726#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1727#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1728
1729#define ADV_TICKLE_NOP 0x00
1730#define ADV_TICKLE_A 0x01
1731#define ADV_TICKLE_B 0x02
1732#define ADV_TICKLE_C 0x03
1733
1734#define ADV_SCSI_CTRL_RSTOUT 0x2000
1735
1736#define AdvIsIntPending(port) \
1737 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1738
1739/*
1740 * SCSI_CFG0 Register bit definitions
1741 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001742#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1743#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1744#define EVEN_PARITY 0x1000 /* Select Even Parity */
1745#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1746#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1747#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1748#define SCAM_EN 0x0080 /* Enable SCAM selection */
1749#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1750#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1751#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1752#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
1754/*
1755 * SCSI_CFG1 Register bit definitions
1756 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001757#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1758#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1759#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1760#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1761#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1762#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1763#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1764#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1765#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1766#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1767#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1768#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1769#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1770#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1771#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
1773/*
1774 * Addendum for ASC-38C0800 Chip
1775 *
1776 * The ASC-38C1600 Chip uses the same definitions except that the
1777 * bus mode override bits [12:10] have been moved to byte register
1778 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1779 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1780 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1781 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1782 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1783 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001784#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1785#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1786#define HVD 0x1000 /* HVD Device Detect */
1787#define LVD 0x0800 /* LVD Device Detect */
1788#define SE 0x0400 /* SE Device Detect */
1789#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1790#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1791#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1792#define TERM_SE 0x0030 /* SE Termination Bits */
1793#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1794#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1795#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1796#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1797#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1798#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1799#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1800#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
1802#define CABLE_ILLEGAL_A 0x7
1803 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1804
1805#define CABLE_ILLEGAL_B 0xB
1806 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1807
1808/*
1809 * MEM_CFG Register bit definitions
1810 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001811#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1812#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1813#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1814#define RAM_SZ_2KB 0x00 /* 2 KB */
1815#define RAM_SZ_4KB 0x04 /* 4 KB */
1816#define RAM_SZ_8KB 0x08 /* 8 KB */
1817#define RAM_SZ_16KB 0x0C /* 16 KB */
1818#define RAM_SZ_32KB 0x10 /* 32 KB */
1819#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821/*
1822 * DMA_CFG0 Register bit definitions
1823 *
1824 * This register is only accessible to the host.
1825 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001826#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1827#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1828#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1829#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1830#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1831#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1832#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1833#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1834#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1835#define START_CTL 0x0C /* DMA start conditions */
1836#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1837#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1838#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1839#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1840#define READ_CMD 0x03 /* Memory Read Method */
1841#define READ_CMD_MR 0x00 /* Memory Read */
1842#define READ_CMD_MRL 0x02 /* Memory Read Long */
1843#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
1845/*
1846 * ASC-38C0800 RAM BIST Register bit definitions
1847 */
1848#define RAM_TEST_MODE 0x80
1849#define PRE_TEST_MODE 0x40
1850#define NORMAL_MODE 0x00
1851#define RAM_TEST_DONE 0x10
1852#define RAM_TEST_STATUS 0x0F
1853#define RAM_TEST_HOST_ERROR 0x08
1854#define RAM_TEST_INTRAM_ERROR 0x04
1855#define RAM_TEST_RISC_ERROR 0x02
1856#define RAM_TEST_SCSI_ERROR 0x01
1857#define RAM_TEST_SUCCESS 0x00
1858#define PRE_TEST_VALUE 0x05
1859#define NORMAL_VALUE 0x00
1860
1861/*
1862 * ASC38C1600 Definitions
1863 *
1864 * IOPB_PCI_INT_CFG Bit Field Definitions
1865 */
1866
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001867#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
1869/*
1870 * Bit 1 can be set to change the interrupt for the Function to operate in
1871 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1872 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1873 * mode, otherwise the operating mode is undefined.
1874 */
1875#define TOTEMPOLE 0x02
1876
1877/*
1878 * Bit 0 can be used to change the Int Pin for the Function. The value is
1879 * 0 by default for both Functions with Function 0 using INT A and Function
1880 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1881 * INT A is used.
1882 *
1883 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1884 * value specified in the PCI Configuration Space.
1885 */
1886#define INTAB 0x01
1887
1888/* a_advlib.h */
1889
1890/*
1891 * Adv Library Status Definitions
1892 */
1893#define ADV_TRUE 1
1894#define ADV_FALSE 0
1895#define ADV_NOERROR 1
1896#define ADV_SUCCESS 1
1897#define ADV_BUSY 0
1898#define ADV_ERROR (-1)
1899
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900/*
1901 * ADV_DVC_VAR 'warn_code' values
1902 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001903#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1904#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1905#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
1906#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
1907#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001909#define ADV_MAX_TID 15 /* max. target identifier */
1910#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
1912/*
1913 * Error code values are set in ADV_DVC_VAR 'err_code'.
1914 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001915#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
1916#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
1917#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
1918#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
1919#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
1920#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
1921#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
1922#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
1923#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
1924#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
1925#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
1926#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
1927#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
1928#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
1930/*
1931 * Fixed locations of microcode operating variables.
1932 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001933#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1934#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1935#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1936#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1937#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1938#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1939#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1940#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1941#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1942#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1943#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1944#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1945#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946#define ASC_MC_CHIP_TYPE 0x009A
1947#define ASC_MC_INTRB_CODE 0x009B
1948#define ASC_MC_WDTR_ABLE 0x009C
1949#define ASC_MC_SDTR_ABLE 0x009E
1950#define ASC_MC_TAGQNG_ABLE 0x00A0
1951#define ASC_MC_DISC_ENABLE 0x00A2
1952#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1953#define ASC_MC_IDLE_CMD 0x00A6
1954#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1955#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1956#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1957#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1958#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1959#define ASC_MC_SDTR_DONE 0x00B6
1960#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1961#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1962#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001963#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001965#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966#define ASC_MC_ICQ 0x0160
1967#define ASC_MC_IRQ 0x0164
1968#define ASC_MC_PPR_ABLE 0x017A
1969
1970/*
1971 * BIOS LRAM variable absolute offsets.
1972 */
1973#define BIOS_CODESEG 0x54
1974#define BIOS_CODELEN 0x56
1975#define BIOS_SIGNATURE 0x58
1976#define BIOS_VERSION 0x5A
1977
1978/*
1979 * Microcode Control Flags
1980 *
1981 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1982 * and handled by the microcode.
1983 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001984#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1985#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
1987/*
1988 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1989 */
1990#define HSHK_CFG_WIDE_XFR 0x8000
1991#define HSHK_CFG_RATE 0x0F00
1992#define HSHK_CFG_OFFSET 0x001F
1993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001994#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1995#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1996#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1997#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001999#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2000#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2001#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2002#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2003#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002005#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2006#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2007#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2008#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2009#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010/*
2011 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2012 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2013 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002014#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2015#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
2017/*
2018 * All fields here are accessed by the board microcode and need to be
2019 * little-endian.
2020 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002021typedef struct adv_carr_t {
2022 ADV_VADDR carr_va; /* Carrier Virtual Address */
2023 ADV_PADDR carr_pa; /* Carrier Physical Address */
2024 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2025 /*
2026 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2027 *
2028 * next_vpa [3:1] Reserved Bits
2029 * next_vpa [0] Done Flag set in Response Queue.
2030 */
2031 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032} ADV_CARR_T;
2033
2034/*
2035 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2036 */
2037#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2038
2039#define ASC_RQ_DONE 0x00000001
2040#define ASC_RQ_GOOD 0x00000002
2041#define ASC_CQ_STOPPER 0x00000000
2042
2043#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2044
2045#define ADV_CARRIER_NUM_PAGE_CROSSING \
2046 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2047 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2048
2049#define ADV_CARRIER_BUFSIZE \
2050 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2051
2052/*
2053 * ASC_SCSI_REQ_Q 'a_flag' definitions
2054 *
2055 * The Adv Library should limit use to the lower nibble (4 bits) of
2056 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2057 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002058#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2059#define ADV_SCSIQ_DONE 0x02 /* request done */
2060#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002062#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2063#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2064#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
2066/*
2067 * Adapter temporary configuration structure
2068 *
2069 * This structure can be discarded after initialization. Don't add
2070 * fields here needed after initialization.
2071 *
2072 * Field naming convention:
2073 *
2074 * *_enable indicates the field enables or disables a feature. The
2075 * value of the field is never reset.
2076 */
2077typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002078 ushort disc_enable; /* enable disconnection */
2079 uchar chip_version; /* chip version */
2080 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2081 ushort lib_version; /* Adv Library version number */
2082 ushort control_flag; /* Microcode Control Flag */
2083 ushort mcode_date; /* Microcode date */
2084 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002085 ushort serial1; /* EEPROM serial number word 1 */
2086 ushort serial2; /* EEPROM serial number word 2 */
2087 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088} ADV_DVC_CFG;
2089
2090struct adv_dvc_var;
2091struct adv_scsi_req_q;
2092
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093/*
2094 * Adapter operation variable structure.
2095 *
2096 * One structure is required per host adapter.
2097 *
2098 * Field naming convention:
2099 *
2100 * *_able indicates both whether a feature should be enabled or disabled
2101 * and whether a device isi capable of the feature. At initialization
2102 * this field may be set, but later if a device is found to be incapable
2103 * of the feature, the field is cleared.
2104 */
2105typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002106 AdvPortAddr iop_base; /* I/O port address */
2107 ushort err_code; /* fatal error code */
2108 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002109 ushort wdtr_able; /* try WDTR for a device */
2110 ushort sdtr_able; /* try SDTR for a device */
2111 ushort ultra_able; /* try SDTR Ultra speed for a device */
2112 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2113 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2114 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2115 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2116 ushort tagqng_able; /* try tagged queuing with a device */
2117 ushort ppr_able; /* PPR message capable per TID bitmask. */
2118 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2119 ushort start_motor; /* start motor command allowed */
2120 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2121 uchar chip_no; /* should be assigned by caller */
2122 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2123 uchar irq_no; /* IRQ number */
2124 ushort no_scam; /* scam_tolerant of EEPROM */
2125 struct asc_board *drv_ptr; /* driver pointer to private structure */
2126 uchar chip_scsi_id; /* chip SCSI target ID */
2127 uchar chip_type;
2128 uchar bist_err_code;
2129 ADV_CARR_T *carrier_buf;
2130 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2131 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2132 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2133 ushort carr_pending_cnt; /* Count of pending carriers. */
2134 /*
2135 * Note: The following fields will not be used after initialization. The
2136 * driver may discard the buffer after initialization is done.
2137 */
2138 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139} ADV_DVC_VAR;
2140
2141#define NO_OF_SG_PER_BLOCK 15
2142
2143typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002144 uchar reserved1;
2145 uchar reserved2;
2146 uchar reserved3;
2147 uchar sg_cnt; /* Valid entries in block. */
2148 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
2149 struct {
2150 ADV_PADDR sg_addr; /* SG element address. */
2151 ADV_DCNT sg_count; /* SG element count. */
2152 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153} ADV_SG_BLOCK;
2154
2155/*
2156 * ADV_SCSI_REQ_Q - microcode request structure
2157 *
2158 * All fields in this structure up to byte 60 are used by the microcode.
2159 * The microcode makes assumptions about the size and ordering of fields
2160 * in this structure. Do not change the structure definition here without
2161 * coordinating the change with the microcode.
2162 *
2163 * All fields accessed by microcode must be maintained in little_endian
2164 * order.
2165 */
2166typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002167 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2168 uchar target_cmd;
2169 uchar target_id; /* Device target identifier. */
2170 uchar target_lun; /* Device target logical unit number. */
2171 ADV_PADDR data_addr; /* Data buffer physical address. */
2172 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
2173 ADV_PADDR sense_addr;
2174 ADV_PADDR carr_pa;
2175 uchar mflag;
2176 uchar sense_len;
2177 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
2178 uchar scsi_cntl;
2179 uchar done_status; /* Completion status. */
2180 uchar scsi_status; /* SCSI status byte. */
2181 uchar host_status; /* Ucode host status. */
2182 uchar sg_working_ix;
2183 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
2184 ADV_PADDR sg_real_addr; /* SG list physical address. */
2185 ADV_PADDR scsiq_rptr;
2186 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
2187 ADV_VADDR scsiq_ptr;
2188 ADV_VADDR carr_va;
2189 /*
2190 * End of microcode structure - 60 bytes. The rest of the structure
2191 * is used by the Adv Library and ignored by the microcode.
2192 */
2193 ADV_VADDR srb_ptr;
2194 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2195 char *vdata_addr; /* Data buffer virtual address. */
2196 uchar a_flag;
2197 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198} ADV_SCSI_REQ_Q;
2199
2200/*
2201 * Microcode idle loop commands
2202 */
2203#define IDLE_CMD_COMPLETED 0
2204#define IDLE_CMD_STOP_CHIP 0x0001
2205#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2206#define IDLE_CMD_SEND_INT 0x0004
2207#define IDLE_CMD_ABORT 0x0008
2208#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002209#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
2210#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211#define IDLE_CMD_SCSIREQ 0x0080
2212
2213#define IDLE_CMD_STATUS_SUCCESS 0x0001
2214#define IDLE_CMD_STATUS_FAILURE 0x0002
2215
2216/*
2217 * AdvSendIdleCmd() flag definitions.
2218 */
2219#define ADV_NOWAIT 0x01
2220
2221/*
2222 * Wait loop time out values.
2223 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002224#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
2225#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2226#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
2227#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
2228#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002230#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2231#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2232#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2233#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002235#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236
2237/*
2238 * Device drivers must define the following functions.
2239 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002240static inline ulong DvcEnterCritical(void);
2241static inline void DvcLeaveCritical(ulong);
2242static void DvcSleepMilliSecond(ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002243static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2244 uchar *, ASC_SDCNT *, int);
2245static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
2247/*
2248 * Adv Library functions available to drivers.
2249 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002250static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2251static int AdvISR(ADV_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002252static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2253static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
2254static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
2255static int AdvResetChipAndSB(ADV_DVC_VAR *);
2256static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258/*
2259 * Internal Adv Library functions.
2260 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002261static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002262static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
2263static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
2264static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
2265static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2266static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2267static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2268static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2269static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2270static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2271static void AdvWaitEEPCmd(AdvPortAddr);
2272static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274/* Read byte from a register. */
2275#define AdvReadByteRegister(iop_base, reg_off) \
2276 (ADV_MEM_READB((iop_base) + (reg_off)))
2277
2278/* Write byte to a register. */
2279#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2280 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2281
2282/* Read word (2 bytes) from a register. */
2283#define AdvReadWordRegister(iop_base, reg_off) \
2284 (ADV_MEM_READW((iop_base) + (reg_off)))
2285
2286/* Write word (2 bytes) to a register. */
2287#define AdvWriteWordRegister(iop_base, reg_off, word) \
2288 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2289
2290/* Write dword (4 bytes) to a register. */
2291#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2292 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2293
2294/* Read byte from LRAM. */
2295#define AdvReadByteLram(iop_base, addr, byte) \
2296do { \
2297 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2298 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2299} while (0)
2300
2301/* Write byte to LRAM. */
2302#define AdvWriteByteLram(iop_base, addr, byte) \
2303 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2304 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2305
2306/* Read word (2 bytes) from LRAM. */
2307#define AdvReadWordLram(iop_base, addr, word) \
2308do { \
2309 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2310 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2311} while (0)
2312
2313/* Write word (2 bytes) to LRAM. */
2314#define AdvWriteWordLram(iop_base, addr, word) \
2315 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2316 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2317
2318/* Write little-endian double word (4 bytes) to LRAM */
2319/* Because of unspecified C language ordering don't use auto-increment. */
2320#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2321 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2322 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2323 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2324 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2325 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2326 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2327
2328/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2329#define AdvReadWordAutoIncLram(iop_base) \
2330 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2331
2332/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2333#define AdvWriteWordAutoIncLram(iop_base, word) \
2334 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2335
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336/*
2337 * Define macro to check for Condor signature.
2338 *
2339 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2340 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2341 */
2342#define AdvFindSignature(iop_base) \
2343 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2344 ADV_CHIP_ID_BYTE) && \
2345 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2346 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2347
2348/*
2349 * Define macro to Return the version number of the chip at 'iop_base'.
2350 *
2351 * The second parameter 'bus_type' is currently unused.
2352 */
2353#define AdvGetChipVersion(iop_base, bus_type) \
2354 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2355
2356/*
2357 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2358 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2359 *
2360 * If the request has not yet been sent to the device it will simply be
2361 * aborted from RISC memory. If the request is disconnected it will be
2362 * aborted on reselection by sending an Abort Message to the target ID.
2363 *
2364 * Return value:
2365 * ADV_TRUE(1) - Queue was successfully aborted.
2366 * ADV_FALSE(0) - Queue was not found on the active queue list.
2367 */
2368#define AdvAbortQueue(asc_dvc, scsiq) \
2369 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2370 (ADV_DCNT) (scsiq))
2371
2372/*
2373 * Send a Bus Device Reset Message to the specified target ID.
2374 *
2375 * All outstanding commands will be purged if sending the
2376 * Bus Device Reset Message is successful.
2377 *
2378 * Return Value:
2379 * ADV_TRUE(1) - All requests on the target are purged.
2380 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2381 * are not purged.
2382 */
2383#define AdvResetDevice(asc_dvc, target_id) \
2384 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2385 (ADV_DCNT) (target_id))
2386
2387/*
2388 * SCSI Wide Type definition.
2389 */
2390#define ADV_SCSI_BIT_ID_TYPE ushort
2391
2392/*
2393 * AdvInitScsiTarget() 'cntl_flag' options.
2394 */
2395#define ADV_SCAN_LUN 0x01
2396#define ADV_CAPINFO_NOLUN 0x02
2397
2398/*
2399 * Convert target id to target id bit mask.
2400 */
2401#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2402
2403/*
2404 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2405 */
2406
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002407#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408#define QD_NO_ERROR 0x01
2409#define QD_ABORTED_BY_HOST 0x02
2410#define QD_WITH_ERROR 0x04
2411
2412#define QHSTA_NO_ERROR 0x00
2413#define QHSTA_M_SEL_TIMEOUT 0x11
2414#define QHSTA_M_DATA_OVER_RUN 0x12
2415#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2416#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002417#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2418#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2419#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2420#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2421#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2422#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2423#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002425#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2426#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2427#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2428#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2429#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2430#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2431#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2432#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433#define QHSTA_M_WTM_TIMEOUT 0x41
2434#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2435#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2436#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002437#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2438#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2439#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 * DvcGetPhyAddr() flag arguments
2443 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002444#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2445#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2446#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2447#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2448#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2449#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
2451/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2452#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2453#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2454#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2455
2456/*
2457 * Total contiguous memory needed for driver SG blocks.
2458 *
2459 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2460 * number of scatter-gather elements the driver supports in a
2461 * single request.
2462 */
2463
2464#define ADV_SG_LIST_MAX_BYTE_SIZE \
2465 (sizeof(ADV_SG_BLOCK) * \
2466 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2467
2468/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 * --- Driver Constants and Macros
2470 */
2471
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472/* Reference Scsi_Host hostdata */
2473#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
2474
2475/* asc_board_t flags */
2476#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002477#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478#define ASC_SELECT_QUEUE_DEPTHS 0x08
2479
2480#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
2481#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
2482
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002483#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002485#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
2487#ifdef CONFIG_PROC_FS
2488/* /proc/scsi/advansys/[0...] related definitions */
2489#define ASC_PRTBUF_SIZE 2048
2490#define ASC_PRTLINE_SIZE 160
2491
2492#define ASC_PRT_NEXT() \
2493 if (cp) { \
2494 totlen += len; \
2495 leftlen -= len; \
2496 if (leftlen == 0) { \
2497 return totlen; \
2498 } \
2499 cp += len; \
2500 }
2501#endif /* CONFIG_PROC_FS */
2502
2503/* Asc Library return codes */
2504#define ASC_TRUE 1
2505#define ASC_FALSE 0
2506#define ASC_NOERROR 1
2507#define ASC_BUSY 0
2508#define ASC_ERROR (-1)
2509
2510/* struct scsi_cmnd function return codes */
2511#define STATUS_BYTE(byte) (byte)
2512#define MSG_BYTE(byte) ((byte) << 8)
2513#define HOST_BYTE(byte) ((byte) << 16)
2514#define DRIVER_BYTE(byte) ((byte) << 24)
2515
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002517#define ASC_STATS(shost, counter)
2518#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002520#define ASC_STATS(shost, counter) \
2521 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002523#define ASC_STATS_ADD(shost, counter, count) \
2524 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525#endif /* ADVANSYS_STATS */
2526
2527#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2528
2529/* If the result wraps when calculating tenths, return 0. */
2530#define ASC_TENTHS(num, den) \
2531 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2532 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2533
2534/*
2535 * Display a message to the console.
2536 */
2537#define ASC_PRINT(s) \
2538 { \
2539 printk("advansys: "); \
2540 printk(s); \
2541 }
2542
2543#define ASC_PRINT1(s, a1) \
2544 { \
2545 printk("advansys: "); \
2546 printk((s), (a1)); \
2547 }
2548
2549#define ASC_PRINT2(s, a1, a2) \
2550 { \
2551 printk("advansys: "); \
2552 printk((s), (a1), (a2)); \
2553 }
2554
2555#define ASC_PRINT3(s, a1, a2, a3) \
2556 { \
2557 printk("advansys: "); \
2558 printk((s), (a1), (a2), (a3)); \
2559 }
2560
2561#define ASC_PRINT4(s, a1, a2, a3, a4) \
2562 { \
2563 printk("advansys: "); \
2564 printk((s), (a1), (a2), (a3), (a4)); \
2565 }
2566
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567#ifndef ADVANSYS_DEBUG
2568
2569#define ASC_DBG(lvl, s)
2570#define ASC_DBG1(lvl, s, a1)
2571#define ASC_DBG2(lvl, s, a1, a2)
2572#define ASC_DBG3(lvl, s, a1, a2, a3)
2573#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2574#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2575#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
2576#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2577#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2578#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2579#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2580#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2581#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2582#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2583#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2584
2585#else /* ADVANSYS_DEBUG */
2586
2587/*
2588 * Debugging Message Levels:
2589 * 0: Errors Only
2590 * 1: High-Level Tracing
2591 * 2-N: Verbose Tracing
2592 */
2593
2594#define ASC_DBG(lvl, s) \
2595 { \
2596 if (asc_dbglvl >= (lvl)) { \
2597 printk(s); \
2598 } \
2599 }
2600
2601#define ASC_DBG1(lvl, s, a1) \
2602 { \
2603 if (asc_dbglvl >= (lvl)) { \
2604 printk((s), (a1)); \
2605 } \
2606 }
2607
2608#define ASC_DBG2(lvl, s, a1, a2) \
2609 { \
2610 if (asc_dbglvl >= (lvl)) { \
2611 printk((s), (a1), (a2)); \
2612 } \
2613 }
2614
2615#define ASC_DBG3(lvl, s, a1, a2, a3) \
2616 { \
2617 if (asc_dbglvl >= (lvl)) { \
2618 printk((s), (a1), (a2), (a3)); \
2619 } \
2620 }
2621
2622#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2623 { \
2624 if (asc_dbglvl >= (lvl)) { \
2625 printk((s), (a1), (a2), (a3), (a4)); \
2626 } \
2627 }
2628
2629#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2630 { \
2631 if (asc_dbglvl >= (lvl)) { \
2632 asc_prt_scsi_host(s); \
2633 } \
2634 }
2635
2636#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
2637 { \
2638 if (asc_dbglvl >= (lvl)) { \
2639 asc_prt_scsi_cmnd(s); \
2640 } \
2641 }
2642
2643#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2644 { \
2645 if (asc_dbglvl >= (lvl)) { \
2646 asc_prt_asc_scsi_q(scsiqp); \
2647 } \
2648 }
2649
2650#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2651 { \
2652 if (asc_dbglvl >= (lvl)) { \
2653 asc_prt_asc_qdone_info(qdone); \
2654 } \
2655 }
2656
2657#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2658 { \
2659 if (asc_dbglvl >= (lvl)) { \
2660 asc_prt_adv_scsi_req_q(scsiqp); \
2661 } \
2662 }
2663
2664#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2665 { \
2666 if (asc_dbglvl >= (lvl)) { \
2667 asc_prt_hex((name), (start), (length)); \
2668 } \
2669 }
2670
2671#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2672 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2673
2674#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2675 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2676
2677#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2678 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2679#endif /* ADVANSYS_DEBUG */
2680
2681#ifndef ADVANSYS_ASSERT
2682#define ASC_ASSERT(a)
2683#else /* ADVANSYS_ASSERT */
2684
2685#define ASC_ASSERT(a) \
2686 { \
2687 if (!(a)) { \
2688 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
2689 __FILE__, __LINE__); \
2690 } \
2691 }
2692
2693#endif /* ADVANSYS_ASSERT */
2694
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695/*
2696 * --- Driver Structures
2697 */
2698
2699#ifdef ADVANSYS_STATS
2700
2701/* Per board statistics structure */
2702struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002703 /* Driver Entrypoint Statistics */
2704 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2705 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2706 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2707 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2708 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2709 ADV_DCNT done; /* # calls to request's scsi_done function */
2710 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2711 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2712 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2713 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2714 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2715 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2716 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2717 ADV_DCNT exe_unknown; /* # unknown returns. */
2718 /* Data Transfer Statistics */
2719 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2720 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2721 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2722 ADV_DCNT sg_elem; /* # scatter-gather elements */
2723 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724};
2725#endif /* ADVANSYS_STATS */
2726
2727/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 * Adv Library Request Structures
2729 *
2730 * The following two structures are used to process Wide Board requests.
2731 *
2732 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2733 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2734 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2735 * Mid-Level SCSI request structure.
2736 *
2737 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2738 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2739 * up to 255 scatter-gather elements may be used per request or
2740 * ADV_SCSI_REQ_Q.
2741 *
2742 * Both structures must be 32 byte aligned.
2743 */
2744typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002745 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2746 uchar align[32]; /* Sgblock structure padding. */
2747 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748} adv_sgblk_t;
2749
2750typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002751 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2752 uchar align[32]; /* Request structure padding. */
2753 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2754 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2755 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756} adv_req_t;
2757
2758/*
2759 * Structure allocated for each board.
2760 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002761 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 * of the 'Scsi_Host' structure starting at the 'hostdata'
2763 * field. It is guaranteed to be allocated from DMA-able memory.
2764 */
2765typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002766 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002767 int id; /* Board Id */
2768 uint flags; /* Board flags */
2769 union {
2770 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2771 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2772 } dvc_var;
2773 union {
2774 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2775 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2776 } dvc_cfg;
2777 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002778 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
2779 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
2780 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2781 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2782 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2783 union {
2784 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2785 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2786 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2787 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2788 } eep_config;
2789 ulong last_reset; /* Saved last reset time */
2790 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002791 /* /proc/scsi/advansys/[0...] */
2792 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002794 struct asc_stats asc_stats; /* Board statistics */
2795#endif /* ADVANSYS_STATS */
2796 /*
2797 * The following fields are used only for Narrow Boards.
2798 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002799 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2800 /*
2801 * The following fields are used only for Wide Boards.
2802 */
2803 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2804 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002805 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002806 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2807 adv_req_t *adv_reqp; /* Request structures. */
2808 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2809 ushort bios_signature; /* BIOS Signature. */
2810 ushort bios_version; /* BIOS Version. */
2811 ushort bios_codeseg; /* BIOS Code Segment. */
2812 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813} asc_board_t;
2814
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002815#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2816 dvc_var.adv_dvc_var)
2817#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2818
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002820static int asc_board_count;
2821
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002823static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
2825/*
2826 * Global structures required to issue a command.
2827 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002828static ASC_SCSI_Q asc_scsi_q = { {0} };
2829static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002832static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833#endif /* ADVANSYS_DEBUG */
2834
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835/*
2836 * --- Driver Function Prototypes
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 */
2838
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002839static int advansys_slave_configure(struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002840static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
2841static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
2842static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
2843static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002845static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
2846static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
2847static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
2848static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
2849static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
2850static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
2851static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
2852static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
2853static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
2854static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855#endif /* CONFIG_PROC_FS */
2856
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857/* Statistics function prototypes. */
2858#ifdef ADVANSYS_STATS
2859#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002860static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861#endif /* CONFIG_PROC_FS */
2862#endif /* ADVANSYS_STATS */
2863
2864/* Debug function prototypes. */
2865#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002866static void asc_prt_scsi_host(struct Scsi_Host *);
2867static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
2868static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
2869static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
2870static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
2871static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
2872static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
2873static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
2874static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
2875static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
2876static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877#endif /* ADVANSYS_DEBUG */
2878
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879#ifdef CONFIG_PROC_FS
2880/*
Matthew Wilcoxc304ec92007-07-30 09:18:45 -06002881 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882 *
2883 * *buffer: I/O buffer
2884 * **start: if inout == FALSE pointer into buffer where user read should start
2885 * offset: current offset into a /proc/scsi/advansys/[0...] file
2886 * length: length of buffer
2887 * hostno: Scsi_Host host_no
2888 * inout: TRUE - user is writing; FALSE - user is reading
2889 *
2890 * Return the number of bytes read from or written to a
2891 * /proc/scsi/advansys/[0...] file.
2892 *
2893 * Note: This function uses the per board buffer 'prtbuf' which is
2894 * allocated when the board is initialized in advansys_detect(). The
2895 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
2896 * used to write to the buffer. The way asc_proc_copy() is written
2897 * if 'prtbuf' is too small it will not be overwritten. Instead the
2898 * user just won't get all the available statistics.
2899 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07002900static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002902 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002904 asc_board_t *boardp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002905 char *cp;
2906 int cplen;
2907 int cnt;
2908 int totcnt;
2909 int leftlen;
2910 char *curbuf;
2911 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002913 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002915 /*
2916 * User write not supported.
2917 */
2918 if (inout == TRUE) {
2919 return (-ENOSYS);
2920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002922 /*
2923 * User read of /proc/scsi/advansys/[0...] file.
2924 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
Matthew Wilcox2a437952007-07-26 11:00:51 -04002926 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002928 /* Copy read data starting at the beginning of the buffer. */
2929 *start = buffer;
2930 curbuf = buffer;
2931 advoffset = 0;
2932 totcnt = 0;
2933 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002935 /*
2936 * Get board configuration information.
2937 *
2938 * advansys_info() returns the board string from its own static buffer.
2939 */
Matthew Wilcox2a437952007-07-26 11:00:51 -04002940 cp = (char *)advansys_info(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002941 strcat(cp, "\n");
2942 cplen = strlen(cp);
2943 /* Copy board information. */
2944 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2945 totcnt += cnt;
2946 leftlen -= cnt;
2947 if (leftlen == 0) {
2948 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2949 return totcnt;
2950 }
2951 advoffset += cplen;
2952 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002954 /*
2955 * Display Wide Board BIOS Information.
2956 */
2957 if (ASC_WIDE_BOARD(boardp)) {
2958 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002959 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002960 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002961 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002962 cplen);
2963 totcnt += cnt;
2964 leftlen -= cnt;
2965 if (leftlen == 0) {
2966 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2967 return totcnt;
2968 }
2969 advoffset += cplen;
2970 curbuf += cnt;
2971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002973 /*
2974 * Display driver information for each device attached to the board.
2975 */
2976 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002977 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002978 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
2979 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2980 totcnt += cnt;
2981 leftlen -= cnt;
2982 if (leftlen == 0) {
2983 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2984 return totcnt;
2985 }
2986 advoffset += cplen;
2987 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002989 /*
2990 * Display EEPROM configuration for the board.
2991 */
2992 cp = boardp->prtbuf;
2993 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04002994 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002995 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04002996 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002997 }
2998 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
2999 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3000 totcnt += cnt;
3001 leftlen -= cnt;
3002 if (leftlen == 0) {
3003 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3004 return totcnt;
3005 }
3006 advoffset += cplen;
3007 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003009 /*
3010 * Display driver configuration and information for the board.
3011 */
3012 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003013 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003014 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3015 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3016 totcnt += cnt;
3017 leftlen -= cnt;
3018 if (leftlen == 0) {
3019 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3020 return totcnt;
3021 }
3022 advoffset += cplen;
3023 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
3025#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003026 /*
3027 * Display driver statistics for the board.
3028 */
3029 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003030 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003031 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
3032 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3033 totcnt += cnt;
3034 leftlen -= cnt;
3035 if (leftlen == 0) {
3036 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3037 return totcnt;
3038 }
3039 advoffset += cplen;
3040 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041#endif /* ADVANSYS_STATS */
3042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003043 /*
3044 * Display Asc Library dynamic configuration information
3045 * for the board.
3046 */
3047 cp = boardp->prtbuf;
3048 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003049 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003050 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003051 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003052 }
3053 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3054 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3055 totcnt += cnt;
3056 leftlen -= cnt;
3057 if (leftlen == 0) {
3058 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3059 return totcnt;
3060 }
3061 advoffset += cplen;
3062 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003064 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003066 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067}
3068#endif /* CONFIG_PROC_FS */
3069
3070/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 * advansys_info()
3072 *
3073 * Return suitable for printing on the console with the argument
3074 * adapter's configuration information.
3075 *
3076 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
3077 * otherwise the static 'info' array will be overrun.
3078 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003079static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003081 static char info[ASC_INFO_SIZE];
3082 asc_board_t *boardp;
3083 ASC_DVC_VAR *asc_dvc_varp;
3084 ADV_DVC_VAR *adv_dvc_varp;
3085 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003086 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003088 boardp = ASC_BOARDP(shost);
3089 if (ASC_NARROW_BOARD(boardp)) {
3090 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3091 ASC_DBG(1, "advansys_info: begin\n");
3092 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3093 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
3094 ASC_IS_ISAPNP) {
3095 busname = "ISA PnP";
3096 } else {
3097 busname = "ISA";
3098 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003099 sprintf(info,
3100 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
3101 ASC_VERSION, busname,
3102 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003103 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3104 shost->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003105 } else {
3106 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
3107 busname = "VL";
3108 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
3109 busname = "EISA";
3110 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
3111 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
3112 == ASC_IS_PCI_ULTRA) {
3113 busname = "PCI Ultra";
3114 } else {
3115 busname = "PCI";
3116 }
3117 } else {
3118 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003119 ASC_PRINT2("advansys_info: board %d: unknown "
3120 "bus type %d\n", boardp->id,
3121 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003122 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003123 sprintf(info,
3124 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003125 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003126 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3127 shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003128 }
3129 } else {
3130 /*
3131 * Wide Adapter Information
3132 *
3133 * Memory-mapped I/O is used instead of I/O space to access
3134 * the adapter, but display the I/O Port range. The Memory
3135 * I/O address is displayed through the driver /proc file.
3136 */
3137 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3138 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003139 widename = "Ultra-Wide";
3140 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003141 widename = "Ultra2-Wide";
3142 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003143 widename = "Ultra3-Wide";
3144 }
3145 sprintf(info,
3146 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
3147 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003148 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003149 }
3150 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
3151 ASC_DBG(1, "advansys_info: end\n");
3152 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153}
3154
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003155static void asc_scsi_done(struct scsi_cmnd *scp)
3156{
3157 struct asc_board *boardp = ASC_BOARDP(scp->device->host);
3158
3159 if (scp->use_sg)
3160 dma_unmap_sg(boardp->dev,
3161 (struct scatterlist *)scp->request_buffer,
3162 scp->use_sg, scp->sc_data_direction);
3163 else if (scp->request_bufflen)
3164 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
3165 scp->request_bufflen, scp->sc_data_direction);
3166
3167 ASC_STATS(scp->device->host, done);
3168
3169 scp->scsi_done(scp);
3170}
3171
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172/*
3173 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
3174 *
3175 * This function always returns 0. Command return status is saved
3176 * in the 'scp' result field.
3177 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003178static int
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003179advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003181 struct Scsi_Host *shost;
3182 asc_board_t *boardp;
3183 ulong flags;
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003184 int asc_res, result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003186 shost = scp->device->host;
3187 boardp = ASC_BOARDP(shost);
3188 ASC_STATS(shost, queuecommand);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003190 /* host_lock taken by mid-level prior to call but need to protect */
3191 /* against own ISR */
3192 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003194 scp->scsi_done = done;
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003195 asc_res = asc_execute_scsi_cmnd(scp);
3196 switch (asc_res) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003197 case ASC_NOERROR:
3198 break;
3199 case ASC_BUSY:
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003200 result = SCSI_MLQUEUE_HOST_BUSY;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003201 break;
3202 case ASC_ERROR:
3203 default:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003204 /* Interrupts could be enabled here. */
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003205 asc_scsi_done(scp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003206 break;
3207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003210 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211}
3212
3213/*
3214 * advansys_reset()
3215 *
3216 * Reset the bus associated with the command 'scp'.
3217 *
3218 * This function runs its own thread. Interrupts must be blocked but
3219 * sleeping is allowed and no locking other than for host structures is
3220 * required. Returns SUCCESS or FAILED.
3221 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003222static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003224 struct Scsi_Host *shost;
3225 asc_board_t *boardp;
3226 ASC_DVC_VAR *asc_dvc_varp;
3227 ADV_DVC_VAR *adv_dvc_varp;
3228 ulong flags;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003229 int status;
3230 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003232 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233
3234#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003235 if (scp->device->host != NULL) {
3236 ASC_STATS(scp->device->host, reset);
3237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238#endif /* ADVANSYS_STATS */
3239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003240 if ((shost = scp->device->host) == NULL) {
3241 scp->result = HOST_BYTE(DID_ERROR);
3242 return FAILED;
3243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003245 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003247 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
3248 boardp->id);
3249 /*
3250 * Check for re-entrancy.
3251 */
3252 spin_lock_irqsave(&boardp->lock, flags);
3253 if (boardp->flags & ASC_HOST_IN_RESET) {
3254 spin_unlock_irqrestore(&boardp->lock, flags);
3255 return FAILED;
3256 }
3257 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003260 if (ASC_NARROW_BOARD(boardp)) {
3261 /*
3262 * Narrow Board
3263 */
3264 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003266 /*
3267 * Reset the chip and SCSI bus.
3268 */
3269 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
3270 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003272 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
3273 if (asc_dvc_varp->err_code) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003274 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3275 "error: 0x%x\n", boardp->id,
3276 asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003277 ret = FAILED;
3278 } else if (status) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003279 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3280 "warning: 0x%x\n", boardp->id, status);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003281 } else {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003282 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3283 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003286 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
3287 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003289 } else {
3290 /*
3291 * Wide Board
3292 *
3293 * If the suggest reset bus flags are set, then reset the bus.
3294 * Otherwise only reset the device.
3295 */
3296 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003298 /*
3299 * Reset the target's SCSI bus.
3300 */
3301 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
3302 switch (AdvResetChipAndSB(adv_dvc_varp)) {
3303 case ASC_TRUE:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003304 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3305 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003306 break;
3307 case ASC_FALSE:
3308 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003309 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3310 "error.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003311 ret = FAILED;
3312 break;
3313 }
3314 spin_lock_irqsave(&boardp->lock, flags);
3315 (void)AdvISR(adv_dvc_varp);
3316 }
3317 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003319 /* Save the time of the most recently completed reset. */
3320 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003322 /* Clear reset flag. */
3323 boardp->flags &= ~ASC_HOST_IN_RESET;
3324 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003326 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003328 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329}
3330
3331/*
3332 * advansys_biosparam()
3333 *
3334 * Translate disk drive geometry if the "BIOS greater than 1 GB"
3335 * support is enabled for a drive.
3336 *
3337 * ip (information pointer) is an int array with the following definition:
3338 * ip[0]: heads
3339 * ip[1]: sectors
3340 * ip[2]: cylinders
3341 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003342static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003344 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003346 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003348 ASC_DBG(1, "advansys_biosparam: begin\n");
3349 ASC_STATS(sdev->host, biosparam);
3350 boardp = ASC_BOARDP(sdev->host);
3351 if (ASC_NARROW_BOARD(boardp)) {
3352 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
3353 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
3354 ip[0] = 255;
3355 ip[1] = 63;
3356 } else {
3357 ip[0] = 64;
3358 ip[1] = 32;
3359 }
3360 } else {
3361 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
3362 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
3363 ip[0] = 255;
3364 ip[1] = 63;
3365 } else {
3366 ip[0] = 64;
3367 ip[1] = 32;
3368 }
3369 }
3370 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
3371 ASC_DBG(1, "advansys_biosparam: end\n");
3372 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373}
3374
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003375static struct scsi_host_template advansys_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003376 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003378 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003380 .name = "advansys",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003381 .info = advansys_info,
3382 .queuecommand = advansys_queuecommand,
3383 .eh_bus_reset_handler = advansys_reset,
3384 .bios_param = advansys_biosparam,
3385 .slave_configure = advansys_slave_configure,
3386 /*
3387 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003388 * must be set. The flag will be cleared in advansys_board_found
3389 * for non-ISA adapters.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003390 */
3391 .unchecked_isa_dma = 1,
3392 /*
3393 * All adapters controlled by this driver are capable of large
3394 * scatter-gather lists. According to the mid-level SCSI documentation
3395 * this obviates any performance gain provided by setting
3396 * 'use_clustering'. But empirically while CPU utilization is increased
3397 * by enabling clustering, I/O throughput increases as well.
3398 */
3399 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402/*
3403 * --- Miscellaneous Driver Functions
3404 */
3405
3406/*
3407 * First-level interrupt handler.
3408 *
3409 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
3410 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
3411 * is not referenced. 'dev_id' could be used to identify an interrupt passed
3412 * to the AdvanSys driver which is for a device sharing an interrupt with
3413 * an AdvanSys adapter.
3414 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003415static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416{
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003417 unsigned long flags;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003418 struct Scsi_Host *shost = dev_id;
3419 asc_board_t *boardp = ASC_BOARDP(shost);
3420 irqreturn_t result = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003422 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
3423 spin_lock_irqsave(&boardp->lock, flags);
3424 if (ASC_NARROW_BOARD(boardp)) {
3425 /*
3426 * Narrow Board
3427 */
3428 if (AscIsIntPending(shost->io_port)) {
3429 result = IRQ_HANDLED;
3430 ASC_STATS(shost, interrupt);
3431 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
3432 AscISR(&boardp->dvc_var.asc_dvc_var);
3433 }
3434 } else {
3435 /*
3436 * Wide Board
3437 */
3438 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
3439 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
3440 result = IRQ_HANDLED;
3441 ASC_STATS(shost, interrupt);
3442 }
3443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003445 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003447 /*
3448 * If interrupts were enabled on entry, then they
3449 * are now enabled here.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003450 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003452 ASC_DBG(1, "advansys_interrupt: end\n");
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003453 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454}
3455
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003456static void
3457advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
3458{
3459 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
3460 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
3461
3462 if (sdev->lun == 0) {
3463 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
3464 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
3465 asc_dvc->init_sdtr |= tid_bit;
3466 } else {
3467 asc_dvc->init_sdtr &= ~tid_bit;
3468 }
3469
3470 if (orig_init_sdtr != asc_dvc->init_sdtr)
3471 AscAsyncFix(asc_dvc, sdev);
3472 }
3473
3474 if (sdev->tagged_supported) {
3475 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
3476 if (sdev->lun == 0) {
3477 asc_dvc->cfg->can_tagged_qng |= tid_bit;
3478 asc_dvc->use_tagged_qng |= tid_bit;
3479 }
3480 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3481 asc_dvc->max_dvc_qng[sdev->id]);
3482 }
3483 } else {
3484 if (sdev->lun == 0) {
3485 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
3486 asc_dvc->use_tagged_qng &= ~tid_bit;
3487 }
3488 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3489 }
3490
3491 if ((sdev->lun == 0) &&
3492 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
3493 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
3494 asc_dvc->cfg->disc_enable);
3495 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
3496 asc_dvc->use_tagged_qng);
3497 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
3498 asc_dvc->cfg->can_tagged_qng);
3499
3500 asc_dvc->max_dvc_qng[sdev->id] =
3501 asc_dvc->cfg->max_tag_qng[sdev->id];
3502 AscWriteLramByte(asc_dvc->iop_base,
3503 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
3504 asc_dvc->max_dvc_qng[sdev->id]);
3505 }
3506}
3507
3508/*
3509 * Wide Transfers
3510 *
3511 * If the EEPROM enabled WDTR for the device and the device supports wide
3512 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
3513 * write the new value to the microcode.
3514 */
3515static void
3516advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
3517{
3518 unsigned short cfg_word;
3519 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3520 if ((cfg_word & tidmask) != 0)
3521 return;
3522
3523 cfg_word |= tidmask;
3524 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3525
3526 /*
3527 * Clear the microcode SDTR and WDTR negotiation done indicators for
3528 * the target to cause it to negotiate with the new setting set above.
3529 * WDTR when accepted causes the target to enter asynchronous mode, so
3530 * SDTR must be negotiated.
3531 */
3532 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3533 cfg_word &= ~tidmask;
3534 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3535 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3536 cfg_word &= ~tidmask;
3537 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3538}
3539
3540/*
3541 * Synchronous Transfers
3542 *
3543 * If the EEPROM enabled SDTR for the device and the device
3544 * supports synchronous transfers, then turn on the device's
3545 * 'sdtr_able' bit. Write the new value to the microcode.
3546 */
3547static void
3548advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
3549{
3550 unsigned short cfg_word;
3551 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3552 if ((cfg_word & tidmask) != 0)
3553 return;
3554
3555 cfg_word |= tidmask;
3556 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3557
3558 /*
3559 * Clear the microcode "SDTR negotiation" done indicator for the
3560 * target to cause it to negotiate with the new setting set above.
3561 */
3562 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3563 cfg_word &= ~tidmask;
3564 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3565}
3566
3567/*
3568 * PPR (Parallel Protocol Request) Capable
3569 *
3570 * If the device supports DT mode, then it must be PPR capable.
3571 * The PPR message will be used in place of the SDTR and WDTR
3572 * messages to negotiate synchronous speed and offset, transfer
3573 * width, and protocol options.
3574 */
3575static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
3576 AdvPortAddr iop_base, unsigned short tidmask)
3577{
3578 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3579 adv_dvc->ppr_able |= tidmask;
3580 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3581}
3582
3583static void
3584advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
3585{
3586 AdvPortAddr iop_base = adv_dvc->iop_base;
3587 unsigned short tidmask = 1 << sdev->id;
3588
3589 if (sdev->lun == 0) {
3590 /*
3591 * Handle WDTR, SDTR, and Tag Queuing. If the feature
3592 * is enabled in the EEPROM and the device supports the
3593 * feature, then enable it in the microcode.
3594 */
3595
3596 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
3597 advansys_wide_enable_wdtr(iop_base, tidmask);
3598 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
3599 advansys_wide_enable_sdtr(iop_base, tidmask);
3600 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
3601 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
3602
3603 /*
3604 * Tag Queuing is disabled for the BIOS which runs in polled
3605 * mode and would see no benefit from Tag Queuing. Also by
3606 * disabling Tag Queuing in the BIOS devices with Tag Queuing
3607 * bugs will at least work with the BIOS.
3608 */
3609 if ((adv_dvc->tagqng_able & tidmask) &&
3610 sdev->tagged_supported) {
3611 unsigned short cfg_word;
3612 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
3613 cfg_word |= tidmask;
3614 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
3615 cfg_word);
3616 AdvWriteByteLram(iop_base,
3617 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
3618 adv_dvc->max_dvc_qng);
3619 }
3620 }
3621
3622 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
3623 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3624 adv_dvc->max_dvc_qng);
3625 } else {
3626 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3627 }
3628}
3629
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630/*
3631 * Set the number of commands to queue per device for the
3632 * specified host adapter.
3633 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003634static int advansys_slave_configure(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003636 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003637 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003638
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003639 /*
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003640 * Save a pointer to the sdev and set its initial/maximum
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003641 * queue depth. Only save the pointer for a lun0 dev though.
3642 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003643 if (sdev->lun == 0)
3644 boardp->device[sdev->id] = sdev;
3645
3646 if (ASC_NARROW_BOARD(boardp))
3647 advansys_narrow_slave_configure(sdev,
3648 &boardp->dvc_var.asc_dvc_var);
3649 else
3650 advansys_wide_slave_configure(sdev,
3651 &boardp->dvc_var.adv_dvc_var);
3652
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003653 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654}
3655
3656/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 * Execute a single 'Scsi_Cmnd'.
3658 *
3659 * The function 'done' is called when the request has been completed.
3660 *
3661 * Scsi_Cmnd:
3662 *
3663 * host - board controlling device
3664 * device - device to send command
3665 * target - target of device
3666 * lun - lun of device
3667 * cmd_len - length of SCSI CDB
3668 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
3669 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
3670 *
3671 * if (use_sg == 0) {
3672 * request_buffer - buffer address for request
3673 * request_bufflen - length of request buffer
3674 * } else {
3675 * request_buffer - pointer to scatterlist structure
3676 * }
3677 *
3678 * sense_buffer - sense command buffer
3679 *
3680 * result (4 bytes of an int):
3681 * Byte Meaning
3682 * 0 SCSI Status Byte Code
3683 * 1 SCSI One Byte Message Code
3684 * 2 Host Error Code
3685 * 3 Mid-Level Error Code
3686 *
3687 * host driver fields:
3688 * SCp - Scsi_Pointer used for command processing status
3689 * scsi_done - used to save caller's done function
3690 * host_scribble - used for pointer to another struct scsi_cmnd
3691 *
Matthew Wilcox349d2c42007-09-09 08:56:34 -06003692 * If this function returns ASC_NOERROR the request will be completed
3693 * from the interrupt handler.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003695 * If this function returns ASC_ERROR the host error code has been set,
3696 * and the called must call asc_scsi_done.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 *
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003698 * If ASC_BUSY is returned the request will be returned to the midlayer
3699 * and re-tried later.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003701static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003703 asc_board_t *boardp;
3704 ASC_DVC_VAR *asc_dvc_varp;
3705 ADV_DVC_VAR *adv_dvc_varp;
3706 ADV_SCSI_REQ_Q *adv_scsiqp;
3707 struct scsi_device *device;
3708 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003710 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
3711 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003713 boardp = ASC_BOARDP(scp->device->host);
3714 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003716 if (ASC_NARROW_BOARD(boardp)) {
3717 /*
3718 * Build and execute Narrow Board request.
3719 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003721 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003723 /*
3724 * Build Asc Library request structure using the
3725 * global structures 'asc_scsi_req' and 'asc_sg_head'.
3726 *
3727 * If an error is returned, then the request has been
3728 * queued on the board done queue. It will be completed
3729 * by the caller.
3730 *
3731 * asc_build_req() can not return ASC_BUSY.
3732 */
3733 if (asc_build_req(boardp, scp) == ASC_ERROR) {
3734 ASC_STATS(scp->device->host, build_error);
3735 return ASC_ERROR;
3736 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003738 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
3739 case ASC_NOERROR:
3740 ASC_STATS(scp->device->host, exe_noerror);
3741 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003742 * Increment monotonically increasing per device
3743 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003744 */
3745 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003746 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), "
3747 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003748 break;
3749 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003750 ASC_STATS(scp->device->host, exe_busy);
3751 break;
3752 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003753 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3754 "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3755 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003756 ASC_STATS(scp->device->host, exe_error);
3757 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003758 break;
3759 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003760 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3761 "AscExeScsiQueue() unknown, err_code 0x%x\n",
3762 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003763 ASC_STATS(scp->device->host, exe_unknown);
3764 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003765 break;
3766 }
3767 } else {
3768 /*
3769 * Build and execute Wide Board request.
3770 */
3771 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003773 /*
3774 * Build and get a pointer to an Adv Library request structure.
3775 *
3776 * If the request is successfully built then send it below,
3777 * otherwise return with an error.
3778 */
3779 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
3780 case ASC_NOERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003781 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
3782 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003783 break;
3784 case ASC_BUSY:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003785 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3786 "ASC_BUSY\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003787 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003788 * The asc_stats fields 'adv_build_noreq' and
3789 * 'adv_build_nosg' count wide board busy conditions.
3790 * They are updated in adv_build_req and
3791 * adv_get_sglist, respectively.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003792 */
3793 return ASC_BUSY;
3794 case ASC_ERROR:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003795 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003796 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3797 "ASC_ERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003798 ASC_STATS(scp->device->host, build_error);
3799 return ASC_ERROR;
3800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003802 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
3803 case ASC_NOERROR:
3804 ASC_STATS(scp->device->host, exe_noerror);
3805 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003806 * Increment monotonically increasing per device
3807 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003808 */
3809 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003810 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), "
3811 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003812 break;
3813 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003814 ASC_STATS(scp->device->host, exe_busy);
3815 break;
3816 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003817 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3818 "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3819 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003820 ASC_STATS(scp->device->host, exe_error);
3821 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003822 break;
3823 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003824 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3825 "AdvExeScsiQueue() unknown, err_code 0x%x\n",
3826 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003827 ASC_STATS(scp->device->host, exe_unknown);
3828 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003829 break;
3830 }
3831 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003833 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
3834 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835}
3836
3837/*
3838 * Build a request structure for the Asc Library (Narrow Board).
3839 *
3840 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
3841 * used to build the request.
3842 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003843 * If an error occurs, then return ASC_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003845static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003847 /*
3848 * Mutually exclusive access is required to 'asc_scsi_q' and
3849 * 'asc_sg_head' until after the request is started.
3850 */
3851 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003853 /*
3854 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
3855 */
3856 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003858 /*
3859 * Build the ASC_SCSI_Q request.
3860 *
3861 * For narrow boards a CDB length maximum of 12 bytes
3862 * is supported.
3863 */
3864 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003865 ASC_PRINT3("asc_build_req: board %d: cmd_len %d > "
3866 "ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len,
3867 ASC_MAX_CDB_LEN);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003868 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003869 return ASC_ERROR;
3870 }
3871 asc_scsi_q.cdbptr = &scp->cmnd[0];
3872 asc_scsi_q.q2.cdb_len = scp->cmd_len;
3873 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
3874 asc_scsi_q.q1.target_lun = scp->device->lun;
3875 asc_scsi_q.q2.target_ix =
3876 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
3877 asc_scsi_q.q1.sense_addr =
3878 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
3879 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003881 /*
3882 * If there are any outstanding requests for the current target,
3883 * then every 255th request send an ORDERED request. This heuristic
3884 * tries to retain the benefit of request sorting while preventing
3885 * request starvation. 255 is the max number of tags or pending commands
3886 * a device may have outstanding.
3887 *
3888 * The request count is incremented below for every successfully
3889 * started request.
3890 *
3891 */
3892 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
3893 (boardp->reqcnt[scp->device->id] % 255) == 0) {
3894 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
3895 } else {
3896 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
3897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003899 /*
3900 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
3901 * buffer command.
3902 */
3903 if (scp->use_sg == 0) {
3904 /*
3905 * CDB request of single contiguous buffer.
3906 */
3907 ASC_STATS(scp->device->host, cont_cnt);
3908 scp->SCp.dma_handle = scp->request_bufflen ?
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003909 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003910 scp->request_bufflen,
3911 scp->sc_data_direction) : 0;
3912 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
3913 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
3914 ASC_STATS_ADD(scp->device->host, cont_xfer,
3915 ASC_CEILING(scp->request_bufflen, 512));
3916 asc_scsi_q.q1.sg_queue_cnt = 0;
3917 asc_scsi_q.sg_head = NULL;
3918 } else {
3919 /*
3920 * CDB scatter-gather request list.
3921 */
3922 int sgcnt;
3923 int use_sg;
3924 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003926 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003927 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
3928 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003930 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003931 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
3932 "sg_tablesize %d\n", boardp->id, use_sg,
3933 scp->device->host->sg_tablesize);
3934 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003935 scp->sc_data_direction);
3936 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003937 return ASC_ERROR;
3938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003940 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003942 /*
3943 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
3944 * structure to point to it.
3945 */
3946 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003948 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
3949 asc_scsi_q.sg_head = &asc_sg_head;
3950 asc_scsi_q.q1.data_cnt = 0;
3951 asc_scsi_q.q1.data_addr = 0;
3952 /* This is a byte value, otherwise it would need to be swapped. */
3953 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
3954 ASC_STATS_ADD(scp->device->host, sg_elem,
3955 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003957 /*
3958 * Convert scatter-gather list into ASC_SG_HEAD list.
3959 */
3960 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
3961 asc_sg_head.sg_list[sgcnt].addr =
3962 cpu_to_le32(sg_dma_address(slp));
3963 asc_sg_head.sg_list[sgcnt].bytes =
3964 cpu_to_le32(sg_dma_len(slp));
3965 ASC_STATS_ADD(scp->device->host, sg_xfer,
3966 ASC_CEILING(sg_dma_len(slp), 512));
3967 }
3968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003970 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
3971 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003973 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974}
3975
3976/*
3977 * Build a request structure for the Adv Library (Wide Board).
3978 *
3979 * If an adv_req_t can not be allocated to issue the request,
3980 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
3981 *
3982 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
3983 * microcode for DMA addresses or math operations are byte swapped
3984 * to little-endian order.
3985 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003986static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003988 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003990 adv_req_t *reqp;
3991 ADV_SCSI_REQ_Q *scsiqp;
3992 int i;
3993 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003995 /*
3996 * Allocate an adv_req_t structure from the board to execute
3997 * the command.
3998 */
3999 if (boardp->adv_reqp == NULL) {
4000 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
4001 ASC_STATS(scp->device->host, adv_build_noreq);
4002 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004004 reqp = boardp->adv_reqp;
4005 boardp->adv_reqp = reqp->next_reqp;
4006 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004009 /*
4010 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
4011 */
4012 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004014 /*
4015 * Initialize the structure.
4016 */
4017 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004019 /*
4020 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
4021 */
4022 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004024 /*
4025 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
4026 */
4027 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004029 /*
4030 * Build the ADV_SCSI_REQ_Q request.
4031 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004033 /*
4034 * Set CDB length and copy it to the request structure.
4035 * For wide boards a CDB length maximum of 16 bytes
4036 * is supported.
4037 */
4038 if (scp->cmd_len > ADV_MAX_CDB_LEN) {
4039 ASC_PRINT3
4040 ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
4041 boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
4042 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004043 return ASC_ERROR;
4044 }
4045 scsiqp->cdb_len = scp->cmd_len;
4046 /* Copy first 12 CDB bytes to cdb[]. */
4047 for (i = 0; i < scp->cmd_len && i < 12; i++) {
4048 scsiqp->cdb[i] = scp->cmnd[i];
4049 }
4050 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
4051 for (; i < scp->cmd_len; i++) {
4052 scsiqp->cdb16[i - 12] = scp->cmnd[i];
4053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004055 scsiqp->target_id = scp->device->id;
4056 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004058 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4059 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004061 /*
4062 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
4063 * buffer command.
4064 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004066 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4067 scsiqp->vdata_addr = scp->request_buffer;
4068 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
4069
4070 if (scp->use_sg == 0) {
4071 /*
4072 * CDB request of single contiguous buffer.
4073 */
4074 reqp->sgblkp = NULL;
4075 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4076 if (scp->request_bufflen) {
4077 scsiqp->vdata_addr = scp->request_buffer;
4078 scp->SCp.dma_handle =
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004079 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004080 scp->request_bufflen,
4081 scp->sc_data_direction);
4082 } else {
4083 scsiqp->vdata_addr = NULL;
4084 scp->SCp.dma_handle = 0;
4085 }
4086 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
4087 scsiqp->sg_list_ptr = NULL;
4088 scsiqp->sg_real_addr = 0;
4089 ASC_STATS(scp->device->host, cont_cnt);
4090 ASC_STATS_ADD(scp->device->host, cont_xfer,
4091 ASC_CEILING(scp->request_bufflen, 512));
4092 } else {
4093 /*
4094 * CDB scatter-gather request list.
4095 */
4096 struct scatterlist *slp;
4097 int use_sg;
4098
4099 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004100 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4101 scp->sc_data_direction);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004102
4103 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004104 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
4105 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
4106 scp->device->host->sg_tablesize);
4107 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004108 scp->sc_data_direction);
4109 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004110
4111 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004112 * Free the 'adv_req_t' structure by adding it back
4113 * to the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004114 */
4115 reqp->next_reqp = boardp->adv_reqp;
4116 boardp->adv_reqp = reqp;
4117
4118 return ASC_ERROR;
4119 }
4120
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004121 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
4122 if (ret != ADV_SUCCESS) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004123 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004124 * Free the adv_req_t structure by adding it back to
4125 * the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004126 */
4127 reqp->next_reqp = boardp->adv_reqp;
4128 boardp->adv_reqp = reqp;
4129
4130 return ret;
4131 }
4132
4133 ASC_STATS(scp->device->host, sg_cnt);
4134 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
4135 }
4136
4137 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
4138 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
4139
4140 *adv_scsiqpp = scsiqp;
4141
4142 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143}
4144
4145/*
4146 * Build scatter-gather list for Adv Library (Wide Board).
4147 *
4148 * Additional ADV_SG_BLOCK structures will need to be allocated
4149 * if the total number of scatter-gather elements exceeds
4150 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
4151 * assumed to be physically contiguous.
4152 *
4153 * Return:
4154 * ADV_SUCCESS(1) - SG List successfully created
4155 * ADV_ERROR(-1) - SG List creation failed
4156 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004157static int
4158adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
4159 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004161 adv_sgblk_t *sgblkp;
4162 ADV_SCSI_REQ_Q *scsiqp;
4163 struct scatterlist *slp;
4164 int sg_elem_cnt;
4165 ADV_SG_BLOCK *sg_block, *prev_sg_block;
4166 ADV_PADDR sg_block_paddr;
4167 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004169 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
4170 slp = (struct scatterlist *)scp->request_buffer;
4171 sg_elem_cnt = use_sg;
4172 prev_sg_block = NULL;
4173 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004175 do {
4176 /*
4177 * Allocate a 'adv_sgblk_t' structure from the board free
4178 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
4179 * (15) scatter-gather elements.
4180 */
4181 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
4182 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
4183 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004185 /*
4186 * Allocation failed. Free 'adv_sgblk_t' structures already
4187 * allocated for the request.
4188 */
4189 while ((sgblkp = reqp->sgblkp) != NULL) {
4190 /* Remove 'sgblkp' from the request list. */
4191 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004193 /* Add 'sgblkp' to the board free list. */
4194 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4195 boardp->adv_sgblkp = sgblkp;
4196 }
4197 return ASC_BUSY;
4198 } else {
4199 /* Complete 'adv_sgblk_t' board allocation. */
4200 boardp->adv_sgblkp = sgblkp->next_sgblkp;
4201 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004203 /*
4204 * Get 8 byte aligned virtual and physical addresses for
4205 * the allocated ADV_SG_BLOCK structure.
4206 */
4207 sg_block =
4208 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
4209 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004211 /*
4212 * Check if this is the first 'adv_sgblk_t' for the request.
4213 */
4214 if (reqp->sgblkp == NULL) {
4215 /* Request's first scatter-gather block. */
4216 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004218 /*
4219 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
4220 * address pointers.
4221 */
4222 scsiqp->sg_list_ptr = sg_block;
4223 scsiqp->sg_real_addr =
4224 cpu_to_le32(sg_block_paddr);
4225 } else {
4226 /* Request's second or later scatter-gather block. */
4227 sgblkp->next_sgblkp = reqp->sgblkp;
4228 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004230 /*
4231 * Point the previous ADV_SG_BLOCK structure to
4232 * the newly allocated ADV_SG_BLOCK structure.
4233 */
4234 ASC_ASSERT(prev_sg_block != NULL);
4235 prev_sg_block->sg_ptr =
4236 cpu_to_le32(sg_block_paddr);
4237 }
4238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004240 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
4241 sg_block->sg_list[i].sg_addr =
4242 cpu_to_le32(sg_dma_address(slp));
4243 sg_block->sg_list[i].sg_count =
4244 cpu_to_le32(sg_dma_len(slp));
4245 ASC_STATS_ADD(scp->device->host, sg_xfer,
4246 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004248 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
4249 sg_block->sg_cnt = i + 1;
4250 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
4251 return ADV_SUCCESS;
4252 }
4253 slp++;
4254 }
4255 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
4256 prev_sg_block = sg_block;
4257 }
4258 while (1);
4259 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
4262/*
4263 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
4264 *
4265 * Interrupt callback function for the Narrow SCSI Asc Library.
4266 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004267static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004269 asc_board_t *boardp;
4270 struct scsi_cmnd *scp;
4271 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004273 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
4274 (ulong)asc_dvc_varp, (ulong)qdonep);
4275 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004277 /*
4278 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4279 * command that has been completed.
4280 */
4281 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
4282 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004284 if (scp == NULL) {
4285 ASC_PRINT("asc_isr_callback: scp is NULL\n");
4286 return;
4287 }
4288 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004290 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004291 ASC_STATS(shost, callback);
4292 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004294 boardp = ASC_BOARDP(shost);
4295 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004297 /*
4298 * 'qdonep' contains the command's ending status.
4299 */
4300 switch (qdonep->d3.done_stat) {
4301 case QD_NO_ERROR:
4302 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
4303 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004305 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004306 * Check for an underrun condition.
4307 *
4308 * If there was no error and an underrun condition, then
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004309 * return the number of underrun bytes.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004310 */
4311 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
4312 qdonep->remain_bytes <= scp->request_bufflen) {
4313 ASC_DBG1(1,
4314 "asc_isr_callback: underrun condition %u bytes\n",
4315 (unsigned)qdonep->remain_bytes);
4316 scp->resid = qdonep->remain_bytes;
4317 }
4318 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004320 case QD_WITH_ERROR:
4321 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
4322 switch (qdonep->d3.host_stat) {
4323 case QHSTA_NO_ERROR:
4324 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
4325 ASC_DBG(2,
4326 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4327 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4328 sizeof(scp->sense_buffer));
4329 /*
4330 * Note: The 'status_byte()' macro used by target drivers
4331 * defined in scsi.h shifts the status byte returned by
4332 * host drivers right by 1 bit. This is why target drivers
4333 * also use right shifted status byte definitions. For
4334 * instance target drivers use CHECK_CONDITION, defined to
4335 * 0x1, instead of the SCSI defined check condition value
4336 * of 0x2. Host drivers are supposed to return the status
4337 * byte as it is defined by SCSI.
4338 */
4339 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4340 STATUS_BYTE(qdonep->d3.scsi_stat);
4341 } else {
4342 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
4343 }
4344 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004346 default:
4347 /* QHSTA error occurred */
4348 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
4349 qdonep->d3.host_stat);
4350 scp->result = HOST_BYTE(DID_BAD_TARGET);
4351 break;
4352 }
4353 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004355 case QD_ABORTED_BY_HOST:
4356 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
4357 scp->result =
4358 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
4359 scsi_msg) |
4360 STATUS_BYTE(qdonep->d3.scsi_stat);
4361 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004363 default:
4364 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
4365 qdonep->d3.done_stat);
4366 scp->result =
4367 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
4368 scsi_msg) |
4369 STATUS_BYTE(qdonep->d3.scsi_stat);
4370 break;
4371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004373 /*
4374 * If the 'init_tidmask' bit isn't already set for the target and the
4375 * current request finished normally, then set the bit for the target
4376 * to indicate that a device is present.
4377 */
4378 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4379 qdonep->d3.done_stat == QD_NO_ERROR &&
4380 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
4381 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004384 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004386 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387}
4388
4389/*
4390 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
4391 *
4392 * Callback function for the Wide SCSI Adv Library.
4393 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004394static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004396 asc_board_t *boardp;
4397 adv_req_t *reqp;
4398 adv_sgblk_t *sgblkp;
4399 struct scsi_cmnd *scp;
4400 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004401 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004403 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
4404 (ulong)adv_dvc_varp, (ulong)scsiqp);
4405 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004407 /*
4408 * Get the adv_req_t structure for the command that has been
4409 * completed. The adv_req_t structure actually contains the
4410 * completed ADV_SCSI_REQ_Q structure.
4411 */
4412 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
4413 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
4414 if (reqp == NULL) {
4415 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
4416 return;
4417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004419 /*
4420 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4421 * command that has been completed.
4422 *
4423 * Note: The adv_req_t request structure and adv_sgblk_t structure,
4424 * if any, are dropped, because a board structure pointer can not be
4425 * determined.
4426 */
4427 scp = reqp->cmndp;
4428 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
4429 if (scp == NULL) {
4430 ASC_PRINT
4431 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
4432 return;
4433 }
4434 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004436 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004437 ASC_STATS(shost, callback);
4438 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004440 boardp = ASC_BOARDP(shost);
4441 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004443 /*
4444 * 'done_status' contains the command's ending status.
4445 */
4446 switch (scsiqp->done_status) {
4447 case QD_NO_ERROR:
4448 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
4449 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004451 /*
4452 * Check for an underrun condition.
4453 *
4454 * If there was no error and an underrun condition, then
4455 * then return the number of underrun bytes.
4456 */
4457 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
4458 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
4459 resid_cnt <= scp->request_bufflen) {
4460 ASC_DBG1(1,
4461 "adv_isr_callback: underrun condition %lu bytes\n",
4462 (ulong)resid_cnt);
4463 scp->resid = resid_cnt;
4464 }
4465 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004467 case QD_WITH_ERROR:
4468 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
4469 switch (scsiqp->host_status) {
4470 case QHSTA_NO_ERROR:
4471 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
4472 ASC_DBG(2,
4473 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4474 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4475 sizeof(scp->sense_buffer));
4476 /*
4477 * Note: The 'status_byte()' macro used by target drivers
4478 * defined in scsi.h shifts the status byte returned by
4479 * host drivers right by 1 bit. This is why target drivers
4480 * also use right shifted status byte definitions. For
4481 * instance target drivers use CHECK_CONDITION, defined to
4482 * 0x1, instead of the SCSI defined check condition value
4483 * of 0x2. Host drivers are supposed to return the status
4484 * byte as it is defined by SCSI.
4485 */
4486 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4487 STATUS_BYTE(scsiqp->scsi_status);
4488 } else {
4489 scp->result = STATUS_BYTE(scsiqp->scsi_status);
4490 }
4491 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004493 default:
4494 /* Some other QHSTA error occurred. */
4495 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
4496 scsiqp->host_status);
4497 scp->result = HOST_BYTE(DID_BAD_TARGET);
4498 break;
4499 }
4500 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004502 case QD_ABORTED_BY_HOST:
4503 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
4504 scp->result =
4505 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
4506 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004508 default:
4509 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
4510 scsiqp->done_status);
4511 scp->result =
4512 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
4513 break;
4514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004516 /*
4517 * If the 'init_tidmask' bit isn't already set for the target and the
4518 * current request finished normally, then set the bit for the target
4519 * to indicate that a device is present.
4520 */
4521 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4522 scsiqp->done_status == QD_NO_ERROR &&
4523 scsiqp->host_status == QHSTA_NO_ERROR) {
4524 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004527 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004529 /*
4530 * Free all 'adv_sgblk_t' structures allocated for the request.
4531 */
4532 while ((sgblkp = reqp->sgblkp) != NULL) {
4533 /* Remove 'sgblkp' from the request list. */
4534 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004536 /* Add 'sgblkp' to the board free list. */
4537 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4538 boardp->adv_sgblkp = sgblkp;
4539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004541 /*
4542 * Free the adv_req_t structure used with the command by adding
4543 * it back to the board free list.
4544 */
4545 reqp->next_reqp = boardp->adv_reqp;
4546 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004548 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004550 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551}
4552
4553/*
4554 * adv_async_callback() - Adv Library asynchronous event callback function.
4555 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004556static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004558 switch (code) {
4559 case ADV_ASYNC_SCSI_BUS_RESET_DET:
4560 /*
4561 * The firmware detected a SCSI Bus reset.
4562 */
4563 ASC_DBG(0,
4564 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
4565 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004567 case ADV_ASYNC_RDMA_FAILURE:
4568 /*
4569 * Handle RDMA failure by resetting the SCSI Bus and
4570 * possibly the chip if it is unresponsive. Log the error
4571 * with a unique code.
4572 */
4573 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
4574 AdvResetChipAndSB(adv_dvc_varp);
4575 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004577 case ADV_HOST_SCSI_BUS_RESET:
4578 /*
4579 * Host generated SCSI bus reset occurred.
4580 */
4581 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
4582 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004584 default:
4585 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
4586 break;
4587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588}
4589
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590#ifdef CONFIG_PROC_FS
4591/*
4592 * asc_prt_board_devices()
4593 *
4594 * Print driver information for devices attached to the board.
4595 *
4596 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4597 * cf. asc_prt_line().
4598 *
4599 * Return the number of characters copied into 'cp'. No more than
4600 * 'cplen' characters will be copied to 'cp'.
4601 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004602static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004604 asc_board_t *boardp;
4605 int leftlen;
4606 int totlen;
4607 int len;
4608 int chip_scsi_id;
4609 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004611 boardp = ASC_BOARDP(shost);
4612 leftlen = cplen;
4613 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004615 len = asc_prt_line(cp, leftlen,
4616 "\nDevice Information for AdvanSys SCSI Host %d:\n",
4617 shost->host_no);
4618 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004620 if (ASC_NARROW_BOARD(boardp)) {
4621 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
4622 } else {
4623 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
4624 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004626 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
4627 ASC_PRT_NEXT();
4628 for (i = 0; i <= ADV_MAX_TID; i++) {
4629 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
4630 len = asc_prt_line(cp, leftlen, " %X,", i);
4631 ASC_PRT_NEXT();
4632 }
4633 }
4634 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
4635 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004637 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638}
4639
4640/*
4641 * Display Wide Board BIOS Information.
4642 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004643static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004645 asc_board_t *boardp;
4646 int leftlen;
4647 int totlen;
4648 int len;
4649 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004651 boardp = ASC_BOARDP(shost);
4652 leftlen = cplen;
4653 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004655 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
4656 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004658 /*
4659 * If the BIOS saved a valid signature, then fill in
4660 * the BIOS code segment base address.
4661 */
4662 if (boardp->bios_signature != 0x55AA) {
4663 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
4664 ASC_PRT_NEXT();
4665 len = asc_prt_line(cp, leftlen,
4666 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
4667 ASC_PRT_NEXT();
4668 len = asc_prt_line(cp, leftlen,
4669 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
4670 ASC_PRT_NEXT();
4671 } else {
4672 major = (boardp->bios_version >> 12) & 0xF;
4673 minor = (boardp->bios_version >> 8) & 0xF;
4674 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004676 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
4677 major, minor,
4678 letter >= 26 ? '?' : letter + 'A');
4679 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004680
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004681 /*
4682 * Current available ROM BIOS release is 3.1I for UW
4683 * and 3.2I for U2W. This code doesn't differentiate
4684 * UW and U2W boards.
4685 */
4686 if (major < 3 || (major <= 3 && minor < 1) ||
4687 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
4688 len = asc_prt_line(cp, leftlen,
4689 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
4690 ASC_PRT_NEXT();
4691 len = asc_prt_line(cp, leftlen,
4692 "ftp://ftp.connectcom.net/pub\n");
4693 ASC_PRT_NEXT();
4694 }
4695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004697 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698}
4699
4700/*
4701 * Add serial number to information bar if signature AAh
4702 * is found in at bit 15-9 (7 bits) of word 1.
4703 *
4704 * Serial Number consists fo 12 alpha-numeric digits.
4705 *
4706 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
4707 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
4708 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
4709 * 5 - Product revision (A-J) Word0: " "
4710 *
4711 * Signature Word1: 15-9 (7 bits)
4712 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
4713 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
4714 *
4715 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
4716 *
4717 * Note 1: Only production cards will have a serial number.
4718 *
4719 * Note 2: Signature is most significant 7 bits (0xFE).
4720 *
4721 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
4722 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004723static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004725 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004727 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
4728 return ASC_FALSE;
4729 } else {
4730 /*
4731 * First word - 6 digits.
4732 */
4733 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004735 /* Product type - 1st digit. */
4736 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
4737 /* Product type is P=Prototype */
4738 *cp += 0x8;
4739 }
4740 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004742 /* Manufacturing location - 2nd digit. */
4743 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004745 /* Product ID - 3rd, 4th digits. */
4746 num = w & 0x3FF;
4747 *cp++ = '0' + (num / 100);
4748 num %= 100;
4749 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004751 /* Product revision - 5th digit. */
4752 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004754 /*
4755 * Second word
4756 */
4757 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004759 /*
4760 * Year - 6th digit.
4761 *
4762 * If bit 15 of third word is set, then the
4763 * last digit of the year is greater than 7.
4764 */
4765 if (serialnum[2] & 0x8000) {
4766 *cp++ = '8' + ((w & 0x1C0) >> 6);
4767 } else {
4768 *cp++ = '0' + ((w & 0x1C0) >> 6);
4769 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004771 /* Week of year - 7th, 8th digits. */
4772 num = w & 0x003F;
4773 *cp++ = '0' + num / 10;
4774 num %= 10;
4775 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004777 /*
4778 * Third word
4779 */
4780 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004782 /* Serial number - 9th digit. */
4783 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004785 /* 10th, 11th, 12th digits. */
4786 num = w % 1000;
4787 *cp++ = '0' + num / 100;
4788 num %= 100;
4789 *cp++ = '0' + num / 10;
4790 num %= 10;
4791 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004793 *cp = '\0'; /* Null Terminate the string. */
4794 return ASC_TRUE;
4795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796}
4797
4798/*
4799 * asc_prt_asc_board_eeprom()
4800 *
4801 * Print board EEPROM configuration.
4802 *
4803 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4804 * cf. asc_prt_line().
4805 *
4806 * Return the number of characters copied into 'cp'. No more than
4807 * 'cplen' characters will be copied to 'cp'.
4808 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004809static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004810{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004811 asc_board_t *boardp;
4812 ASC_DVC_VAR *asc_dvc_varp;
4813 int leftlen;
4814 int totlen;
4815 int len;
4816 ASCEEP_CONFIG *ep;
4817 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004819 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004821 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004823 boardp = ASC_BOARDP(shost);
4824 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4825 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004827 leftlen = cplen;
4828 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004830 len = asc_prt_line(cp, leftlen,
4831 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4832 shost->host_no);
4833 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004835 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
4836 == ASC_TRUE) {
4837 len =
4838 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4839 serialstr);
4840 ASC_PRT_NEXT();
4841 } else {
4842 if (ep->adapter_info[5] == 0xBB) {
4843 len = asc_prt_line(cp, leftlen,
4844 " Default Settings Used for EEPROM-less Adapter.\n");
4845 ASC_PRT_NEXT();
4846 } else {
4847 len = asc_prt_line(cp, leftlen,
4848 " Serial Number Signature Not Present.\n");
4849 ASC_PRT_NEXT();
4850 }
4851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004853 len = asc_prt_line(cp, leftlen,
4854 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4855 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
4856 ep->max_tag_qng);
4857 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004859 len = asc_prt_line(cp, leftlen,
4860 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
4861 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004863 len = asc_prt_line(cp, leftlen, " Target ID: ");
4864 ASC_PRT_NEXT();
4865 for (i = 0; i <= ASC_MAX_TID; i++) {
4866 len = asc_prt_line(cp, leftlen, " %d", i);
4867 ASC_PRT_NEXT();
4868 }
4869 len = asc_prt_line(cp, leftlen, "\n");
4870 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004872 len = asc_prt_line(cp, leftlen, " Disconnects: ");
4873 ASC_PRT_NEXT();
4874 for (i = 0; i <= ASC_MAX_TID; i++) {
4875 len = asc_prt_line(cp, leftlen, " %c",
4876 (ep->
4877 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4878 'N');
4879 ASC_PRT_NEXT();
4880 }
4881 len = asc_prt_line(cp, leftlen, "\n");
4882 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004884 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
4885 ASC_PRT_NEXT();
4886 for (i = 0; i <= ASC_MAX_TID; i++) {
4887 len = asc_prt_line(cp, leftlen, " %c",
4888 (ep->
4889 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4890 'N');
4891 ASC_PRT_NEXT();
4892 }
4893 len = asc_prt_line(cp, leftlen, "\n");
4894 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004896 len = asc_prt_line(cp, leftlen, " Start Motor: ");
4897 ASC_PRT_NEXT();
4898 for (i = 0; i <= ASC_MAX_TID; i++) {
4899 len = asc_prt_line(cp, leftlen, " %c",
4900 (ep->
4901 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4902 'N');
4903 ASC_PRT_NEXT();
4904 }
4905 len = asc_prt_line(cp, leftlen, "\n");
4906 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004908 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
4909 ASC_PRT_NEXT();
4910 for (i = 0; i <= ASC_MAX_TID; i++) {
4911 len = asc_prt_line(cp, leftlen, " %c",
4912 (ep->
4913 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4914 'N');
4915 ASC_PRT_NEXT();
4916 }
4917 len = asc_prt_line(cp, leftlen, "\n");
4918 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919
4920#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004921 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4922 len = asc_prt_line(cp, leftlen,
4923 " Host ISA DMA speed: %d MB/S\n",
4924 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
4925 ASC_PRT_NEXT();
4926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927#endif /* CONFIG_ISA */
4928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004929 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930}
4931
4932/*
4933 * asc_prt_adv_board_eeprom()
4934 *
4935 * Print board EEPROM configuration.
4936 *
4937 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4938 * cf. asc_prt_line().
4939 *
4940 * Return the number of characters copied into 'cp'. No more than
4941 * 'cplen' characters will be copied to 'cp'.
4942 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004943static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004944{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004945 asc_board_t *boardp;
4946 ADV_DVC_VAR *adv_dvc_varp;
4947 int leftlen;
4948 int totlen;
4949 int len;
4950 int i;
4951 char *termstr;
4952 uchar serialstr[13];
4953 ADVEEP_3550_CONFIG *ep_3550 = NULL;
4954 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
4955 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
4956 ushort word;
4957 ushort *wordp;
4958 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004960 boardp = ASC_BOARDP(shost);
4961 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4962 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4963 ep_3550 = &boardp->eep_config.adv_3550_eep;
4964 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4965 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
4966 } else {
4967 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
4968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004970 leftlen = cplen;
4971 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004973 len = asc_prt_line(cp, leftlen,
4974 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4975 shost->host_no);
4976 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004978 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4979 wordp = &ep_3550->serial_number_word1;
4980 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4981 wordp = &ep_38C0800->serial_number_word1;
4982 } else {
4983 wordp = &ep_38C1600->serial_number_word1;
4984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004986 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
4987 len =
4988 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4989 serialstr);
4990 ASC_PRT_NEXT();
4991 } else {
4992 len = asc_prt_line(cp, leftlen,
4993 " Serial Number Signature Not Present.\n");
4994 ASC_PRT_NEXT();
4995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004997 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4998 len = asc_prt_line(cp, leftlen,
4999 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5000 ep_3550->adapter_scsi_id,
5001 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
5002 ASC_PRT_NEXT();
5003 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5004 len = asc_prt_line(cp, leftlen,
5005 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5006 ep_38C0800->adapter_scsi_id,
5007 ep_38C0800->max_host_qng,
5008 ep_38C0800->max_dvc_qng);
5009 ASC_PRT_NEXT();
5010 } else {
5011 len = asc_prt_line(cp, leftlen,
5012 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5013 ep_38C1600->adapter_scsi_id,
5014 ep_38C1600->max_host_qng,
5015 ep_38C1600->max_dvc_qng);
5016 ASC_PRT_NEXT();
5017 }
5018 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5019 word = ep_3550->termination;
5020 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5021 word = ep_38C0800->termination_lvd;
5022 } else {
5023 word = ep_38C1600->termination_lvd;
5024 }
5025 switch (word) {
5026 case 1:
5027 termstr = "Low Off/High Off";
5028 break;
5029 case 2:
5030 termstr = "Low Off/High On";
5031 break;
5032 case 3:
5033 termstr = "Low On/High On";
5034 break;
5035 default:
5036 case 0:
5037 termstr = "Automatic";
5038 break;
5039 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005041 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5042 len = asc_prt_line(cp, leftlen,
5043 " termination: %u (%s), bios_ctrl: 0x%x\n",
5044 ep_3550->termination, termstr,
5045 ep_3550->bios_ctrl);
5046 ASC_PRT_NEXT();
5047 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5048 len = asc_prt_line(cp, leftlen,
5049 " termination: %u (%s), bios_ctrl: 0x%x\n",
5050 ep_38C0800->termination_lvd, termstr,
5051 ep_38C0800->bios_ctrl);
5052 ASC_PRT_NEXT();
5053 } else {
5054 len = asc_prt_line(cp, leftlen,
5055 " termination: %u (%s), bios_ctrl: 0x%x\n",
5056 ep_38C1600->termination_lvd, termstr,
5057 ep_38C1600->bios_ctrl);
5058 ASC_PRT_NEXT();
5059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005061 len = asc_prt_line(cp, leftlen, " Target ID: ");
5062 ASC_PRT_NEXT();
5063 for (i = 0; i <= ADV_MAX_TID; i++) {
5064 len = asc_prt_line(cp, leftlen, " %X", i);
5065 ASC_PRT_NEXT();
5066 }
5067 len = asc_prt_line(cp, leftlen, "\n");
5068 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005070 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5071 word = ep_3550->disc_enable;
5072 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5073 word = ep_38C0800->disc_enable;
5074 } else {
5075 word = ep_38C1600->disc_enable;
5076 }
5077 len = asc_prt_line(cp, leftlen, " Disconnects: ");
5078 ASC_PRT_NEXT();
5079 for (i = 0; i <= ADV_MAX_TID; i++) {
5080 len = asc_prt_line(cp, leftlen, " %c",
5081 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5082 ASC_PRT_NEXT();
5083 }
5084 len = asc_prt_line(cp, leftlen, "\n");
5085 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005087 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5088 word = ep_3550->tagqng_able;
5089 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5090 word = ep_38C0800->tagqng_able;
5091 } else {
5092 word = ep_38C1600->tagqng_able;
5093 }
5094 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
5095 ASC_PRT_NEXT();
5096 for (i = 0; i <= ADV_MAX_TID; i++) {
5097 len = asc_prt_line(cp, leftlen, " %c",
5098 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5099 ASC_PRT_NEXT();
5100 }
5101 len = asc_prt_line(cp, leftlen, "\n");
5102 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005104 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5105 word = ep_3550->start_motor;
5106 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5107 word = ep_38C0800->start_motor;
5108 } else {
5109 word = ep_38C1600->start_motor;
5110 }
5111 len = asc_prt_line(cp, leftlen, " Start Motor: ");
5112 ASC_PRT_NEXT();
5113 for (i = 0; i <= ADV_MAX_TID; i++) {
5114 len = asc_prt_line(cp, leftlen, " %c",
5115 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5116 ASC_PRT_NEXT();
5117 }
5118 len = asc_prt_line(cp, leftlen, "\n");
5119 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005121 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5122 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5123 ASC_PRT_NEXT();
5124 for (i = 0; i <= ADV_MAX_TID; i++) {
5125 len = asc_prt_line(cp, leftlen, " %c",
5126 (ep_3550->
5127 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
5128 'Y' : 'N');
5129 ASC_PRT_NEXT();
5130 }
5131 len = asc_prt_line(cp, leftlen, "\n");
5132 ASC_PRT_NEXT();
5133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005135 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5136 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
5137 ASC_PRT_NEXT();
5138 for (i = 0; i <= ADV_MAX_TID; i++) {
5139 len = asc_prt_line(cp, leftlen, " %c",
5140 (ep_3550->
5141 ultra_able & ADV_TID_TO_TIDMASK(i))
5142 ? 'Y' : 'N');
5143 ASC_PRT_NEXT();
5144 }
5145 len = asc_prt_line(cp, leftlen, "\n");
5146 ASC_PRT_NEXT();
5147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005149 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5150 word = ep_3550->wdtr_able;
5151 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5152 word = ep_38C0800->wdtr_able;
5153 } else {
5154 word = ep_38C1600->wdtr_able;
5155 }
5156 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
5157 ASC_PRT_NEXT();
5158 for (i = 0; i <= ADV_MAX_TID; i++) {
5159 len = asc_prt_line(cp, leftlen, " %c",
5160 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5161 ASC_PRT_NEXT();
5162 }
5163 len = asc_prt_line(cp, leftlen, "\n");
5164 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005165
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005166 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
5167 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
5168 len = asc_prt_line(cp, leftlen,
5169 " Synchronous Transfer Speed (Mhz):\n ");
5170 ASC_PRT_NEXT();
5171 for (i = 0; i <= ADV_MAX_TID; i++) {
5172 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005174 if (i == 0) {
5175 sdtr_speed = adv_dvc_varp->sdtr_speed1;
5176 } else if (i == 4) {
5177 sdtr_speed = adv_dvc_varp->sdtr_speed2;
5178 } else if (i == 8) {
5179 sdtr_speed = adv_dvc_varp->sdtr_speed3;
5180 } else if (i == 12) {
5181 sdtr_speed = adv_dvc_varp->sdtr_speed4;
5182 }
5183 switch (sdtr_speed & ADV_MAX_TID) {
5184 case 0:
5185 speed_str = "Off";
5186 break;
5187 case 1:
5188 speed_str = " 5";
5189 break;
5190 case 2:
5191 speed_str = " 10";
5192 break;
5193 case 3:
5194 speed_str = " 20";
5195 break;
5196 case 4:
5197 speed_str = " 40";
5198 break;
5199 case 5:
5200 speed_str = " 80";
5201 break;
5202 default:
5203 speed_str = "Unk";
5204 break;
5205 }
5206 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
5207 ASC_PRT_NEXT();
5208 if (i == 7) {
5209 len = asc_prt_line(cp, leftlen, "\n ");
5210 ASC_PRT_NEXT();
5211 }
5212 sdtr_speed >>= 4;
5213 }
5214 len = asc_prt_line(cp, leftlen, "\n");
5215 ASC_PRT_NEXT();
5216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005218 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219}
5220
5221/*
5222 * asc_prt_driver_conf()
5223 *
5224 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5225 * cf. asc_prt_line().
5226 *
5227 * Return the number of characters copied into 'cp'. No more than
5228 * 'cplen' characters will be copied to 'cp'.
5229 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005230static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005232 asc_board_t *boardp;
5233 int leftlen;
5234 int totlen;
5235 int len;
5236 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005238 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005240 leftlen = cplen;
5241 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005243 len = asc_prt_line(cp, leftlen,
5244 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
5245 shost->host_no);
5246 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005248 len = asc_prt_line(cp, leftlen,
5249 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
5250 shost->host_busy, shost->last_reset, shost->max_id,
5251 shost->max_lun, shost->max_channel);
5252 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005254 len = asc_prt_line(cp, leftlen,
5255 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
5256 shost->unique_id, shost->can_queue, shost->this_id,
5257 shost->sg_tablesize, shost->cmd_per_lun);
5258 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005260 len = asc_prt_line(cp, leftlen,
5261 " unchecked_isa_dma %d, use_clustering %d\n",
5262 shost->unchecked_isa_dma, shost->use_clustering);
5263 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005265 len = asc_prt_line(cp, leftlen,
5266 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
5267 boardp->flags, boardp->last_reset, jiffies,
5268 boardp->asc_n_io_port);
5269 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04005271 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005272 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005274 if (ASC_NARROW_BOARD(boardp)) {
5275 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
5276 } else {
5277 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
5278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005280 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281}
5282
5283/*
5284 * asc_prt_asc_board_info()
5285 *
5286 * Print dynamic board configuration information.
5287 *
5288 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5289 * cf. asc_prt_line().
5290 *
5291 * Return the number of characters copied into 'cp'. No more than
5292 * 'cplen' characters will be copied to 'cp'.
5293 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005294static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005296 asc_board_t *boardp;
5297 int chip_scsi_id;
5298 int leftlen;
5299 int totlen;
5300 int len;
5301 ASC_DVC_VAR *v;
5302 ASC_DVC_CFG *c;
5303 int i;
5304 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005306 boardp = ASC_BOARDP(shost);
5307 v = &boardp->dvc_var.asc_dvc_var;
5308 c = &boardp->dvc_cfg.asc_dvc_cfg;
5309 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005310
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005311 leftlen = cplen;
5312 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005314 len = asc_prt_line(cp, leftlen,
5315 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5316 shost->host_no);
5317 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005319 len = asc_prt_line(cp, leftlen,
5320 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
5321 c->chip_version, c->lib_version, c->lib_serial_no,
5322 c->mcode_date);
5323 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005325 len = asc_prt_line(cp, leftlen,
5326 " mcode_version 0x%x, err_code %u\n",
5327 c->mcode_version, v->err_code);
5328 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005330 /* Current number of commands waiting for the host. */
5331 len = asc_prt_line(cp, leftlen,
5332 " Total Command Pending: %d\n", v->cur_total_qng);
5333 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005335 len = asc_prt_line(cp, leftlen, " Command Queuing:");
5336 ASC_PRT_NEXT();
5337 for (i = 0; i <= ASC_MAX_TID; i++) {
5338 if ((chip_scsi_id == i) ||
5339 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5340 continue;
5341 }
5342 len = asc_prt_line(cp, leftlen, " %X:%c",
5343 i,
5344 (v->
5345 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
5346 'Y' : 'N');
5347 ASC_PRT_NEXT();
5348 }
5349 len = asc_prt_line(cp, leftlen, "\n");
5350 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005351
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005352 /* Current number of commands waiting for a device. */
5353 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
5354 ASC_PRT_NEXT();
5355 for (i = 0; i <= ASC_MAX_TID; i++) {
5356 if ((chip_scsi_id == i) ||
5357 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5358 continue;
5359 }
5360 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
5361 ASC_PRT_NEXT();
5362 }
5363 len = asc_prt_line(cp, leftlen, "\n");
5364 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005366 /* Current limit on number of commands that can be sent to a device. */
5367 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
5368 ASC_PRT_NEXT();
5369 for (i = 0; i <= ASC_MAX_TID; i++) {
5370 if ((chip_scsi_id == i) ||
5371 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5372 continue;
5373 }
5374 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
5375 ASC_PRT_NEXT();
5376 }
5377 len = asc_prt_line(cp, leftlen, "\n");
5378 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005380 /* Indicate whether the device has returned queue full status. */
5381 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
5382 ASC_PRT_NEXT();
5383 for (i = 0; i <= ASC_MAX_TID; i++) {
5384 if ((chip_scsi_id == i) ||
5385 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5386 continue;
5387 }
5388 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
5389 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
5390 i, boardp->queue_full_cnt[i]);
5391 } else {
5392 len = asc_prt_line(cp, leftlen, " %X:N", i);
5393 }
5394 ASC_PRT_NEXT();
5395 }
5396 len = asc_prt_line(cp, leftlen, "\n");
5397 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005399 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5400 ASC_PRT_NEXT();
5401 for (i = 0; i <= ASC_MAX_TID; i++) {
5402 if ((chip_scsi_id == i) ||
5403 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5404 continue;
5405 }
5406 len = asc_prt_line(cp, leftlen, " %X:%c",
5407 i,
5408 (v->
5409 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5410 'N');
5411 ASC_PRT_NEXT();
5412 }
5413 len = asc_prt_line(cp, leftlen, "\n");
5414 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005416 for (i = 0; i <= ASC_MAX_TID; i++) {
5417 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005419 if ((chip_scsi_id == i) ||
5420 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5421 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
5422 continue;
5423 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005425 len = asc_prt_line(cp, leftlen, " %X:", i);
5426 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005428 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
5429 len = asc_prt_line(cp, leftlen, " Asynchronous");
5430 ASC_PRT_NEXT();
5431 } else {
5432 syn_period_ix =
5433 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
5434 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005436 len = asc_prt_line(cp, leftlen,
5437 " Transfer Period Factor: %d (%d.%d Mhz),",
5438 v->sdtr_period_tbl[syn_period_ix],
5439 250 /
5440 v->sdtr_period_tbl[syn_period_ix],
5441 ASC_TENTHS(250,
5442 v->
5443 sdtr_period_tbl
5444 [syn_period_ix]));
5445 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005447 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5448 boardp->
5449 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
5450 ASC_PRT_NEXT();
5451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005453 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5454 len = asc_prt_line(cp, leftlen, "*\n");
5455 renegotiate = 1;
5456 } else {
5457 len = asc_prt_line(cp, leftlen, "\n");
5458 }
5459 ASC_PRT_NEXT();
5460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005462 if (renegotiate) {
5463 len = asc_prt_line(cp, leftlen,
5464 " * = Re-negotiation pending before next command.\n");
5465 ASC_PRT_NEXT();
5466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005468 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469}
5470
5471/*
5472 * asc_prt_adv_board_info()
5473 *
5474 * Print dynamic board configuration information.
5475 *
5476 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5477 * cf. asc_prt_line().
5478 *
5479 * Return the number of characters copied into 'cp'. No more than
5480 * 'cplen' characters will be copied to 'cp'.
5481 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005482static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 asc_board_t *boardp;
5485 int leftlen;
5486 int totlen;
5487 int len;
5488 int i;
5489 ADV_DVC_VAR *v;
5490 ADV_DVC_CFG *c;
5491 AdvPortAddr iop_base;
5492 ushort chip_scsi_id;
5493 ushort lramword;
5494 uchar lrambyte;
5495 ushort tagqng_able;
5496 ushort sdtr_able, wdtr_able;
5497 ushort wdtr_done, sdtr_done;
5498 ushort period = 0;
5499 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005501 boardp = ASC_BOARDP(shost);
5502 v = &boardp->dvc_var.adv_dvc_var;
5503 c = &boardp->dvc_cfg.adv_dvc_cfg;
5504 iop_base = v->iop_base;
5505 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005507 leftlen = cplen;
5508 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005510 len = asc_prt_line(cp, leftlen,
5511 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5512 shost->host_no);
5513 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005515 len = asc_prt_line(cp, leftlen,
5516 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
5517 v->iop_base,
5518 AdvReadWordRegister(iop_base,
5519 IOPW_SCSI_CFG1) & CABLE_DETECT,
5520 v->err_code);
5521 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005523 len = asc_prt_line(cp, leftlen,
5524 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
5525 c->chip_version, c->lib_version, c->mcode_date,
5526 c->mcode_version);
5527 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005529 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
5530 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
5531 ASC_PRT_NEXT();
5532 for (i = 0; i <= ADV_MAX_TID; i++) {
5533 if ((chip_scsi_id == i) ||
5534 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5535 continue;
5536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005538 len = asc_prt_line(cp, leftlen, " %X:%c",
5539 i,
5540 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5541 'N');
5542 ASC_PRT_NEXT();
5543 }
5544 len = asc_prt_line(cp, leftlen, "\n");
5545 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005547 len = asc_prt_line(cp, leftlen, " Queue Limit:");
5548 ASC_PRT_NEXT();
5549 for (i = 0; i <= ADV_MAX_TID; i++) {
5550 if ((chip_scsi_id == i) ||
5551 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5552 continue;
5553 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005555 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
5556 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005558 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5559 ASC_PRT_NEXT();
5560 }
5561 len = asc_prt_line(cp, leftlen, "\n");
5562 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005564 len = asc_prt_line(cp, leftlen, " Command Pending:");
5565 ASC_PRT_NEXT();
5566 for (i = 0; i <= ADV_MAX_TID; i++) {
5567 if ((chip_scsi_id == i) ||
5568 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5569 continue;
5570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005571
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005572 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
5573 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005575 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5576 ASC_PRT_NEXT();
5577 }
5578 len = asc_prt_line(cp, leftlen, "\n");
5579 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005581 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
5582 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
5583 ASC_PRT_NEXT();
5584 for (i = 0; i <= ADV_MAX_TID; i++) {
5585 if ((chip_scsi_id == i) ||
5586 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5587 continue;
5588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005590 len = asc_prt_line(cp, leftlen, " %X:%c",
5591 i,
5592 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5593 'N');
5594 ASC_PRT_NEXT();
5595 }
5596 len = asc_prt_line(cp, leftlen, "\n");
5597 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005598
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005599 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
5600 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
5601 ASC_PRT_NEXT();
5602 for (i = 0; i <= ADV_MAX_TID; i++) {
5603 if ((chip_scsi_id == i) ||
5604 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5605 continue;
5606 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005608 AdvReadWordLram(iop_base,
5609 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5610 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005612 len = asc_prt_line(cp, leftlen, " %X:%d",
5613 i, (lramword & 0x8000) ? 16 : 8);
5614 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005616 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
5617 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5618 len = asc_prt_line(cp, leftlen, "*");
5619 ASC_PRT_NEXT();
5620 renegotiate = 1;
5621 }
5622 }
5623 len = asc_prt_line(cp, leftlen, "\n");
5624 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005626 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
5627 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
5628 ASC_PRT_NEXT();
5629 for (i = 0; i <= ADV_MAX_TID; i++) {
5630 if ((chip_scsi_id == i) ||
5631 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5632 continue;
5633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005635 len = asc_prt_line(cp, leftlen, " %X:%c",
5636 i,
5637 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5638 'N');
5639 ASC_PRT_NEXT();
5640 }
5641 len = asc_prt_line(cp, leftlen, "\n");
5642 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005643
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005644 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
5645 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005646
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005647 AdvReadWordLram(iop_base,
5648 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5649 lramword);
5650 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005652 if ((chip_scsi_id == i) ||
5653 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5654 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
5655 continue;
5656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005658 len = asc_prt_line(cp, leftlen, " %X:", i);
5659 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005661 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
5662 len = asc_prt_line(cp, leftlen, " Asynchronous");
5663 ASC_PRT_NEXT();
5664 } else {
5665 len =
5666 asc_prt_line(cp, leftlen,
5667 " Transfer Period Factor: ");
5668 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005670 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
5671 len =
5672 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
5673 ASC_PRT_NEXT();
5674 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
5675 len =
5676 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
5677 ASC_PRT_NEXT();
5678 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005680 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005682 if (period == 0) { /* Should never happen. */
5683 len =
5684 asc_prt_line(cp, leftlen,
5685 "%d (? Mhz), ");
5686 ASC_PRT_NEXT();
5687 } else {
5688 len = asc_prt_line(cp, leftlen,
5689 "%d (%d.%d Mhz),",
5690 period, 250 / period,
5691 ASC_TENTHS(250,
5692 period));
5693 ASC_PRT_NEXT();
5694 }
5695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005697 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5698 lramword & 0x1F);
5699 ASC_PRT_NEXT();
5700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005702 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5703 len = asc_prt_line(cp, leftlen, "*\n");
5704 renegotiate = 1;
5705 } else {
5706 len = asc_prt_line(cp, leftlen, "\n");
5707 }
5708 ASC_PRT_NEXT();
5709 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005711 if (renegotiate) {
5712 len = asc_prt_line(cp, leftlen,
5713 " * = Re-negotiation pending before next command.\n");
5714 ASC_PRT_NEXT();
5715 }
5716
5717 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718}
5719
5720/*
5721 * asc_proc_copy()
5722 *
5723 * Copy proc information to a read buffer taking into account the current
5724 * read offset in the file and the remaining space in the read buffer.
5725 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005726static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005727asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005728 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005730 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005732 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
5733 (unsigned)offset, (unsigned)advoffset, cplen);
5734 if (offset <= advoffset) {
5735 /* Read offset below current offset, copy everything. */
5736 cnt = min(cplen, leftlen);
5737 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5738 (ulong)curbuf, (ulong)cp, cnt);
5739 memcpy(curbuf, cp, cnt);
5740 } else if (offset < advoffset + cplen) {
5741 /* Read offset within current range, partial copy. */
5742 cnt = (advoffset + cplen) - offset;
5743 cp = (cp + cplen) - cnt;
5744 cnt = min(cnt, leftlen);
5745 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5746 (ulong)curbuf, (ulong)cp, cnt);
5747 memcpy(curbuf, cp, cnt);
5748 }
5749 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750}
5751
5752/*
5753 * asc_prt_line()
5754 *
5755 * If 'cp' is NULL print to the console, otherwise print to a buffer.
5756 *
5757 * Return 0 if printing to the console, otherwise return the number of
5758 * bytes written to the buffer.
5759 *
5760 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
5761 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
5762 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005763static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005765 va_list args;
5766 int ret;
5767 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005769 va_start(args, fmt);
5770 ret = vsprintf(s, fmt, args);
5771 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
5772 if (buf == NULL) {
5773 (void)printk(s);
5774 ret = 0;
5775 } else {
5776 ret = min(buflen, ret);
5777 memcpy(buf, s, ret);
5778 }
5779 va_end(args);
5780 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781}
5782#endif /* CONFIG_PROC_FS */
5783
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784/*
5785 * --- Functions Required by the Asc Library
5786 */
5787
5788/*
5789 * Delay for 'n' milliseconds. Don't use the 'jiffies'
5790 * global variable which is incremented once every 5 ms
5791 * from a timer interrupt, because this function may be
5792 * called when interrupts are disabled.
5793 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005794static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005795{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005796 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
5797 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798}
5799
5800/*
5801 * Currently and inline noop but leave as a placeholder.
5802 * Leave DvcEnterCritical() as a noop placeholder.
5803 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005804static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005806 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807}
5808
5809/*
5810 * Critical sections are all protected by the board spinlock.
5811 * Leave DvcLeaveCritical() as a noop placeholder.
5812 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005813static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005815 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005816}
5817
5818/*
5819 * void
5820 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5821 *
5822 * Calling/Exit State:
5823 * none
5824 *
5825 * Description:
5826 * Output an ASC_SCSI_Q structure to the chip
5827 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005828static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5830{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005831 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005833 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
5834 AscSetChipLramAddr(iop_base, s_addr);
5835 for (i = 0; i < 2 * words; i += 2) {
5836 if (i == 4 || i == 20) {
5837 continue;
5838 }
5839 outpw(iop_base + IOP_RAM_DATA,
5840 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
5841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842}
5843
5844/*
5845 * void
5846 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5847 *
5848 * Calling/Exit State:
5849 * none
5850 *
5851 * Description:
5852 * Input an ASC_QDONE_INFO structure from the chip
5853 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005854static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5856{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005857 int i;
5858 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005860 AscSetChipLramAddr(iop_base, s_addr);
5861 for (i = 0; i < 2 * words; i += 2) {
5862 if (i == 10) {
5863 continue;
5864 }
5865 word = inpw(iop_base + IOP_RAM_DATA);
5866 inbuf[i] = word & 0xff;
5867 inbuf[i + 1] = (word >> 8) & 0xff;
5868 }
5869 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870}
5871
5872/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873 * Return the BIOS address of the adapter at the specified
5874 * I/O port and with the specified bus type.
5875 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005876static unsigned short __devinit
5877AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005879 unsigned short cfg_lsw;
5880 unsigned short bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005882 /*
5883 * The PCI BIOS is re-located by the motherboard BIOS. Because
5884 * of this the driver can not determine where a PCI BIOS is
5885 * loaded and executes.
5886 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005887 if (bus_type & ASC_IS_PCI)
5888 return 0;
5889
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005891 if ((bus_type & ASC_IS_EISA) != 0) {
5892 cfg_lsw = AscGetEisaChipCfg(iop_base);
5893 cfg_lsw &= 0x000F;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005894 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
5895 return bios_addr;
5896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897#endif /* CONFIG_ISA */
5898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005899 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005901 /*
5902 * ISA PnP uses the top bit as the 32K BIOS flag
5903 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005904 if (bus_type == ASC_IS_ISAPNP)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005905 cfg_lsw &= 0x7FFF;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005906 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
5907 return bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908}
5909
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910/*
5911 * --- Functions Required by the Adv Library
5912 */
5913
5914/*
5915 * DvcGetPhyAddr()
5916 *
5917 * Return the physical address of 'vaddr' and set '*lenp' to the
5918 * number of physically contiguous bytes that follow 'vaddr'.
5919 * 'flag' indicates the type of structure whose physical address
5920 * is being translated.
5921 *
5922 * Note: Because Linux currently doesn't page the kernel and all
5923 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
5924 */
5925ADV_PADDR
5926DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005927 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005929 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005931 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005933 ASC_DBG4(4,
5934 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
5935 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
5936 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005938 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939}
5940
5941/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 * --- Tracing and Debugging Functions
5943 */
5944
5945#ifdef ADVANSYS_STATS
5946#ifdef CONFIG_PROC_FS
5947/*
5948 * asc_prt_board_stats()
5949 *
5950 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5951 * cf. asc_prt_line().
5952 *
5953 * Return the number of characters copied into 'cp'. No more than
5954 * 'cplen' characters will be copied to 'cp'.
5955 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005956static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005958 int leftlen;
5959 int totlen;
5960 int len;
5961 struct asc_stats *s;
5962 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005964 leftlen = cplen;
5965 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005967 boardp = ASC_BOARDP(shost);
5968 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005970 len = asc_prt_line(cp, leftlen,
5971 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
5972 shost->host_no);
5973 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005975 len = asc_prt_line(cp, leftlen,
5976 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
5977 s->queuecommand, s->reset, s->biosparam,
5978 s->interrupt);
5979 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005981 len = asc_prt_line(cp, leftlen,
5982 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
5983 s->callback, s->done, s->build_error,
5984 s->adv_build_noreq, s->adv_build_nosg);
5985 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005987 len = asc_prt_line(cp, leftlen,
5988 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
5989 s->exe_noerror, s->exe_busy, s->exe_error,
5990 s->exe_unknown);
5991 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005992
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005993 /*
5994 * Display data transfer statistics.
5995 */
5996 if (s->cont_cnt > 0) {
5997 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
5998 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006000 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
6001 s->cont_xfer / 2,
6002 ASC_TENTHS(s->cont_xfer, 2));
6003 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006005 /* Contiguous transfer average size */
6006 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
6007 (s->cont_xfer / 2) / s->cont_cnt,
6008 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
6009 ASC_PRT_NEXT();
6010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006012 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006014 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
6015 s->sg_cnt, s->sg_elem);
6016 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006018 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
6019 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
6020 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006022 /* Scatter gather transfer statistics */
6023 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
6024 s->sg_elem / s->sg_cnt,
6025 ASC_TENTHS(s->sg_elem, s->sg_cnt));
6026 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006028 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
6029 (s->sg_xfer / 2) / s->sg_elem,
6030 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
6031 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006033 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
6034 (s->sg_xfer / 2) / s->sg_cnt,
6035 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
6036 ASC_PRT_NEXT();
6037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006039 /*
6040 * Display request queuing statistics.
6041 */
6042 len = asc_prt_line(cp, leftlen,
6043 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
6044 HZ);
6045 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006047 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049#endif /* CONFIG_PROC_FS */
6050#endif /* ADVANSYS_STATS */
6051
6052#ifdef ADVANSYS_DEBUG
6053/*
6054 * asc_prt_scsi_host()
6055 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006056static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006058 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006059
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006060 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006062 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
6063 printk(" host_busy %u, host_no %d, last_reset %d,\n",
6064 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04006066 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
6067 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006069 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
6070 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006072 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
6073 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006075 if (ASC_NARROW_BOARD(boardp)) {
6076 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
6077 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
6078 } else {
6079 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
6080 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
6081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082}
6083
6084/*
6085 * asc_prt_scsi_cmnd()
6086 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006087static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006089 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006091 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
6092 (ulong)s->device->host, (ulong)s->device, s->device->id,
6093 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006095 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006097 printk("sc_data_direction %u, resid %d\n",
6098 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006100 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006102 printk(" serial_number 0x%x, retries %d, allowed %d\n",
6103 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006105 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006106
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006107 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
6108 s->scsi_done, s->done, s->host_scribble, s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006110 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111}
6112
6113/*
6114 * asc_prt_asc_dvc_var()
6115 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006116static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006118 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006120 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
6121 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122
Matthew Wilcox895d6b42007-07-26 11:57:06 -04006123 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
6124 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006125
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006126 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
6127 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
6128 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
6129 (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006131 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
6132 "%u,\n", (unsigned)h->queue_full_or_busy,
6133 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006135 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
6136 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
6137 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
6138 (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006140 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
6141 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
6142 (unsigned)h->init_state, (unsigned)h->no_scam,
6143 (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006145 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146}
6147
6148/*
6149 * asc_prt_asc_dvc_cfg()
6150 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006151static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006153 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006154
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006155 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
6156 h->can_tagged_qng, h->cmd_qng_enabled);
6157 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
6158 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006160 printk
6161 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
6162 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
6163 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006165 printk
6166 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
6167 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
6168 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006170 printk(" mcode_version %d, overrun_buf 0x%lx\n",
6171 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172}
6173
6174/*
6175 * asc_prt_asc_scsi_q()
6176 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006177static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006179 ASC_SG_HEAD *sgp;
6180 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006182 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006184 printk
6185 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
6186 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
6187 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006189 printk
6190 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6191 (ulong)le32_to_cpu(q->q1.data_addr),
6192 (ulong)le32_to_cpu(q->q1.data_cnt),
6193 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006195 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
6196 (ulong)q->cdbptr, q->q2.cdb_len,
6197 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006199 if (q->sg_head) {
6200 sgp = q->sg_head;
6201 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
6202 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
6203 sgp->queue_cnt);
6204 for (i = 0; i < sgp->entry_cnt; i++) {
6205 printk(" [%u]: addr 0x%lx, bytes %lu\n",
6206 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
6207 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
6208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006211}
6212
6213/*
6214 * asc_prt_asc_qdone_info()
6215 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006216static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006218 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
6219 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
6220 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
6221 q->d2.tag_code);
6222 printk
6223 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
6224 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225}
6226
6227/*
6228 * asc_prt_adv_dvc_var()
6229 *
6230 * Display an ADV_DVC_VAR structure.
6231 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006232static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006234 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006235
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006236 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
6237 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006239 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
6240 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
6241 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006243 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
6244 (unsigned)h->start_motor,
6245 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006247 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
6248 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
6249 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006251 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
6252 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006254 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
6255 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006256
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006257 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
6258 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259}
6260
6261/*
6262 * asc_prt_adv_dvc_cfg()
6263 *
6264 * Display an ADV_DVC_CFG structure.
6265 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006266static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006267{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006268 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006270 printk(" disc_enable 0x%x, termination 0x%x\n",
6271 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006273 printk(" chip_version 0x%x, mcode_date 0x%x\n",
6274 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006276 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
6277 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06006279 printk(" control_flag 0x%x\n", h->control_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006280}
6281
6282/*
6283 * asc_prt_adv_scsi_req_q()
6284 *
6285 * Display an ADV_SCSI_REQ_Q structure.
6286 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006287static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006289 int sg_blk_cnt;
6290 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006292 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006294 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
6295 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006297 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
6298 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006300 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6301 (ulong)le32_to_cpu(q->data_cnt),
6302 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006303
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006304 printk
6305 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
6306 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006308 printk(" sg_working_ix 0x%x, target_cmd %u\n",
6309 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006311 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
6312 (ulong)le32_to_cpu(q->scsiq_rptr),
6313 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006315 /* Display the request's ADV_SG_BLOCK structures. */
6316 if (q->sg_list_ptr != NULL) {
6317 sg_blk_cnt = 0;
6318 while (1) {
6319 /*
6320 * 'sg_ptr' is a physical address. Convert it to a virtual
6321 * address by indexing 'sg_blk_cnt' into the virtual address
6322 * array 'sg_list_ptr'.
6323 *
6324 * XXX - Assumes all SG physical blocks are virtually contiguous.
6325 */
6326 sg_ptr =
6327 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
6328 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
6329 if (sg_ptr->sg_ptr == 0) {
6330 break;
6331 }
6332 sg_blk_cnt++;
6333 }
6334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335}
6336
6337/*
6338 * asc_prt_adv_sgblock()
6339 *
6340 * Display an ADV_SG_BLOCK structure.
6341 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006342static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006343{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006344 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006345
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006346 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
6347 (ulong)b, sgblockno);
6348 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
6349 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
6350 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
6351 if (b->sg_ptr != 0) {
6352 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
6353 }
6354 for (i = 0; i < b->sg_cnt; i++) {
6355 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
6356 i, (ulong)b->sg_list[i].sg_addr,
6357 (ulong)b->sg_list[i].sg_count);
6358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359}
6360
6361/*
6362 * asc_prt_hex()
6363 *
6364 * Print hexadecimal output in 4 byte groupings 32 bytes
6365 * or 8 double-words per line.
6366 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006367static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006368{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006369 int i;
6370 int j;
6371 int k;
6372 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006374 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006375
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006376 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006377
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006378 /* Display a maximum of 8 double-words per line. */
6379 if ((k = (l - i) / 4) >= 8) {
6380 k = 8;
6381 m = 0;
6382 } else {
6383 m = (l - i) % 4;
6384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006385
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006386 for (j = 0; j < k; j++) {
6387 printk(" %2.2X%2.2X%2.2X%2.2X",
6388 (unsigned)s[i + (j * 4)],
6389 (unsigned)s[i + (j * 4) + 1],
6390 (unsigned)s[i + (j * 4) + 2],
6391 (unsigned)s[i + (j * 4) + 3]);
6392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006394 switch (m) {
6395 case 0:
6396 default:
6397 break;
6398 case 1:
6399 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
6400 break;
6401 case 2:
6402 printk(" %2.2X%2.2X",
6403 (unsigned)s[i + (j * 4)],
6404 (unsigned)s[i + (j * 4) + 1]);
6405 break;
6406 case 3:
6407 printk(" %2.2X%2.2X%2.2X",
6408 (unsigned)s[i + (j * 4) + 1],
6409 (unsigned)s[i + (j * 4) + 2],
6410 (unsigned)s[i + (j * 4) + 3]);
6411 break;
6412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006414 printk("\n");
6415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006416}
6417#endif /* ADVANSYS_DEBUG */
6418
6419/*
6420 * --- Asc Library Functions
6421 */
6422
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006423static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006424{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006425 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006427 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6428 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
6429 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006430}
6431
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006432static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006433{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006434 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006436 if (AscGetChipScsiID(iop_base) == new_host_id) {
6437 return (new_host_id);
6438 }
6439 cfg_lsw = AscGetChipCfgLsw(iop_base);
6440 cfg_lsw &= 0xF8FF;
6441 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
6442 AscSetChipCfgLsw(iop_base, cfg_lsw);
6443 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006444}
6445
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006446static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006447{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006448 unsigned char sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006450 AscSetBank(iop_base, 1);
6451 sc = inp(iop_base + IOP_REG_SC);
6452 AscSetBank(iop_base, 0);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006453 return sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006454}
6455
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006456static unsigned char __devinit
6457AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006458{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006459 if (bus_type & ASC_IS_EISA) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006460 PortAddr eisa_iop;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006461 unsigned char revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006462 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6463 (PortAddr) ASC_EISA_REV_IOP_MASK;
6464 revision = inp(eisa_iop);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006465 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006466 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006467 return AscGetChipVerNo(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006468}
6469
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006470static ASC_DCNT
6471AscLoadMicroCode(PortAddr iop_base,
6472 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006473{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006474 ASC_DCNT chksum;
6475 ushort mcode_word_size;
6476 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006478 /* Write the microcode buffer starting at LRAM address 0. */
6479 mcode_word_size = (ushort)(mcode_size >> 1);
6480 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
6481 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006482
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006483 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
6484 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
6485 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
6486 (ushort)ASC_CODE_SEC_BEG,
6487 (ushort)((mcode_size -
6488 s_addr - (ushort)
6489 ASC_CODE_SEC_BEG) /
6490 2));
6491 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
6492 (ulong)mcode_chksum);
6493 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
6494 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
6495 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006496}
6497
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006498static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006499{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006500 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006501
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006502 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
6503 iop_base, AscGetChipSignatureByte(iop_base));
6504 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
6505 ASC_DBG2(1,
6506 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
6507 iop_base, AscGetChipSignatureWord(iop_base));
6508 sig_word = AscGetChipSignatureWord(iop_base);
6509 if ((sig_word == (ushort)ASC_1000_ID0W) ||
6510 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
6511 return (1);
6512 }
6513 }
6514 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006515}
6516
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006517static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006518{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006519 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
6520 AscSetChipStatus(iop_base, 0);
6521 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006522}
6523
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006524static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006525{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006526 ushort cfg_lsw;
6527 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006529 if ((bus_type & ASC_IS_EISA) != 0) {
6530 cfg_lsw = AscGetEisaChipCfg(iop_base);
6531 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
6532 if ((chip_irq == 13) || (chip_irq > 15)) {
6533 return (0);
6534 }
6535 return (chip_irq);
6536 }
6537 if ((bus_type & ASC_IS_VL) != 0) {
6538 cfg_lsw = AscGetChipCfgLsw(iop_base);
6539 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
6540 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
6541 return (0);
6542 }
6543 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
6544 }
6545 cfg_lsw = AscGetChipCfgLsw(iop_base);
6546 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
6547 if (chip_irq == 3)
6548 chip_irq += (uchar)2;
6549 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550}
6551
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006552static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006553AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006554{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006555 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006557 if ((bus_type & ASC_IS_VL) != 0) {
6558 if (irq_no != 0) {
6559 if ((irq_no < ASC_MIN_IRQ_NO)
6560 || (irq_no > ASC_MAX_IRQ_NO)) {
6561 irq_no = 0;
6562 } else {
6563 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
6564 }
6565 }
6566 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
6567 cfg_lsw |= (ushort)0x0010;
6568 AscSetChipCfgLsw(iop_base, cfg_lsw);
6569 AscToggleIRQAct(iop_base);
6570 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
6571 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
6572 AscSetChipCfgLsw(iop_base, cfg_lsw);
6573 AscToggleIRQAct(iop_base);
6574 return (AscGetChipIRQ(iop_base, bus_type));
6575 }
6576 if ((bus_type & (ASC_IS_ISA)) != 0) {
6577 if (irq_no == 15)
6578 irq_no -= (uchar)2;
6579 irq_no -= (uchar)ASC_MIN_IRQ_NO;
6580 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
6581 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
6582 AscSetChipCfgLsw(iop_base, cfg_lsw);
6583 return (AscGetChipIRQ(iop_base, bus_type));
6584 }
6585 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006586}
6587
6588#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006589static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006590{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006591 if (dma_channel < 4) {
6592 outp(0x000B, (ushort)(0xC0 | dma_channel));
6593 outp(0x000A, dma_channel);
6594 } else if (dma_channel < 8) {
6595 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
6596 outp(0x00D4, (ushort)(dma_channel - 4));
6597 }
6598 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006599}
6600#endif /* CONFIG_ISA */
6601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006602static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006603{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006604 EXT_MSG ext_msg;
6605 EXT_MSG out_msg;
6606 ushort halt_q_addr;
6607 int sdtr_accept;
6608 ushort int_halt_code;
6609 ASC_SCSI_BIT_ID_TYPE scsi_busy;
6610 ASC_SCSI_BIT_ID_TYPE target_id;
6611 PortAddr iop_base;
6612 uchar tag_code;
6613 uchar q_status;
6614 uchar halt_qp;
6615 uchar sdtr_data;
6616 uchar target_ix;
6617 uchar q_cntl, tid_no;
6618 uchar cur_dvc_qng;
6619 uchar asyn_sdtr;
6620 uchar scsi_status;
6621 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006622
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006623 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
6624 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006625
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006626 iop_base = asc_dvc->iop_base;
6627 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006629 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
6630 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
6631 target_ix = AscReadLramByte(iop_base,
6632 (ushort)(halt_q_addr +
6633 (ushort)ASC_SCSIQ_B_TARGET_IX));
6634 q_cntl =
6635 AscReadLramByte(iop_base,
6636 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
6637 tid_no = ASC_TIX_TO_TID(target_ix);
6638 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
6639 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6640 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
6641 } else {
6642 asyn_sdtr = 0;
6643 }
6644 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
6645 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6646 AscSetChipSDTR(iop_base, 0, tid_no);
6647 boardp->sdtr_data[tid_no] = 0;
6648 }
6649 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6650 return (0);
6651 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
6652 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6653 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6654 boardp->sdtr_data[tid_no] = asyn_sdtr;
6655 }
6656 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6657 return (0);
6658 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006659
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006660 AscMemWordCopyPtrFromLram(iop_base,
6661 ASCV_MSGIN_BEG,
6662 (uchar *)&ext_msg,
6663 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006664
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006665 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6666 ext_msg.msg_req == EXTENDED_SDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006667 ext_msg.msg_len == MS_SDTR_LEN) {
6668 sdtr_accept = TRUE;
6669 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006671 sdtr_accept = FALSE;
6672 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
6673 }
6674 if ((ext_msg.xfer_period <
6675 asc_dvc->sdtr_period_tbl[asc_dvc->
6676 host_init_sdtr_index])
6677 || (ext_msg.xfer_period >
6678 asc_dvc->sdtr_period_tbl[asc_dvc->
6679 max_sdtr_index])) {
6680 sdtr_accept = FALSE;
6681 ext_msg.xfer_period =
6682 asc_dvc->sdtr_period_tbl[asc_dvc->
6683 host_init_sdtr_index];
6684 }
6685 if (sdtr_accept) {
6686 sdtr_data =
6687 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
6688 ext_msg.req_ack_offset);
6689 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006690
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006691 q_cntl |= QC_MSG_OUT;
6692 asc_dvc->init_sdtr &= ~target_id;
6693 asc_dvc->sdtr_done &= ~target_id;
6694 AscSetChipSDTR(iop_base, asyn_sdtr,
6695 tid_no);
6696 boardp->sdtr_data[tid_no] = asyn_sdtr;
6697 }
6698 }
6699 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006700
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006701 q_cntl &= ~QC_MSG_OUT;
6702 asc_dvc->init_sdtr &= ~target_id;
6703 asc_dvc->sdtr_done &= ~target_id;
6704 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6705 } else {
6706 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006708 q_cntl &= ~QC_MSG_OUT;
6709 asc_dvc->sdtr_done |= target_id;
6710 asc_dvc->init_sdtr |= target_id;
6711 asc_dvc->pci_fix_asyn_xfer &=
6712 ~target_id;
6713 sdtr_data =
6714 AscCalSDTRData(asc_dvc,
6715 ext_msg.xfer_period,
6716 ext_msg.
6717 req_ack_offset);
6718 AscSetChipSDTR(iop_base, sdtr_data,
6719 tid_no);
6720 boardp->sdtr_data[tid_no] = sdtr_data;
6721 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006723 q_cntl |= QC_MSG_OUT;
6724 AscMsgOutSDTR(asc_dvc,
6725 ext_msg.xfer_period,
6726 ext_msg.req_ack_offset);
6727 asc_dvc->pci_fix_asyn_xfer &=
6728 ~target_id;
6729 sdtr_data =
6730 AscCalSDTRData(asc_dvc,
6731 ext_msg.xfer_period,
6732 ext_msg.
6733 req_ack_offset);
6734 AscSetChipSDTR(iop_base, sdtr_data,
6735 tid_no);
6736 boardp->sdtr_data[tid_no] = sdtr_data;
6737 asc_dvc->sdtr_done |= target_id;
6738 asc_dvc->init_sdtr |= target_id;
6739 }
6740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006742 AscWriteLramByte(iop_base,
6743 (ushort)(halt_q_addr +
6744 (ushort)ASC_SCSIQ_B_CNTL),
6745 q_cntl);
6746 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6747 return (0);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006748 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6749 ext_msg.msg_req == EXTENDED_WDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006750 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006751
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006752 ext_msg.wdtr_width = 0;
6753 AscMemWordCopyPtrToLram(iop_base,
6754 ASCV_MSGOUT_BEG,
6755 (uchar *)&ext_msg,
6756 sizeof(EXT_MSG) >> 1);
6757 q_cntl |= QC_MSG_OUT;
6758 AscWriteLramByte(iop_base,
6759 (ushort)(halt_q_addr +
6760 (ushort)ASC_SCSIQ_B_CNTL),
6761 q_cntl);
6762 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6763 return (0);
6764 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006765
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006766 ext_msg.msg_type = MESSAGE_REJECT;
6767 AscMemWordCopyPtrToLram(iop_base,
6768 ASCV_MSGOUT_BEG,
6769 (uchar *)&ext_msg,
6770 sizeof(EXT_MSG) >> 1);
6771 q_cntl |= QC_MSG_OUT;
6772 AscWriteLramByte(iop_base,
6773 (ushort)(halt_q_addr +
6774 (ushort)ASC_SCSIQ_B_CNTL),
6775 q_cntl);
6776 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6777 return (0);
6778 }
6779 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006781 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006783 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006785 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006786
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006787 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
6788 q_cntl |= QC_MSG_OUT;
6789 AscMsgOutSDTR(asc_dvc,
6790 asc_dvc->
6791 sdtr_period_tbl[(sdtr_data >> 4) &
6792 (uchar)(asc_dvc->
6793 max_sdtr_index -
6794 1)],
6795 (uchar)(sdtr_data & (uchar)
6796 ASC_SYN_MAX_OFFSET));
6797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006799 AscWriteLramByte(iop_base,
6800 (ushort)(halt_q_addr +
6801 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006802
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006803 tag_code = AscReadLramByte(iop_base,
6804 (ushort)(halt_q_addr + (ushort)
6805 ASC_SCSIQ_B_TAG_CODE));
6806 tag_code &= 0xDC;
6807 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
6808 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
6809 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006810
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006811 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
6812 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006813
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006814 }
6815 AscWriteLramByte(iop_base,
6816 (ushort)(halt_q_addr +
6817 (ushort)ASC_SCSIQ_B_TAG_CODE),
6818 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006820 q_status = AscReadLramByte(iop_base,
6821 (ushort)(halt_q_addr + (ushort)
6822 ASC_SCSIQ_B_STATUS));
6823 q_status |= (QS_READY | QS_BUSY);
6824 AscWriteLramByte(iop_base,
6825 (ushort)(halt_q_addr +
6826 (ushort)ASC_SCSIQ_B_STATUS),
6827 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006828
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006829 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
6830 scsi_busy &= ~target_id;
6831 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006832
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006833 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6834 return (0);
6835 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006837 AscMemWordCopyPtrFromLram(iop_base,
6838 ASCV_MSGOUT_BEG,
6839 (uchar *)&out_msg,
6840 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006841
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006842 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006843 (out_msg.msg_len == MS_SDTR_LEN) &&
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006844 (out_msg.msg_req == EXTENDED_SDTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006845
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006846 asc_dvc->init_sdtr &= ~target_id;
6847 asc_dvc->sdtr_done &= ~target_id;
6848 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6849 boardp->sdtr_data[tid_no] = asyn_sdtr;
6850 }
6851 q_cntl &= ~QC_MSG_OUT;
6852 AscWriteLramByte(iop_base,
6853 (ushort)(halt_q_addr +
6854 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
6855 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6856 return (0);
6857 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006859 scsi_status = AscReadLramByte(iop_base,
6860 (ushort)((ushort)halt_q_addr +
6861 (ushort)
6862 ASC_SCSIQ_SCSI_STATUS));
6863 cur_dvc_qng =
6864 AscReadLramByte(iop_base,
6865 (ushort)((ushort)ASC_QADR_BEG +
6866 (ushort)target_ix));
6867 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006869 scsi_busy = AscReadLramByte(iop_base,
6870 (ushort)ASCV_SCSIBUSY_B);
6871 scsi_busy |= target_id;
6872 AscWriteLramByte(iop_base,
6873 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
6874 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006875
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006876 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
6877 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
6878 cur_dvc_qng -= 1;
6879 asc_dvc->max_dvc_qng[tid_no] =
6880 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006882 AscWriteLramByte(iop_base,
6883 (ushort)((ushort)
6884 ASCV_MAX_DVC_QNG_BEG
6885 + (ushort)
6886 tid_no),
6887 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006889 /*
6890 * Set the device queue depth to the number of
6891 * active requests when the QUEUE FULL condition
6892 * was encountered.
6893 */
6894 boardp->queue_full |= target_id;
6895 boardp->queue_full_cnt[tid_no] =
6896 cur_dvc_qng;
6897 }
6898 }
6899 }
6900 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6901 return (0);
6902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006903#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006904 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
6905 uchar q_no;
6906 ushort q_addr;
6907 uchar sg_wk_q_no;
6908 uchar first_sg_wk_q_no;
6909 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
6910 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
6911 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
6912 ushort sg_list_dwords;
6913 ushort sg_entry_cnt;
6914 uchar next_qp;
6915 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006916
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006917 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
6918 if (q_no == ASC_QLINK_END) {
6919 return (0);
6920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006922 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006923
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006924 /*
6925 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
6926 * structure pointer using a macro provided by the driver.
6927 * The ASC_SCSI_REQ pointer provides a pointer to the
6928 * host ASC_SG_HEAD structure.
6929 */
6930 /* Read request's SRB pointer. */
6931 scsiq = (ASC_SCSI_Q *)
6932 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
6933 (ushort)
6934 (q_addr +
6935 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006936
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006937 /*
6938 * Get request's first and working SG queue.
6939 */
6940 sg_wk_q_no = AscReadLramByte(iop_base,
6941 (ushort)(q_addr +
6942 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006944 first_sg_wk_q_no = AscReadLramByte(iop_base,
6945 (ushort)(q_addr +
6946 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006948 /*
6949 * Reset request's working SG queue back to the
6950 * first SG queue.
6951 */
6952 AscWriteLramByte(iop_base,
6953 (ushort)(q_addr +
6954 (ushort)ASC_SCSIQ_B_SG_WK_QP),
6955 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006956
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006957 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006959 /*
6960 * Set sg_entry_cnt to the number of SG elements
6961 * that will be completed on this interrupt.
6962 *
6963 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
6964 * SG elements. The data_cnt and data_addr fields which
6965 * add 1 to the SG element capacity are not used when
6966 * restarting SG handling after a halt.
6967 */
6968 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
6969 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006970
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006971 /*
6972 * Keep track of remaining number of SG elements that will
6973 * need to be handled on the next interrupt.
6974 */
6975 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
6976 } else {
6977 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
6978 scsiq->remain_sg_entry_cnt = 0;
6979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006981 /*
6982 * Copy SG elements into the list of allocated SG queues.
6983 *
6984 * Last index completed is saved in scsiq->next_sg_index.
6985 */
6986 next_qp = first_sg_wk_q_no;
6987 q_addr = ASC_QNO_TO_QADDR(next_qp);
6988 scsi_sg_q.sg_head_qp = q_no;
6989 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
6990 for (i = 0; i < sg_head->queue_cnt; i++) {
6991 scsi_sg_q.seq_no = i + 1;
6992 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
6993 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
6994 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
6995 /*
6996 * After very first SG queue RISC FW uses next
6997 * SG queue first element then checks sg_list_cnt
6998 * against zero and then decrements, so set
6999 * sg_list_cnt 1 less than number of SG elements
7000 * in each SG queue.
7001 */
7002 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
7003 scsi_sg_q.sg_cur_list_cnt =
7004 ASC_SG_LIST_PER_Q - 1;
7005 } else {
7006 /*
7007 * This is the last SG queue in the list of
7008 * allocated SG queues. If there are more
7009 * SG elements than will fit in the allocated
7010 * queues, then set the QCSG_SG_XFER_MORE flag.
7011 */
7012 if (scsiq->remain_sg_entry_cnt != 0) {
7013 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
7014 } else {
7015 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
7016 }
7017 /* equals sg_entry_cnt * 2 */
7018 sg_list_dwords = sg_entry_cnt << 1;
7019 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
7020 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
7021 sg_entry_cnt = 0;
7022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007023
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007024 scsi_sg_q.q_no = next_qp;
7025 AscMemWordCopyPtrToLram(iop_base,
7026 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
7027 (uchar *)&scsi_sg_q,
7028 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007030 AscMemDWordCopyPtrToLram(iop_base,
7031 q_addr + ASC_SGQ_LIST_BEG,
7032 (uchar *)&sg_head->
7033 sg_list[scsiq->next_sg_index],
7034 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007035
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007036 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007038 /*
7039 * If the just completed SG queue contained the
7040 * last SG element, then no more SG queues need
7041 * to be written.
7042 */
7043 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
7044 break;
7045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007047 next_qp = AscReadLramByte(iop_base,
7048 (ushort)(q_addr +
7049 ASC_SCSIQ_B_FWD));
7050 q_addr = ASC_QNO_TO_QADDR(next_qp);
7051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007053 /*
7054 * Clear the halt condition so the RISC will be restarted
7055 * after the return.
7056 */
7057 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7058 return (0);
7059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007061 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007062}
7063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007064static uchar
7065_AscCopyLramScsiDoneQ(PortAddr iop_base,
7066 ushort q_addr,
7067 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007069 ushort _val;
7070 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007072 DvcGetQinfo(iop_base,
7073 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
7074 (uchar *)scsiq,
7075 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007077 _val = AscReadLramWord(iop_base,
7078 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
7079 scsiq->q_status = (uchar)_val;
7080 scsiq->q_no = (uchar)(_val >> 8);
7081 _val = AscReadLramWord(iop_base,
7082 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
7083 scsiq->cntl = (uchar)_val;
7084 sg_queue_cnt = (uchar)(_val >> 8);
7085 _val = AscReadLramWord(iop_base,
7086 (ushort)(q_addr +
7087 (ushort)ASC_SCSIQ_B_SENSE_LEN));
7088 scsiq->sense_len = (uchar)_val;
7089 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007091 /*
7092 * Read high word of remain bytes from alternate location.
7093 */
7094 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
7095 (ushort)(q_addr +
7096 (ushort)
7097 ASC_SCSIQ_W_ALT_DC1)))
7098 << 16);
7099 /*
7100 * Read low word of remain bytes from original location.
7101 */
7102 scsiq->remain_bytes += AscReadLramWord(iop_base,
7103 (ushort)(q_addr + (ushort)
7104 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007106 scsiq->remain_bytes &= max_dma_count;
7107 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108}
7109
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007110static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007112 uchar next_qp;
7113 uchar n_q_used;
7114 uchar sg_list_qp;
7115 uchar sg_queue_cnt;
7116 uchar q_cnt;
7117 uchar done_q_tail;
7118 uchar tid_no;
7119 ASC_SCSI_BIT_ID_TYPE scsi_busy;
7120 ASC_SCSI_BIT_ID_TYPE target_id;
7121 PortAddr iop_base;
7122 ushort q_addr;
7123 ushort sg_q_addr;
7124 uchar cur_target_qng;
7125 ASC_QDONE_INFO scsiq_buf;
7126 ASC_QDONE_INFO *scsiq;
7127 int false_overrun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007129 iop_base = asc_dvc->iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007130 n_q_used = 1;
7131 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
7132 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
7133 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
7134 next_qp = AscReadLramByte(iop_base,
7135 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
7136 if (next_qp != ASC_QLINK_END) {
7137 AscPutVarDoneQTail(iop_base, next_qp);
7138 q_addr = ASC_QNO_TO_QADDR(next_qp);
7139 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
7140 asc_dvc->max_dma_count);
7141 AscWriteLramByte(iop_base,
7142 (ushort)(q_addr +
7143 (ushort)ASC_SCSIQ_B_STATUS),
7144 (uchar)(scsiq->
7145 q_status & (uchar)~(QS_READY |
7146 QS_ABORTED)));
7147 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
7148 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
7149 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
7150 sg_q_addr = q_addr;
7151 sg_list_qp = next_qp;
7152 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
7153 sg_list_qp = AscReadLramByte(iop_base,
7154 (ushort)(sg_q_addr
7155 + (ushort)
7156 ASC_SCSIQ_B_FWD));
7157 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
7158 if (sg_list_qp == ASC_QLINK_END) {
7159 AscSetLibErrorCode(asc_dvc,
7160 ASCQ_ERR_SG_Q_LINKS);
7161 scsiq->d3.done_stat = QD_WITH_ERROR;
7162 scsiq->d3.host_stat =
7163 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
7164 goto FATAL_ERR_QDONE;
7165 }
7166 AscWriteLramByte(iop_base,
7167 (ushort)(sg_q_addr + (ushort)
7168 ASC_SCSIQ_B_STATUS),
7169 QS_FREE);
7170 }
7171 n_q_used = sg_queue_cnt + 1;
7172 AscPutVarDoneQTail(iop_base, sg_list_qp);
7173 }
7174 if (asc_dvc->queue_full_or_busy & target_id) {
7175 cur_target_qng = AscReadLramByte(iop_base,
7176 (ushort)((ushort)
7177 ASC_QADR_BEG
7178 + (ushort)
7179 scsiq->d2.
7180 target_ix));
7181 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
7182 scsi_busy = AscReadLramByte(iop_base, (ushort)
7183 ASCV_SCSIBUSY_B);
7184 scsi_busy &= ~target_id;
7185 AscWriteLramByte(iop_base,
7186 (ushort)ASCV_SCSIBUSY_B,
7187 scsi_busy);
7188 asc_dvc->queue_full_or_busy &= ~target_id;
7189 }
7190 }
7191 if (asc_dvc->cur_total_qng >= n_q_used) {
7192 asc_dvc->cur_total_qng -= n_q_used;
7193 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
7194 asc_dvc->cur_dvc_qng[tid_no]--;
7195 }
7196 } else {
7197 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
7198 scsiq->d3.done_stat = QD_WITH_ERROR;
7199 goto FATAL_ERR_QDONE;
7200 }
7201 if ((scsiq->d2.srb_ptr == 0UL) ||
7202 ((scsiq->q_status & QS_ABORTED) != 0)) {
7203 return (0x11);
7204 } else if (scsiq->q_status == QS_DONE) {
7205 false_overrun = FALSE;
7206 if (scsiq->extra_bytes != 0) {
7207 scsiq->remain_bytes +=
7208 (ADV_DCNT)scsiq->extra_bytes;
7209 }
7210 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
7211 if (scsiq->d3.host_stat ==
7212 QHSTA_M_DATA_OVER_RUN) {
7213 if ((scsiq->
7214 cntl & (QC_DATA_IN | QC_DATA_OUT))
7215 == 0) {
7216 scsiq->d3.done_stat =
7217 QD_NO_ERROR;
7218 scsiq->d3.host_stat =
7219 QHSTA_NO_ERROR;
7220 } else if (false_overrun) {
7221 scsiq->d3.done_stat =
7222 QD_NO_ERROR;
7223 scsiq->d3.host_stat =
7224 QHSTA_NO_ERROR;
7225 }
7226 } else if (scsiq->d3.host_stat ==
7227 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
7228 AscStopChip(iop_base);
7229 AscSetChipControl(iop_base,
7230 (uchar)(CC_SCSI_RESET
7231 | CC_HALT));
7232 DvcDelayNanoSecond(asc_dvc, 60000);
7233 AscSetChipControl(iop_base, CC_HALT);
7234 AscSetChipStatus(iop_base,
7235 CIW_CLR_SCSI_RESET_INT);
7236 AscSetChipStatus(iop_base, 0);
7237 AscSetChipControl(iop_base, 0);
7238 }
7239 }
7240 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007241 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007242 } else {
7243 if ((AscReadLramByte(iop_base,
7244 (ushort)(q_addr + (ushort)
7245 ASC_SCSIQ_CDB_BEG))
7246 == START_STOP)) {
7247 asc_dvc->unit_not_ready &= ~target_id;
7248 if (scsiq->d3.done_stat != QD_NO_ERROR) {
7249 asc_dvc->start_motor &=
7250 ~target_id;
7251 }
7252 }
7253 }
7254 return (1);
7255 } else {
7256 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
7257 FATAL_ERR_QDONE:
7258 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007259 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007260 }
7261 return (0x80);
7262 }
7263 }
7264 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007265}
7266
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007267static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007268{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007269 ASC_CS_TYPE chipstat;
7270 PortAddr iop_base;
7271 ushort saved_ram_addr;
7272 uchar ctrl_reg;
7273 uchar saved_ctrl_reg;
7274 int int_pending;
7275 int status;
7276 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007278 iop_base = asc_dvc->iop_base;
7279 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007280
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007281 if (AscIsIntPending(iop_base) == 0) {
7282 return int_pending;
7283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007284
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007285 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007286 return (ERR);
7287 }
7288 if (asc_dvc->in_critical_cnt != 0) {
7289 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
7290 return (ERR);
7291 }
7292 if (asc_dvc->is_in_int) {
7293 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
7294 return (ERR);
7295 }
7296 asc_dvc->is_in_int = TRUE;
7297 ctrl_reg = AscGetChipControl(iop_base);
7298 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
7299 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
7300 chipstat = AscGetChipStatus(iop_base);
7301 if (chipstat & CSW_SCSI_RESET_LATCH) {
7302 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
7303 int i = 10;
7304 int_pending = TRUE;
7305 asc_dvc->sdtr_done = 0;
7306 saved_ctrl_reg &= (uchar)(~CC_HALT);
7307 while ((AscGetChipStatus(iop_base) &
7308 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
7309 DvcSleepMilliSecond(100);
7310 }
7311 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
7312 AscSetChipControl(iop_base, CC_HALT);
7313 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
7314 AscSetChipStatus(iop_base, 0);
7315 chipstat = AscGetChipStatus(iop_base);
7316 }
7317 }
7318 saved_ram_addr = AscGetChipLramAddr(iop_base);
7319 host_flag = AscReadLramByte(iop_base,
7320 ASCV_HOST_FLAG_B) &
7321 (uchar)(~ASC_HOST_FLAG_IN_ISR);
7322 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7323 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
7324 if ((chipstat & CSW_INT_PENDING)
7325 || (int_pending)
7326 ) {
7327 AscAckInterrupt(iop_base);
7328 int_pending = TRUE;
7329 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
7330 if (AscIsrChipHalted(asc_dvc) == ERR) {
7331 goto ISR_REPORT_QDONE_FATAL_ERROR;
7332 } else {
7333 saved_ctrl_reg &= (uchar)(~CC_HALT);
7334 }
7335 } else {
7336 ISR_REPORT_QDONE_FATAL_ERROR:
7337 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
7338 while (((status =
7339 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
7340 }
7341 } else {
7342 do {
7343 if ((status =
7344 AscIsrQDone(asc_dvc)) == 1) {
7345 break;
7346 }
7347 } while (status == 0x11);
7348 }
7349 if ((status & 0x80) != 0)
7350 int_pending = ERR;
7351 }
7352 }
7353 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7354 AscSetChipLramAddr(iop_base, saved_ram_addr);
7355 AscSetChipControl(iop_base, saved_ctrl_reg);
7356 asc_dvc->is_in_int = FALSE;
7357 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007358}
7359
7360/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007361static uchar _asc_mcode_buf[] = {
7362 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007363 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
7368 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7369 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007370 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007371 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
7372 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
7373 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007374 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007375 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
7376 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
7377 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007378 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007379 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
7380 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
7381 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007382 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007383 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
7384 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
7385 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007386 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007387 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
7388 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
7389 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007390 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007391 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
7392 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
7393 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007394 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007395 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
7396 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
7397 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007398 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007399 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
7400 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
7401 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007402 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007403 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
7404 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
7405 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007406 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007407 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
7408 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
7409 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007410 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007411 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
7412 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
7413 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007414 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007415 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
7416 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
7417 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007418 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007419 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
7420 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
7421 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007422 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007423 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
7424 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
7425 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007426 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007427 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
7428 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
7429 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007430 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007431 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
7432 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
7433 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007434 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007435 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
7436 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
7437 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007438 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007439 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
7440 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
7441 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007442 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007443 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
7444 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
7445 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007446 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007447 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
7448 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
7449 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007450 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007451 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
7452 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
7453 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007454 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007455 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
7456 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
7457 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007458 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007459 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
7460 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
7461 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007462 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007463 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
7464 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
7465 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007466 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007467 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
7468 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
7469 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007470 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007471 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
7472 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
7473 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007474 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007475 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
7476 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
7477 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007478 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007479 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
7480 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
7481 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007482 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007483 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
7484 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
7485 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007486 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007487 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
7488 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
7489 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007490 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007491 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
7492 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
7493 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007494 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007495 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
7496 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
7497 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007498 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007499 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
7500 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
7501 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007502 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007503 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
7504 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
7505 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007506 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007507 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
7508 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
7509 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007510 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007511 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
7512 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
7513 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007514 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007515 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
7516 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
7517 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007518 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007519 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
7520 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
7521 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007522 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007523 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
7524 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
7525 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007526 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007527 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
7528 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
7529 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007530 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007531 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
7532 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
7533 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007534 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007535 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
7536 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
7537 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007538 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007539 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
7540 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
7541 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007542 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007543 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
7544 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
7545 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007546 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007547 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
7548 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
7549 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007550 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007551 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
7552 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
7553 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007554};
7555
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007556static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
7557static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007558
7559#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007560static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
7561 INQUIRY,
7562 REQUEST_SENSE,
7563 READ_CAPACITY,
7564 READ_TOC,
7565 MODE_SELECT,
7566 MODE_SENSE,
7567 MODE_SELECT_10,
7568 MODE_SENSE_10,
7569 0xFF,
7570 0xFF,
7571 0xFF,
7572 0xFF,
7573 0xFF,
7574 0xFF,
7575 0xFF,
7576 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07007577};
7578
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007579static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007580{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007581 PortAddr iop_base;
7582 ulong last_int_level;
7583 int sta;
7584 int n_q_required;
7585 int disable_syn_offset_one_fix;
7586 int i;
7587 ASC_PADDR addr;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007588 ushort sg_entry_cnt = 0;
7589 ushort sg_entry_cnt_minus_one = 0;
7590 uchar target_ix;
7591 uchar tid_no;
7592 uchar sdtr_data;
7593 uchar extra_bytes;
7594 uchar scsi_cmd;
7595 uchar disable_cmd;
7596 ASC_SG_HEAD *sg_head;
7597 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007598
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007599 iop_base = asc_dvc->iop_base;
7600 sg_head = scsiq->sg_head;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007601 if (asc_dvc->err_code != 0)
7602 return (ERR);
7603 if (scsiq == (ASC_SCSI_Q *)0L) {
7604 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
7605 return (ERR);
7606 }
7607 scsiq->q1.q_no = 0;
7608 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
7609 scsiq->q1.extra_bytes = 0;
7610 }
7611 sta = 0;
7612 target_ix = scsiq->q2.target_ix;
7613 tid_no = ASC_TIX_TO_TID(target_ix);
7614 n_q_required = 1;
7615 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
7616 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
7617 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
7618 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7619 AscMsgOutSDTR(asc_dvc,
7620 asc_dvc->
7621 sdtr_period_tbl[(sdtr_data >> 4) &
7622 (uchar)(asc_dvc->
7623 max_sdtr_index -
7624 1)],
7625 (uchar)(sdtr_data & (uchar)
7626 ASC_SYN_MAX_OFFSET));
7627 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
7628 }
7629 }
7630 last_int_level = DvcEnterCritical();
7631 if (asc_dvc->in_critical_cnt != 0) {
7632 DvcLeaveCritical(last_int_level);
7633 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
7634 return (ERR);
7635 }
7636 asc_dvc->in_critical_cnt++;
7637 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7638 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
7639 asc_dvc->in_critical_cnt--;
7640 DvcLeaveCritical(last_int_level);
7641 return (ERR);
7642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007643#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007644 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7645 asc_dvc->in_critical_cnt--;
7646 DvcLeaveCritical(last_int_level);
7647 return (ERR);
7648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007649#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007650 if (sg_entry_cnt == 1) {
7651 scsiq->q1.data_addr =
7652 (ADV_PADDR)sg_head->sg_list[0].addr;
7653 scsiq->q1.data_cnt =
7654 (ADV_DCNT)sg_head->sg_list[0].bytes;
7655 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
7656 }
7657 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
7658 }
7659 scsi_cmd = scsiq->cdbptr[0];
7660 disable_syn_offset_one_fix = FALSE;
7661 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
7662 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
7663 if (scsiq->q1.cntl & QC_SG_HEAD) {
7664 data_cnt = 0;
7665 for (i = 0; i < sg_entry_cnt; i++) {
7666 data_cnt +=
7667 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
7668 bytes);
7669 }
7670 } else {
7671 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
7672 }
7673 if (data_cnt != 0UL) {
7674 if (data_cnt < 512UL) {
7675 disable_syn_offset_one_fix = TRUE;
7676 } else {
7677 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
7678 i++) {
7679 disable_cmd =
7680 _syn_offset_one_disable_cmd[i];
7681 if (disable_cmd == 0xFF) {
7682 break;
7683 }
7684 if (scsi_cmd == disable_cmd) {
7685 disable_syn_offset_one_fix =
7686 TRUE;
7687 break;
7688 }
7689 }
7690 }
7691 }
7692 }
7693 if (disable_syn_offset_one_fix) {
7694 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7695 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
7696 ASC_TAG_FLAG_DISABLE_DISCONNECT);
7697 } else {
7698 scsiq->q2.tag_code &= 0x27;
7699 }
7700 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7701 if (asc_dvc->bug_fix_cntl) {
7702 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7703 if ((scsi_cmd == READ_6) ||
7704 (scsi_cmd == READ_10)) {
7705 addr =
7706 (ADV_PADDR)le32_to_cpu(sg_head->
7707 sg_list
7708 [sg_entry_cnt_minus_one].
7709 addr) +
7710 (ADV_DCNT)le32_to_cpu(sg_head->
7711 sg_list
7712 [sg_entry_cnt_minus_one].
7713 bytes);
7714 extra_bytes =
7715 (uchar)((ushort)addr & 0x0003);
7716 if ((extra_bytes != 0)
7717 &&
7718 ((scsiq->q2.
7719 tag_code &
7720 ASC_TAG_FLAG_EXTRA_BYTES)
7721 == 0)) {
7722 scsiq->q2.tag_code |=
7723 ASC_TAG_FLAG_EXTRA_BYTES;
7724 scsiq->q1.extra_bytes =
7725 extra_bytes;
7726 data_cnt =
7727 le32_to_cpu(sg_head->
7728 sg_list
7729 [sg_entry_cnt_minus_one].
7730 bytes);
7731 data_cnt -=
7732 (ASC_DCNT) extra_bytes;
7733 sg_head->
7734 sg_list
7735 [sg_entry_cnt_minus_one].
7736 bytes =
7737 cpu_to_le32(data_cnt);
7738 }
7739 }
7740 }
7741 }
7742 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007743#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007744 /*
7745 * Set the sg_entry_cnt to the maximum possible. The rest of
7746 * the SG elements will be copied when the RISC completes the
7747 * SG elements that fit and halts.
7748 */
7749 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7750 sg_entry_cnt = ASC_MAX_SG_LIST;
7751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007752#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007753 n_q_required = AscSgListToQueue(sg_entry_cnt);
7754 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
7755 (uint) n_q_required)
7756 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7757 if ((sta =
7758 AscSendScsiQueue(asc_dvc, scsiq,
7759 n_q_required)) == 1) {
7760 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007761 DvcLeaveCritical(last_int_level);
7762 return (sta);
7763 }
7764 }
7765 } else {
7766 if (asc_dvc->bug_fix_cntl) {
7767 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7768 if ((scsi_cmd == READ_6) ||
7769 (scsi_cmd == READ_10)) {
7770 addr =
7771 le32_to_cpu(scsiq->q1.data_addr) +
7772 le32_to_cpu(scsiq->q1.data_cnt);
7773 extra_bytes =
7774 (uchar)((ushort)addr & 0x0003);
7775 if ((extra_bytes != 0)
7776 &&
7777 ((scsiq->q2.
7778 tag_code &
7779 ASC_TAG_FLAG_EXTRA_BYTES)
7780 == 0)) {
7781 data_cnt =
7782 le32_to_cpu(scsiq->q1.
7783 data_cnt);
7784 if (((ushort)data_cnt & 0x01FF)
7785 == 0) {
7786 scsiq->q2.tag_code |=
7787 ASC_TAG_FLAG_EXTRA_BYTES;
7788 data_cnt -= (ASC_DCNT)
7789 extra_bytes;
7790 scsiq->q1.data_cnt =
7791 cpu_to_le32
7792 (data_cnt);
7793 scsiq->q1.extra_bytes =
7794 extra_bytes;
7795 }
7796 }
7797 }
7798 }
7799 }
7800 n_q_required = 1;
7801 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
7802 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7803 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
7804 n_q_required)) == 1) {
7805 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007806 DvcLeaveCritical(last_int_level);
7807 return (sta);
7808 }
7809 }
7810 }
7811 asc_dvc->in_critical_cnt--;
7812 DvcLeaveCritical(last_int_level);
7813 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007814}
7815
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007816static int
7817AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007818{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007819 PortAddr iop_base;
7820 uchar free_q_head;
7821 uchar next_qp;
7822 uchar tid_no;
7823 uchar target_ix;
7824 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007825
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007826 iop_base = asc_dvc->iop_base;
7827 target_ix = scsiq->q2.target_ix;
7828 tid_no = ASC_TIX_TO_TID(target_ix);
7829 sta = 0;
7830 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
7831 if (n_q_required > 1) {
7832 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
7833 free_q_head, (uchar)
7834 (n_q_required)))
7835 != (uchar)ASC_QLINK_END) {
7836 asc_dvc->last_q_shortage = 0;
7837 scsiq->sg_head->queue_cnt = n_q_required - 1;
7838 scsiq->q1.q_no = free_q_head;
7839 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
7840 free_q_head)) == 1) {
7841 AscPutVarFreeQHead(iop_base, next_qp);
7842 asc_dvc->cur_total_qng += (uchar)(n_q_required);
7843 asc_dvc->cur_dvc_qng[tid_no]++;
7844 }
7845 return (sta);
7846 }
7847 } else if (n_q_required == 1) {
7848 if ((next_qp = AscAllocFreeQueue(iop_base,
7849 free_q_head)) !=
7850 ASC_QLINK_END) {
7851 scsiq->q1.q_no = free_q_head;
7852 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
7853 free_q_head)) == 1) {
7854 AscPutVarFreeQHead(iop_base, next_qp);
7855 asc_dvc->cur_total_qng++;
7856 asc_dvc->cur_dvc_qng[tid_no]++;
7857 }
7858 return (sta);
7859 }
7860 }
7861 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007862}
7863
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007864static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007865{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007866 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007868 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
7869 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
7870 n_sg_list_qs++;
7871 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007872}
7873
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007874static uint
7875AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007876{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007877 uint cur_used_qs;
7878 uint cur_free_qs;
7879 ASC_SCSI_BIT_ID_TYPE target_id;
7880 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007882 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
7883 tid_no = ASC_TIX_TO_TID(target_ix);
7884 if ((asc_dvc->unit_not_ready & target_id) ||
7885 (asc_dvc->queue_full_or_busy & target_id)) {
7886 return (0);
7887 }
7888 if (n_qs == 1) {
7889 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7890 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
7891 } else {
7892 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7893 (uint) ASC_MIN_FREE_Q;
7894 }
7895 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
7896 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
7897 if (asc_dvc->cur_dvc_qng[tid_no] >=
7898 asc_dvc->max_dvc_qng[tid_no]) {
7899 return (0);
7900 }
7901 return (cur_free_qs);
7902 }
7903 if (n_qs > 1) {
7904 if ((n_qs > asc_dvc->last_q_shortage)
7905 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
7906 asc_dvc->last_q_shortage = n_qs;
7907 }
7908 }
7909 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007910}
7911
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007912static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007913{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007914 ushort q_addr;
7915 uchar tid_no;
7916 uchar sdtr_data;
7917 uchar syn_period_ix;
7918 uchar syn_offset;
7919 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007920
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007921 iop_base = asc_dvc->iop_base;
7922 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
7923 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
7924 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
7925 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7926 syn_period_ix =
7927 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
7928 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
7929 AscMsgOutSDTR(asc_dvc,
7930 asc_dvc->sdtr_period_tbl[syn_period_ix],
7931 syn_offset);
7932 scsiq->q1.cntl |= QC_MSG_OUT;
7933 }
7934 q_addr = ASC_QNO_TO_QADDR(q_no);
7935 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
7936 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7937 }
7938 scsiq->q1.status = QS_FREE;
7939 AscMemWordCopyPtrToLram(iop_base,
7940 q_addr + ASC_SCSIQ_CDB_BEG,
7941 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007942
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007943 DvcPutScsiQ(iop_base,
7944 q_addr + ASC_SCSIQ_CPY_BEG,
7945 (uchar *)&scsiq->q1.cntl,
7946 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
7947 AscWriteLramWord(iop_base,
7948 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
7949 (ushort)(((ushort)scsiq->q1.
7950 q_no << 8) | (ushort)QS_READY));
7951 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007952}
7953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007954static int
7955AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007956{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007957 int sta;
7958 int i;
7959 ASC_SG_HEAD *sg_head;
7960 ASC_SG_LIST_Q scsi_sg_q;
7961 ASC_DCNT saved_data_addr;
7962 ASC_DCNT saved_data_cnt;
7963 PortAddr iop_base;
7964 ushort sg_list_dwords;
7965 ushort sg_index;
7966 ushort sg_entry_cnt;
7967 ushort q_addr;
7968 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007970 iop_base = asc_dvc->iop_base;
7971 sg_head = scsiq->sg_head;
7972 saved_data_addr = scsiq->q1.data_addr;
7973 saved_data_cnt = scsiq->q1.data_cnt;
7974 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
7975 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007976#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007977 /*
7978 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
7979 * then not all SG elements will fit in the allocated queues.
7980 * The rest of the SG elements will be copied when the RISC
7981 * completes the SG elements that fit and halts.
7982 */
7983 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
7984 /*
7985 * Set sg_entry_cnt to be the number of SG elements that
7986 * will fit in the allocated SG queues. It is minus 1, because
7987 * the first SG element is handled above. ASC_MAX_SG_LIST is
7988 * already inflated by 1 to account for this. For example it
7989 * may be 50 which is 1 + 7 queues * 7 SG elements.
7990 */
7991 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007992
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007993 /*
7994 * Keep track of remaining number of SG elements that will
7995 * need to be handled from a_isr.c.
7996 */
7997 scsiq->remain_sg_entry_cnt =
7998 sg_head->entry_cnt - ASC_MAX_SG_LIST;
7999 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008000#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008001 /*
8002 * Set sg_entry_cnt to be the number of SG elements that
8003 * will fit in the allocated SG queues. It is minus 1, because
8004 * the first SG element is handled above.
8005 */
8006 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008007#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008009#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008010 if (sg_entry_cnt != 0) {
8011 scsiq->q1.cntl |= QC_SG_HEAD;
8012 q_addr = ASC_QNO_TO_QADDR(q_no);
8013 sg_index = 1;
8014 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
8015 scsi_sg_q.sg_head_qp = q_no;
8016 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
8017 for (i = 0; i < sg_head->queue_cnt; i++) {
8018 scsi_sg_q.seq_no = i + 1;
8019 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
8020 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
8021 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8022 if (i == 0) {
8023 scsi_sg_q.sg_list_cnt =
8024 ASC_SG_LIST_PER_Q;
8025 scsi_sg_q.sg_cur_list_cnt =
8026 ASC_SG_LIST_PER_Q;
8027 } else {
8028 scsi_sg_q.sg_list_cnt =
8029 ASC_SG_LIST_PER_Q - 1;
8030 scsi_sg_q.sg_cur_list_cnt =
8031 ASC_SG_LIST_PER_Q - 1;
8032 }
8033 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008034#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008035 /*
8036 * This is the last SG queue in the list of
8037 * allocated SG queues. If there are more
8038 * SG elements than will fit in the allocated
8039 * queues, then set the QCSG_SG_XFER_MORE flag.
8040 */
8041 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
8042 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8043 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008044#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008045 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008046#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008048#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008049 sg_list_dwords = sg_entry_cnt << 1;
8050 if (i == 0) {
8051 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
8052 scsi_sg_q.sg_cur_list_cnt =
8053 sg_entry_cnt;
8054 } else {
8055 scsi_sg_q.sg_list_cnt =
8056 sg_entry_cnt - 1;
8057 scsi_sg_q.sg_cur_list_cnt =
8058 sg_entry_cnt - 1;
8059 }
8060 sg_entry_cnt = 0;
8061 }
8062 next_qp = AscReadLramByte(iop_base,
8063 (ushort)(q_addr +
8064 ASC_SCSIQ_B_FWD));
8065 scsi_sg_q.q_no = next_qp;
8066 q_addr = ASC_QNO_TO_QADDR(next_qp);
8067 AscMemWordCopyPtrToLram(iop_base,
8068 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8069 (uchar *)&scsi_sg_q,
8070 sizeof(ASC_SG_LIST_Q) >> 1);
8071 AscMemDWordCopyPtrToLram(iop_base,
8072 q_addr + ASC_SGQ_LIST_BEG,
8073 (uchar *)&sg_head->
8074 sg_list[sg_index],
8075 sg_list_dwords);
8076 sg_index += ASC_SG_LIST_PER_Q;
8077 scsiq->next_sg_index = sg_index;
8078 }
8079 } else {
8080 scsiq->q1.cntl &= ~QC_SG_HEAD;
8081 }
8082 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
8083 scsiq->q1.data_addr = saved_data_addr;
8084 scsiq->q1.data_cnt = saved_data_cnt;
8085 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008086}
8087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008088static int
8089AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008090{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008091 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008092
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008093 if (AscHostReqRiscHalt(iop_base)) {
8094 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8095 AscStartChip(iop_base);
8096 return (sta);
8097 }
8098 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008099}
8100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008101static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008102{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008103 ASC_SCSI_BIT_ID_TYPE org_id;
8104 int i;
8105 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008107 AscSetBank(iop_base, 1);
8108 org_id = AscReadChipDvcID(iop_base);
8109 for (i = 0; i <= ASC_MAX_TID; i++) {
8110 if (org_id == (0x01 << i))
8111 break;
8112 }
8113 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8114 AscWriteChipDvcID(iop_base, id);
8115 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8116 AscSetBank(iop_base, 0);
8117 AscSetChipSyn(iop_base, sdtr_data);
8118 if (AscGetChipSyn(iop_base) != sdtr_data) {
8119 sta = FALSE;
8120 }
8121 } else {
8122 sta = FALSE;
8123 }
8124 AscSetBank(iop_base, 1);
8125 AscWriteChipDvcID(iop_base, org_id);
8126 AscSetBank(iop_base, 0);
8127 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008128}
8129
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008130static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008131{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008132 uchar i;
8133 ushort s_addr;
8134 PortAddr iop_base;
8135 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008137 iop_base = asc_dvc->iop_base;
8138 warn_code = 0;
8139 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
8140 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
8141 64) >> 1)
8142 );
8143 i = ASC_MIN_ACTIVE_QNO;
8144 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
8145 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8146 (uchar)(i + 1));
8147 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8148 (uchar)(asc_dvc->max_total_qng));
8149 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8150 (uchar)i);
8151 i++;
8152 s_addr += ASC_QBLK_SIZE;
8153 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
8154 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8155 (uchar)(i + 1));
8156 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8157 (uchar)(i - 1));
8158 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8159 (uchar)i);
8160 }
8161 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8162 (uchar)ASC_QLINK_END);
8163 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8164 (uchar)(asc_dvc->max_total_qng - 1));
8165 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8166 (uchar)asc_dvc->max_total_qng);
8167 i++;
8168 s_addr += ASC_QBLK_SIZE;
8169 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
8170 i++, s_addr += ASC_QBLK_SIZE) {
8171 AscWriteLramByte(iop_base,
8172 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
8173 AscWriteLramByte(iop_base,
8174 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
8175 AscWriteLramByte(iop_base,
8176 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
8177 }
8178 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008179}
8180
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008181static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008182{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008183 PortAddr iop_base;
8184 int i;
8185 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008186
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008187 iop_base = asc_dvc->iop_base;
8188 AscPutRiscVarFreeQHead(iop_base, 1);
8189 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8190 AscPutVarFreeQHead(iop_base, 1);
8191 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8192 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
8193 (uchar)((int)asc_dvc->max_total_qng + 1));
8194 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
8195 (uchar)((int)asc_dvc->max_total_qng + 2));
8196 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
8197 asc_dvc->max_total_qng);
8198 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
8199 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8200 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
8201 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
8202 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
8203 AscPutQDoneInProgress(iop_base, 0);
8204 lram_addr = ASC_QADR_BEG;
8205 for (i = 0; i < 32; i++, lram_addr += 2) {
8206 AscWriteLramWord(iop_base, lram_addr, 0);
8207 }
8208 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008209}
8210
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008211static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008212{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008213 if (asc_dvc->err_code == 0) {
8214 asc_dvc->err_code = err_code;
8215 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8216 err_code);
8217 }
8218 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008219}
8220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008221static uchar
8222AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008223{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008224 EXT_MSG sdtr_buf;
8225 uchar sdtr_period_index;
8226 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008227
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008228 iop_base = asc_dvc->iop_base;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008229 sdtr_buf.msg_type = EXTENDED_MESSAGE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008230 sdtr_buf.msg_len = MS_SDTR_LEN;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008231 sdtr_buf.msg_req = EXTENDED_SDTR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008232 sdtr_buf.xfer_period = sdtr_period;
8233 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8234 sdtr_buf.req_ack_offset = sdtr_offset;
8235 if ((sdtr_period_index =
8236 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
8237 asc_dvc->max_sdtr_index) {
8238 AscMemWordCopyPtrToLram(iop_base,
8239 ASCV_MSGOUT_BEG,
8240 (uchar *)&sdtr_buf,
8241 sizeof(EXT_MSG) >> 1);
8242 return ((sdtr_period_index << 4) | sdtr_offset);
8243 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008245 sdtr_buf.req_ack_offset = 0;
8246 AscMemWordCopyPtrToLram(iop_base,
8247 ASCV_MSGOUT_BEG,
8248 (uchar *)&sdtr_buf,
8249 sizeof(EXT_MSG) >> 1);
8250 return (0);
8251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008252}
8253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008254static uchar
8255AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008256{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008257 uchar byte;
8258 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008259
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008260 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8261 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
8262 ) {
8263 return (0xFF);
8264 }
8265 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8266 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008267}
8268
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008269static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008270{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008271 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8272 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8273 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008274}
8275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008276static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008277{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008278 uchar *period_table;
8279 int max_index;
8280 int min_index;
8281 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008283 period_table = asc_dvc->sdtr_period_tbl;
8284 max_index = (int)asc_dvc->max_sdtr_index;
8285 min_index = (int)asc_dvc->host_init_sdtr_index;
8286 if ((syn_time <= period_table[max_index])) {
8287 for (i = min_index; i < (max_index - 1); i++) {
8288 if (syn_time <= period_table[i]) {
8289 return ((uchar)i);
8290 }
8291 }
8292 return ((uchar)max_index);
8293 } else {
8294 return ((uchar)(max_index + 1));
8295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008296}
8297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008298static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008299{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008300 ushort q_addr;
8301 uchar next_qp;
8302 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008303
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008304 q_addr = ASC_QNO_TO_QADDR(free_q_head);
8305 q_status = (uchar)AscReadLramByte(iop_base,
8306 (ushort)(q_addr +
8307 ASC_SCSIQ_B_STATUS));
8308 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
8309 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
8310 return (next_qp);
8311 }
8312 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008313}
8314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008315static uchar
8316AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008317{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008318 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008320 for (i = 0; i < n_free_q; i++) {
8321 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
8322 == ASC_QLINK_END) {
8323 return (ASC_QLINK_END);
8324 }
8325 }
8326 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008327}
8328
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008329static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008330{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008331 int count = 0;
8332 int sta = 0;
8333 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008334
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008335 if (AscIsChipHalted(iop_base))
8336 return (1);
8337 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
8338 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8339 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
8340 do {
8341 if (AscIsChipHalted(iop_base)) {
8342 sta = 1;
8343 break;
8344 }
8345 DvcSleepMilliSecond(100);
8346 } while (count++ < 20);
8347 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
8348 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008349}
8350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008351static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008352{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008353 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008354
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008355 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
8356 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8357 ASC_STOP_REQ_RISC_STOP);
8358 do {
8359 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
8360 ASC_STOP_ACK_RISC_STOP) {
8361 return (1);
8362 }
8363 DvcSleepMilliSecond(100);
8364 } while (count++ < 20);
8365 }
8366 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008367}
8368
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008369static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008370{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008371 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008372}
8373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008374static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008375{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008376 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008377}
8378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008379static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008380{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008381 AscSetChipControl(iop_base, 0);
8382 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8383 return (0);
8384 }
8385 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008386}
8387
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008388static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008389{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008390 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008392 cc_val =
8393 AscGetChipControl(iop_base) &
8394 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
8395 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
8396 AscSetChipIH(iop_base, INS_HALT);
8397 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8398 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
8399 return (0);
8400 }
8401 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008402}
8403
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008404static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008405{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008406 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8407 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
8408 return (1);
8409 }
8410 }
8411 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008412}
8413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008414static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008415{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008416 AscSetBank(iop_base, 1);
8417 AscWriteChipIH(iop_base, ins_code);
8418 AscSetBank(iop_base, 0);
8419 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008420}
8421
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008422static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008423{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008424 uchar host_flag;
8425 uchar risc_flag;
8426 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008428 loop = 0;
8429 do {
8430 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8431 if (loop++ > 0x7FFF) {
8432 break;
8433 }
8434 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8435 host_flag =
8436 AscReadLramByte(iop_base,
8437 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8438 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8439 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8440 AscSetChipStatus(iop_base, CIW_INT_ACK);
8441 loop = 0;
8442 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8443 AscSetChipStatus(iop_base, CIW_INT_ACK);
8444 if (loop++ > 3) {
8445 break;
8446 }
8447 }
8448 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8449 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008450}
8451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008452static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008453{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008454 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008455
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008456 cfg = AscGetChipCfgLsw(iop_base);
8457 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
8458 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008459}
8460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008461static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008462{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008463 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008464
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008465 cfg = AscGetChipCfgLsw(iop_base);
8466 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
8467 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008468}
8469
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008470static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008471{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008472 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008473
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008474 val = AscGetChipControl(iop_base) &
8475 (~
8476 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
8477 CC_CHIP_RESET));
8478 if (bank == 1) {
8479 val |= CC_BANK_ONE;
8480 } else if (bank == 2) {
8481 val |= CC_DIAG | CC_BANK_ONE;
8482 } else {
8483 val &= ~CC_BANK_ONE;
8484 }
8485 AscSetChipControl(iop_base, val);
8486 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008487}
8488
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008489static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008490{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008491 PortAddr iop_base;
8492 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008493
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008494 iop_base = asc_dvc->iop_base;
8495 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
8496 && (i-- > 0)) {
8497 DvcSleepMilliSecond(100);
8498 }
8499 AscStopChip(iop_base);
8500 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
8501 DvcDelayNanoSecond(asc_dvc, 60000);
8502 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8503 AscSetChipIH(iop_base, INS_HALT);
8504 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
8505 AscSetChipControl(iop_base, CC_HALT);
8506 DvcSleepMilliSecond(200);
8507 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
8508 AscSetChipStatus(iop_base, 0);
8509 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008510}
8511
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008512static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008513{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008514 if (bus_type & ASC_IS_ISA)
8515 return (ASC_MAX_ISA_DMA_COUNT);
8516 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
8517 return (ASC_MAX_VL_DMA_COUNT);
8518 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008519}
8520
8521#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008522static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008523{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008524 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008525
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008526 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
8527 if (channel == 0x03)
8528 return (0);
8529 else if (channel == 0x00)
8530 return (7);
8531 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008532}
8533
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008534static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008535{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008536 ushort cfg_lsw;
8537 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008538
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008539 if ((dma_channel >= 5) && (dma_channel <= 7)) {
8540 if (dma_channel == 7)
8541 value = 0x00;
8542 else
8543 value = dma_channel - 4;
8544 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
8545 cfg_lsw |= value;
8546 AscSetChipCfgLsw(iop_base, cfg_lsw);
8547 return (AscGetIsaDmaChannel(iop_base));
8548 }
8549 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008550}
8551
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008552static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008553{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008554 speed_value &= 0x07;
8555 AscSetBank(iop_base, 1);
8556 AscWriteChipDmaSpeed(iop_base, speed_value);
8557 AscSetBank(iop_base, 0);
8558 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008559}
8560
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008561static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008562{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008563 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008564
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008565 AscSetBank(iop_base, 1);
8566 speed_value = AscReadChipDmaSpeed(iop_base);
8567 speed_value &= 0x07;
8568 AscSetBank(iop_base, 0);
8569 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008570}
8571#endif /* CONFIG_ISA */
8572
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008573static int __devinit AscInitGetConfig(asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008574{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008575 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008576 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008577
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008578 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008579 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008580 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008581
Matthew Wilcox9649af32007-07-26 21:51:47 -06008582 if (AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008583 warn_code |= AscInitAscDvcVar(asc_dvc);
8584 warn_code |= AscInitFromEEP(asc_dvc);
8585 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06008586 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008587 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008588 } else {
8589 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8590 }
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008591
8592 switch (warn_code) {
8593 case 0: /* No error */
8594 break;
8595 case ASC_WARN_IO_PORT_ROTATE:
8596 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
8597 "modified\n", boardp->id);
8598 break;
8599 case ASC_WARN_AUTO_CONFIG:
8600 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
8601 "switch enabled\n", boardp->id);
8602 break;
8603 case ASC_WARN_EEPROM_CHKSUM:
8604 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
8605 "error\n", boardp->id);
8606 break;
8607 case ASC_WARN_IRQ_MODIFIED:
8608 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
8609 boardp->id);
8610 break;
8611 case ASC_WARN_CMD_QNG_CONFLICT:
8612 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
8613 "w/o disconnects\n", boardp->id);
8614 break;
8615 default:
8616 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
8617 "0x%x\n", boardp->id, warn_code);
8618 break;
8619 }
8620
8621 if (asc_dvc->err_code != 0) {
8622 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
8623 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8624 asc_dvc->err_code);
8625 }
8626
8627 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008628}
8629
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008630static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008631{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008632 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008633 PortAddr iop_base = asc_dvc->iop_base;
8634 unsigned short cfg_msw;
8635 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008636
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008637 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
8638 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008639 return asc_dvc->err_code;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008640 if (!AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008641 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008642 return asc_dvc->err_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008644
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008645 cfg_msw = AscGetChipCfgMsw(iop_base);
8646 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008647 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008648 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8649 AscSetChipCfgMsw(iop_base, cfg_msw);
8650 }
8651 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
8652 asc_dvc->cfg->cmd_qng_enabled) {
8653 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
8654 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
8655 }
8656 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8657 warn_code |= ASC_WARN_AUTO_CONFIG;
8658 }
8659 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
8660 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
8661 != asc_dvc->irq_no) {
8662 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
8663 }
8664 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008665#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008666 if (asc_dvc->bus_type & ASC_IS_PCI) {
8667 cfg_msw &= 0xFFC0;
8668 AscSetChipCfgMsw(iop_base, cfg_msw);
8669 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
8670 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -06008671 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
8672 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008673 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
8674 asc_dvc->bug_fix_cntl |=
8675 ASC_BUG_FIX_ASYN_USE_SYN;
8676 }
8677 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008678 } else
8679#endif /* CONFIG_PCI */
8680 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008681 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
8682 == ASC_CHIP_VER_ASYN_BUG) {
8683 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
8684 }
8685 }
8686 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
8687 asc_dvc->cfg->chip_scsi_id) {
8688 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
8689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008690#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008691 if (asc_dvc->bus_type & ASC_IS_ISA) {
8692 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
8693 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
8694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008695#endif /* CONFIG_ISA */
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008696
8697 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008698
8699 switch (warn_code) {
8700 case 0: /* No error. */
8701 break;
8702 case ASC_WARN_IO_PORT_ROTATE:
8703 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
8704 "modified\n", boardp->id);
8705 break;
8706 case ASC_WARN_AUTO_CONFIG:
8707 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
8708 "switch enabled\n", boardp->id);
8709 break;
8710 case ASC_WARN_EEPROM_CHKSUM:
8711 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
8712 "error\n", boardp->id);
8713 break;
8714 case ASC_WARN_IRQ_MODIFIED:
8715 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
8716 boardp->id);
8717 break;
8718 case ASC_WARN_CMD_QNG_CONFLICT:
8719 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
8720 "disconnects\n",
8721 boardp->id);
8722 break;
8723 default:
8724 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
8725 "0x%x\n", boardp->id, warn_code);
8726 break;
8727 }
8728
8729 if (asc_dvc->err_code != 0) {
8730 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
8731 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8732 asc_dvc->err_code);
8733 }
8734
8735 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008736}
8737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008738static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008739{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008740 ushort warn_code;
8741 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008742
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008743 iop_base = asc_dvc->iop_base;
8744 warn_code = 0;
8745 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
8746 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
8747 AscResetChipAndScsiBus(asc_dvc);
8748 DvcSleepMilliSecond((ASC_DCNT)
8749 ((ushort)asc_dvc->scsi_reset_wait * 1000));
8750 }
8751 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
8752 if (asc_dvc->err_code != 0)
8753 return (UW_ERR);
8754 if (!AscFindSignature(asc_dvc->iop_base)) {
8755 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8756 return (warn_code);
8757 }
8758 AscDisableInterrupt(iop_base);
8759 warn_code |= AscInitLram(asc_dvc);
8760 if (asc_dvc->err_code != 0)
8761 return (UW_ERR);
8762 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
8763 (ulong)_asc_mcode_chksum);
8764 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
8765 _asc_mcode_size) != _asc_mcode_chksum) {
8766 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
8767 return (warn_code);
8768 }
8769 warn_code |= AscInitMicroCodeVar(asc_dvc);
8770 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
8771 AscEnableInterrupt(iop_base);
8772 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008773}
8774
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008775static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008776{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008777 int i;
8778 PortAddr iop_base;
8779 ushort warn_code;
8780 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008781
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008782 iop_base = asc_dvc->iop_base;
8783 warn_code = 0;
8784 asc_dvc->err_code = 0;
8785 if ((asc_dvc->bus_type &
8786 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
8787 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
8788 }
8789 AscSetChipControl(iop_base, CC_HALT);
8790 AscSetChipStatus(iop_base, 0);
8791 asc_dvc->bug_fix_cntl = 0;
8792 asc_dvc->pci_fix_asyn_xfer = 0;
8793 asc_dvc->pci_fix_asyn_xfer_always = 0;
8794 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
8795 asc_dvc->sdtr_done = 0;
8796 asc_dvc->cur_total_qng = 0;
8797 asc_dvc->is_in_int = 0;
8798 asc_dvc->in_critical_cnt = 0;
8799 asc_dvc->last_q_shortage = 0;
8800 asc_dvc->use_tagged_qng = 0;
8801 asc_dvc->no_scam = 0;
8802 asc_dvc->unit_not_ready = 0;
8803 asc_dvc->queue_full_or_busy = 0;
8804 asc_dvc->redo_scam = 0;
8805 asc_dvc->res2 = 0;
8806 asc_dvc->host_init_sdtr_index = 0;
8807 asc_dvc->cfg->can_tagged_qng = 0;
8808 asc_dvc->cfg->cmd_qng_enabled = 0;
8809 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
8810 asc_dvc->init_sdtr = 0;
8811 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
8812 asc_dvc->scsi_reset_wait = 3;
8813 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
8814 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
8815 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
8816 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
8817 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
8818 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
8819 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
8820 ASC_LIB_VERSION_MINOR;
8821 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
8822 asc_dvc->cfg->chip_version = chip_version;
8823 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
8824 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
8825 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
8826 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
8827 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
8828 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
8829 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
8830 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
8831 asc_dvc->max_sdtr_index = 7;
8832 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
8833 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
8834 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
8835 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
8836 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
8837 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
8838 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
8839 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
8840 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
8841 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
8842 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
8843 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
8844 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
8845 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
8846 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
8847 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
8848 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
8849 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
8850 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
8851 asc_dvc->max_sdtr_index = 15;
8852 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
8853 AscSetExtraControl(iop_base,
8854 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8855 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
8856 AscSetExtraControl(iop_base,
8857 (SEC_ACTIVE_NEGATE |
8858 SEC_ENABLE_FILTER));
8859 }
8860 }
8861 if (asc_dvc->bus_type == ASC_IS_PCI) {
8862 AscSetExtraControl(iop_base,
8863 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008866 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008867#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008868 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
Matthew Wilcox59fcf842007-07-26 11:54:15 -04008869 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
8870 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
8871 asc_dvc->bus_type = ASC_IS_ISAPNP;
8872 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008873 asc_dvc->cfg->isa_dma_channel =
8874 (uchar)AscGetIsaDmaChannel(iop_base);
8875 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008876#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008877 for (i = 0; i <= ASC_MAX_TID; i++) {
8878 asc_dvc->cur_dvc_qng[i] = 0;
8879 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
8880 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
8881 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
8882 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
8883 }
8884 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008885}
8886
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008887static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008888{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008889 ASCEEP_CONFIG eep_config_buf;
8890 ASCEEP_CONFIG *eep_config;
8891 PortAddr iop_base;
8892 ushort chksum;
8893 ushort warn_code;
8894 ushort cfg_msw, cfg_lsw;
8895 int i;
8896 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008897
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008898 iop_base = asc_dvc->iop_base;
8899 warn_code = 0;
8900 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
8901 AscStopQueueExe(iop_base);
8902 if ((AscStopChip(iop_base) == FALSE) ||
8903 (AscGetChipScsiCtrl(iop_base) != 0)) {
8904 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
8905 AscResetChipAndScsiBus(asc_dvc);
8906 DvcSleepMilliSecond((ASC_DCNT)
8907 ((ushort)asc_dvc->scsi_reset_wait * 1000));
8908 }
8909 if (AscIsChipHalted(iop_base) == FALSE) {
8910 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8911 return (warn_code);
8912 }
8913 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8914 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8915 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8916 return (warn_code);
8917 }
8918 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
8919 cfg_msw = AscGetChipCfgMsw(iop_base);
8920 cfg_lsw = AscGetChipCfgLsw(iop_base);
8921 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008922 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008923 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8924 AscSetChipCfgMsw(iop_base, cfg_msw);
8925 }
8926 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
8927 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
8928 if (chksum == 0) {
8929 chksum = 0xaa55;
8930 }
8931 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8932 warn_code |= ASC_WARN_AUTO_CONFIG;
8933 if (asc_dvc->cfg->chip_version == 3) {
8934 if (eep_config->cfg_lsw != cfg_lsw) {
8935 warn_code |= ASC_WARN_EEPROM_RECOVER;
8936 eep_config->cfg_lsw =
8937 AscGetChipCfgLsw(iop_base);
8938 }
8939 if (eep_config->cfg_msw != cfg_msw) {
8940 warn_code |= ASC_WARN_EEPROM_RECOVER;
8941 eep_config->cfg_msw =
8942 AscGetChipCfgMsw(iop_base);
8943 }
8944 }
8945 }
8946 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
8947 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
8948 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
8949 eep_config->chksum);
8950 if (chksum != eep_config->chksum) {
8951 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
8952 ASC_CHIP_VER_PCI_ULTRA_3050) {
8953 ASC_DBG(1,
8954 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
8955 eep_config->init_sdtr = 0xFF;
8956 eep_config->disc_enable = 0xFF;
8957 eep_config->start_motor = 0xFF;
8958 eep_config->use_cmd_qng = 0;
8959 eep_config->max_total_qng = 0xF0;
8960 eep_config->max_tag_qng = 0x20;
8961 eep_config->cntl = 0xBFFF;
8962 ASC_EEP_SET_CHIP_ID(eep_config, 7);
8963 eep_config->no_scam = 0;
8964 eep_config->adapter_info[0] = 0;
8965 eep_config->adapter_info[1] = 0;
8966 eep_config->adapter_info[2] = 0;
8967 eep_config->adapter_info[3] = 0;
8968 eep_config->adapter_info[4] = 0;
8969 /* Indicate EEPROM-less board. */
8970 eep_config->adapter_info[5] = 0xBB;
8971 } else {
8972 ASC_PRINT
8973 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
8974 write_eep = 1;
8975 warn_code |= ASC_WARN_EEPROM_CHKSUM;
8976 }
8977 }
8978 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
8979 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
8980 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
8981 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
8982 asc_dvc->start_motor = eep_config->start_motor;
8983 asc_dvc->dvc_cntl = eep_config->cntl;
8984 asc_dvc->no_scam = eep_config->no_scam;
8985 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
8986 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
8987 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
8988 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
8989 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
8990 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
8991 if (!AscTestExternalLram(asc_dvc)) {
8992 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
8993 ASC_IS_PCI_ULTRA)) {
8994 eep_config->max_total_qng =
8995 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
8996 eep_config->max_tag_qng =
8997 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
8998 } else {
8999 eep_config->cfg_msw |= 0x0800;
9000 cfg_msw |= 0x0800;
9001 AscSetChipCfgMsw(iop_base, cfg_msw);
9002 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
9003 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
9004 }
9005 } else {
9006 }
9007 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
9008 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
9009 }
9010 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
9011 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
9012 }
9013 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
9014 eep_config->max_tag_qng = eep_config->max_total_qng;
9015 }
9016 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
9017 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
9018 }
9019 asc_dvc->max_total_qng = eep_config->max_total_qng;
9020 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
9021 eep_config->use_cmd_qng) {
9022 eep_config->disc_enable = eep_config->use_cmd_qng;
9023 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
9024 }
9025 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
9026 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
9027 }
9028 ASC_EEP_SET_CHIP_ID(eep_config,
9029 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
9030 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
9031 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
9032 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
9033 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
9034 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009035
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009036 for (i = 0; i <= ASC_MAX_TID; i++) {
9037 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
9038 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
9039 asc_dvc->cfg->sdtr_period_offset[i] =
9040 (uchar)(ASC_DEF_SDTR_OFFSET |
9041 (asc_dvc->host_init_sdtr_index << 4));
9042 }
9043 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
9044 if (write_eep) {
9045 if ((i =
9046 AscSetEEPConfig(iop_base, eep_config,
9047 asc_dvc->bus_type)) != 0) {
9048 ASC_PRINT1
9049 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
9050 i);
9051 } else {
9052 ASC_PRINT
9053 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
9054 }
9055 }
9056 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009057}
9058
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009059static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009060{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009061 int i;
9062 ushort warn_code;
9063 PortAddr iop_base;
9064 ASC_PADDR phy_addr;
9065 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009067 iop_base = asc_dvc->iop_base;
9068 warn_code = 0;
9069 for (i = 0; i <= ASC_MAX_TID; i++) {
9070 AscPutMCodeInitSDTRAtID(iop_base, i,
9071 asc_dvc->cfg->sdtr_period_offset[i]
9072 );
9073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009075 AscInitQLinkVar(asc_dvc);
9076 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
9077 asc_dvc->cfg->disc_enable);
9078 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
9079 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009081 /* Align overrun buffer on an 8 byte boundary. */
9082 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
9083 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
9084 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
9085 (uchar *)&phy_addr, 1);
9086 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
9087 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
9088 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009089
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009090 asc_dvc->cfg->mcode_date =
9091 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
9092 asc_dvc->cfg->mcode_version =
9093 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009095 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
9096 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
9097 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
9098 return (warn_code);
9099 }
9100 if (AscStartChip(iop_base) != 1) {
9101 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
9102 return (warn_code);
9103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009105 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009106}
9107
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009108static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009109{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009110 PortAddr iop_base;
9111 ushort q_addr;
9112 ushort saved_word;
9113 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009115 iop_base = asc_dvc->iop_base;
9116 sta = 0;
9117 q_addr = ASC_QNO_TO_QADDR(241);
9118 saved_word = AscReadLramWord(iop_base, q_addr);
9119 AscSetChipLramAddr(iop_base, q_addr);
9120 AscSetChipLramData(iop_base, 0x55AA);
9121 DvcSleepMilliSecond(10);
9122 AscSetChipLramAddr(iop_base, q_addr);
9123 if (AscGetChipLramData(iop_base) == 0x55AA) {
9124 sta = 1;
9125 AscWriteLramWord(iop_base, q_addr, saved_word);
9126 }
9127 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009128}
9129
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009130static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009131{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009132 uchar read_back;
9133 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009135 retry = 0;
9136 while (TRUE) {
9137 AscSetChipEEPCmd(iop_base, cmd_reg);
9138 DvcSleepMilliSecond(1);
9139 read_back = AscGetChipEEPCmd(iop_base);
9140 if (read_back == cmd_reg) {
9141 return (1);
9142 }
9143 if (retry++ > ASC_EEP_MAX_RETRY) {
9144 return (0);
9145 }
9146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009147}
9148
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009149static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009150{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009151 ushort read_back;
9152 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009154 retry = 0;
9155 while (TRUE) {
9156 AscSetChipEEPData(iop_base, data_reg);
9157 DvcSleepMilliSecond(1);
9158 read_back = AscGetChipEEPData(iop_base);
9159 if (read_back == data_reg) {
9160 return (1);
9161 }
9162 if (retry++ > ASC_EEP_MAX_RETRY) {
9163 return (0);
9164 }
9165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009166}
9167
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009168static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009169{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009170 DvcSleepMilliSecond(1);
9171 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009172}
9173
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009174static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009175{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009176 DvcSleepMilliSecond(20);
9177 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009178}
9179
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009180static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009181{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009182 ushort read_wval;
9183 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009185 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9186 AscWaitEEPRead();
9187 cmd_reg = addr | ASC_EEP_CMD_READ;
9188 AscWriteEEPCmdReg(iop_base, cmd_reg);
9189 AscWaitEEPRead();
9190 read_wval = AscGetChipEEPData(iop_base);
9191 AscWaitEEPRead();
9192 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009193}
9194
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009195static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009196AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009197{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009198 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009200 read_wval = AscReadEEPWord(iop_base, addr);
9201 if (read_wval != word_val) {
9202 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
9203 AscWaitEEPRead();
9204 AscWriteEEPDataReg(iop_base, word_val);
9205 AscWaitEEPRead();
9206 AscWriteEEPCmdReg(iop_base,
9207 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
9208 AscWaitEEPWrite();
9209 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9210 AscWaitEEPRead();
9211 return (AscReadEEPWord(iop_base, addr));
9212 }
9213 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009214}
9215
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009216static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009217AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009218{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009219 ushort wval;
9220 ushort sum;
9221 ushort *wbuf;
9222 int cfg_beg;
9223 int cfg_end;
9224 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
9225 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009226
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009227 wbuf = (ushort *)cfg_buf;
9228 sum = 0;
9229 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
9230 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9231 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9232 sum += *wbuf;
9233 }
9234 if (bus_type & ASC_IS_VL) {
9235 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9236 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9237 } else {
9238 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9239 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9240 }
9241 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9242 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
9243 if (s_addr <= uchar_end_in_config) {
9244 /*
9245 * Swap all char fields - must unswap bytes already swapped
9246 * by AscReadEEPWord().
9247 */
9248 *wbuf = le16_to_cpu(wval);
9249 } else {
9250 /* Don't swap word field at the end - cntl field. */
9251 *wbuf = wval;
9252 }
9253 sum += wval; /* Checksum treats all EEPROM data as words. */
9254 }
9255 /*
9256 * Read the checksum word which will be compared against 'sum'
9257 * by the caller. Word field already swapped.
9258 */
9259 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9260 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009261}
9262
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009263static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009264AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009265{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009266 int n_error;
9267 ushort *wbuf;
9268 ushort word;
9269 ushort sum;
9270 int s_addr;
9271 int cfg_beg;
9272 int cfg_end;
9273 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009275 wbuf = (ushort *)cfg_buf;
9276 n_error = 0;
9277 sum = 0;
9278 /* Write two config words; AscWriteEEPWord() will swap bytes. */
9279 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9280 sum += *wbuf;
9281 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9282 n_error++;
9283 }
9284 }
9285 if (bus_type & ASC_IS_VL) {
9286 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9287 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9288 } else {
9289 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9290 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9291 }
9292 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9293 if (s_addr <= uchar_end_in_config) {
9294 /*
9295 * This is a char field. Swap char fields before they are
9296 * swapped again by AscWriteEEPWord().
9297 */
9298 word = cpu_to_le16(*wbuf);
9299 if (word !=
9300 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
9301 n_error++;
9302 }
9303 } else {
9304 /* Don't swap word field at the end - cntl field. */
9305 if (*wbuf !=
9306 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9307 n_error++;
9308 }
9309 }
9310 sum += *wbuf; /* Checksum calculated from word values. */
9311 }
9312 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
9313 *wbuf = sum;
9314 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
9315 n_error++;
9316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009318 /* Read EEPROM back again. */
9319 wbuf = (ushort *)cfg_buf;
9320 /*
9321 * Read two config words; Byte-swapping done by AscReadEEPWord().
9322 */
9323 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9324 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
9325 n_error++;
9326 }
9327 }
9328 if (bus_type & ASC_IS_VL) {
9329 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9330 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9331 } else {
9332 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9333 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9334 }
9335 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9336 if (s_addr <= uchar_end_in_config) {
9337 /*
9338 * Swap all char fields. Must unswap bytes already swapped
9339 * by AscReadEEPWord().
9340 */
9341 word =
9342 le16_to_cpu(AscReadEEPWord
9343 (iop_base, (uchar)s_addr));
9344 } else {
9345 /* Don't swap word field at the end - cntl field. */
9346 word = AscReadEEPWord(iop_base, (uchar)s_addr);
9347 }
9348 if (*wbuf != word) {
9349 n_error++;
9350 }
9351 }
9352 /* Read checksum; Byte swapping not needed. */
9353 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
9354 n_error++;
9355 }
9356 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009357}
9358
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009359static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009360AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009361{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009362 int retry;
9363 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009364
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009365 retry = 0;
9366 while (TRUE) {
9367 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
9368 bus_type)) == 0) {
9369 break;
9370 }
9371 if (++retry > ASC_EEP_MAX_RETRY) {
9372 break;
9373 }
9374 }
9375 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009376}
9377
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009378static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009379{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009380 char type = sdev->type;
9381 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009382
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009383 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
9384 if (!(asc_dvc->init_sdtr & tid_bits)) {
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009385 if ((type == TYPE_ROM) &&
9386 (strncmp(sdev->vendor, "HP ", 3) == 0)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009387 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9388 }
9389 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009390 if ((type == TYPE_PROCESSOR) ||
9391 (type == TYPE_SCANNER) || (type == TYPE_ROM) ||
9392 (type == TYPE_TAPE)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009393 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009395
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009396 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
9397 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009398 sdev->id,
9399 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009400 }
9401 }
9402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009403}
9404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009405static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009406{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009407 uchar byte_data;
9408 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009409
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009410 if (isodd_word(addr)) {
9411 AscSetChipLramAddr(iop_base, addr - 1);
9412 word_data = AscGetChipLramData(iop_base);
9413 byte_data = (uchar)((word_data >> 8) & 0xFF);
9414 } else {
9415 AscSetChipLramAddr(iop_base, addr);
9416 word_data = AscGetChipLramData(iop_base);
9417 byte_data = (uchar)(word_data & 0xFF);
9418 }
9419 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420}
Linus Torvalds1da177e2005-04-16 15:20:36 -07009421
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009422static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
9423{
9424 ushort word_data;
9425
9426 AscSetChipLramAddr(iop_base, addr);
9427 word_data = AscGetChipLramData(iop_base);
9428 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009429}
9430
9431#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009432static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009433{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009434 ushort val_low, val_high;
9435 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009436
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009437 AscSetChipLramAddr(iop_base, addr);
9438 val_low = AscGetChipLramData(iop_base);
9439 val_high = AscGetChipLramData(iop_base);
9440 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
9441 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009442}
9443#endif /* CC_VERY_LONG_SG_LIST */
9444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009445static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009446{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009447 AscSetChipLramAddr(iop_base, addr);
9448 AscSetChipLramData(iop_base, word_val);
9449 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009450}
9451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009452static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009453{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009454 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009455
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009456 if (isodd_word(addr)) {
9457 addr--;
9458 word_data = AscReadLramWord(iop_base, addr);
9459 word_data &= 0x00FF;
9460 word_data |= (((ushort)byte_val << 8) & 0xFF00);
9461 } else {
9462 word_data = AscReadLramWord(iop_base, addr);
9463 word_data &= 0xFF00;
9464 word_data |= ((ushort)byte_val & 0x00FF);
9465 }
9466 AscWriteLramWord(iop_base, addr, word_data);
9467 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009468}
9469
9470/*
9471 * Copy 2 bytes to LRAM.
9472 *
9473 * The source data is assumed to be in little-endian order in memory
9474 * and is maintained in little-endian order when written to LRAM.
9475 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009476static void
9477AscMemWordCopyPtrToLram(PortAddr iop_base,
9478 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009479{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009480 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009481
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009482 AscSetChipLramAddr(iop_base, s_addr);
9483 for (i = 0; i < 2 * words; i += 2) {
9484 /*
9485 * On a little-endian system the second argument below
9486 * produces a little-endian ushort which is written to
9487 * LRAM in little-endian order. On a big-endian system
9488 * the second argument produces a big-endian ushort which
9489 * is "transparently" byte-swapped by outpw() and written
9490 * in little-endian order to LRAM.
9491 */
9492 outpw(iop_base + IOP_RAM_DATA,
9493 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
9494 }
9495 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009496}
9497
9498/*
9499 * Copy 4 bytes to LRAM.
9500 *
9501 * The source data is assumed to be in little-endian order in memory
9502 * and is maintained in little-endian order when writen to LRAM.
9503 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009504static void
9505AscMemDWordCopyPtrToLram(PortAddr iop_base,
9506 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009507{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009508 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009509
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009510 AscSetChipLramAddr(iop_base, s_addr);
9511 for (i = 0; i < 4 * dwords; i += 4) {
9512 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
9513 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
9514 }
9515 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009516}
9517
9518/*
9519 * Copy 2 bytes from LRAM.
9520 *
9521 * The source data is assumed to be in little-endian order in LRAM
9522 * and is maintained in little-endian order when written to memory.
9523 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009524static void
9525AscMemWordCopyPtrFromLram(PortAddr iop_base,
9526 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009527{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009528 int i;
9529 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009530
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009531 AscSetChipLramAddr(iop_base, s_addr);
9532 for (i = 0; i < 2 * words; i += 2) {
9533 word = inpw(iop_base + IOP_RAM_DATA);
9534 d_buffer[i] = word & 0xff;
9535 d_buffer[i + 1] = (word >> 8) & 0xff;
9536 }
9537 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009538}
9539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009540static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009541{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009542 ASC_DCNT sum;
9543 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009545 sum = 0L;
9546 for (i = 0; i < words; i++, s_addr += 2) {
9547 sum += AscReadLramWord(iop_base, s_addr);
9548 }
9549 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009550}
9551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009552static void
9553AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009554{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009555 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009557 AscSetChipLramAddr(iop_base, s_addr);
9558 for (i = 0; i < words; i++) {
9559 AscSetChipLramData(iop_base, set_wval);
9560 }
9561 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009562}
9563
Linus Torvalds1da177e2005-04-16 15:20:36 -07009564/*
9565 * --- Adv Library Functions
9566 */
9567
9568/* a_mcode.h */
9569
9570/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009571static unsigned char _adv_asc3550_buf[] = {
9572 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009573 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
9574 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
9575 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009576 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009577 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
9578 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
9579 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009580 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009581 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
9582 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
9583 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009584 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009585 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
9586 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
9587 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009588 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009589 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
9590 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
9591 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009592 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009593 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
9594 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
9595 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009596 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009597 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
9598 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
9599 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009600 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009601 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
9602 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
9603 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009604 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009605 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
9606 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
9607 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009608 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009609 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
9610 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
9611 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009612 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009613 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
9614 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
9615 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009616 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009617 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
9618 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
9619 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009620 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009621 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
9622 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
9623 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009624 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009625 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
9626 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
9627 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009628 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009629 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
9630 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
9631 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009632 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009633 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
9634 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
9635 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009636 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009637 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
9638 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
9639 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009640 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009641 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
9642 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
9643 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009644 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009645 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
9646 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
9647 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009648 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009649 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
9650 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
9651 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009652 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009653 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
9654 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
9655 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009656 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009657 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
9658 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
9659 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009660 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009661 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
9662 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
9663 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009664 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009665 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
9666 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
9667 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009668 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009669 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
9670 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
9671 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009672 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009673 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
9674 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
9675 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009676 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009677 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
9678 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
9679 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009680 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009681 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
9682 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
9683 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009684 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009685 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
9686 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
9687 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009688 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009689 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
9690 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
9691 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009692 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009693 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
9694 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
9695 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009696 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009697 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
9698 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
9699 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009700 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009701 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
9702 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
9703 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009704 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009705 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
9706 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
9707 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009708 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009709 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
9710 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
9711 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009712 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009713 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
9714 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
9715 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009716 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009717 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
9718 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
9719 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009720 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009721 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
9722 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
9723 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009724 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009725 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
9726 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
9727 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009728 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009729 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
9730 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
9731 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009732 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009733 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
9734 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
9735 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009736 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009737 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
9738 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
9739 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009740 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009741 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
9742 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
9743 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009744 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009745 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
9746 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
9747 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009748 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009749 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
9750 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
9751 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009752 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009753 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
9754 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
9755 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009756 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009757 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
9758 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
9759 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009760 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009761 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
9762 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
9763 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009764 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009765 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
9766 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
9767 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009768 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009769 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
9770 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
9771 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009772 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009773 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
9774 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
9775 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009776 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009777 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
9778 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
9779 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009780 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009781 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
9782 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
9783 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009784 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009785 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
9786 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
9787 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009788 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009789 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
9790 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
9791 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009792 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009793 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
9794 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
9795 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009796 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009797 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
9798 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
9799 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009800 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009801 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
9802 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
9803 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009804 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009805 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
9806 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
9807 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009808 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009809 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
9810 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
9811 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009812 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009813 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
9814 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
9815 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009816 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009817 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
9818 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
9819 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009820 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009821 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
9822 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
9823 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009824 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009825 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
9826 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
9827 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009828 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009829 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
9830 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
9831 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009832 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009833 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
9834 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
9835 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009836 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009837 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
9838 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
9839 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009840 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009841 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
9842 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
9843 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009844 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009845 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
9846 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
9847 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009848 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009849 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
9850 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
9851 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009852 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009853 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
9854 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
9855 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009856 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009857 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
9858 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
9859 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009860 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009861 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
9862 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
9863 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009864 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009865 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
9866 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
9867 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009868 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009869 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
9870 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
9871 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009872 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009873 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
9874 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
9875 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009876 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009877 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
9878 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
9879 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009880 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009881 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
9882 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
9883 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009884 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009885 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
9886 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
9887 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009888 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009889 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
9890 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
9891 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009892 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009893 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
9894 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
9895 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009896 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009897 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
9898 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
9899 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009900 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009901 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
9902 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
9903 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009904 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009905 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
9906 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
9907 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009908 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009909 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
9910 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
9911 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009912 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009913 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
9914 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
9915 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009916 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009917 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
9918 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
9919 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009920 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009921 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
9922 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
9923 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009924 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009925 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
9926 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
9927 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009928 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009929 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
9930 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
9931 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009932 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009933 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
9934 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
9935 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009936 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009937 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
9938 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
9939 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009940 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009941 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
9942 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
9943 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009944 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009945 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
9946 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
9947 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009948 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009949 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
9950 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
9951 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009952 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009953 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
9954 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
9955 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009956 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009957 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
9958 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
9959 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009960 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009961 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
9962 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
9963 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009964 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009965 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
9966 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
9967 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009968 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009969 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
9970 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
9971 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009972 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009973 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
9974 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
9975 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009976 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009977 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
9978 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
9979 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009980 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009981 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
9982 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
9983 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009984 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009985 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
9986 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
9987 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009988 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009989 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
9990 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009991};
9992
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009993static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
9994static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009995
9996/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009997static unsigned char _adv_asc38C0800_buf[] = {
9998 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009999 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
10000 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
10001 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010002 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010003 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
10004 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
10005 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010006 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010007 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
10008 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
10009 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010010 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010011 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
10012 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
10013 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010014 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010015 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
10016 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
10017 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010018 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010019 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
10020 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
10021 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010022 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010023 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
10024 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
10025 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010026 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010027 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
10028 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
10029 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010030 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010031 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
10032 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
10033 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010034 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010035 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
10036 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
10037 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010038 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010039 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
10040 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
10041 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010042 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010043 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
10044 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10045 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010046 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010047 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
10048 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
10049 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010050 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010051 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
10052 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
10053 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010054 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010055 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
10056 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
10057 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010058 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010059 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
10060 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
10061 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010062 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010063 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
10064 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
10065 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010066 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010067 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
10068 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
10069 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010070 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010071 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
10072 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
10073 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010074 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010075 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
10076 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
10077 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010078 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010079 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
10080 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
10081 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010082 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010083 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
10084 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
10085 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010086 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010087 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
10088 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
10089 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010090 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010091 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
10092 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
10093 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010094 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010095 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
10096 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
10097 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010098 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010099 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
10100 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
10101 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010102 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010103 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
10104 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
10105 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010106 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010107 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
10108 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
10109 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010110 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010111 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
10112 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
10113 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010114 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010115 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
10116 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
10117 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010118 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010119 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
10120 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
10121 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010122 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010123 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
10124 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
10125 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010126 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010127 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
10128 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
10129 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010130 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010131 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
10132 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
10133 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010134 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010135 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
10136 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
10137 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010138 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010139 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
10140 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
10141 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010142 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010143 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
10144 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
10145 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010146 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010147 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
10148 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
10149 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010150 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010151 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
10152 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
10153 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010154 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010155 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
10156 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
10157 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010158 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010159 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
10160 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
10161 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010162 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010163 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
10164 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
10165 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010166 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010167 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
10168 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
10169 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010170 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010171 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
10172 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
10173 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010174 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010175 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
10176 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
10177 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010178 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010179 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
10180 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
10181 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010182 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010183 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
10184 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
10185 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010186 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010187 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
10188 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
10189 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010190 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010191 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
10192 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
10193 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010194 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010195 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
10196 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
10197 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010198 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010199 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
10200 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
10201 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010202 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010203 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
10204 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
10205 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010206 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010207 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
10208 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
10209 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010210 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010211 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
10212 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
10213 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010214 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010215 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
10216 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
10217 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010218 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010219 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
10220 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
10221 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010222 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010223 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
10224 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
10225 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010226 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010227 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
10228 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
10229 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010230 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010231 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
10232 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
10233 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010234 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010235 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
10236 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
10237 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010238 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010239 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
10240 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
10241 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010242 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010243 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
10244 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
10245 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010246 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010247 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
10248 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
10249 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010250 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010251 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
10252 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
10253 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010254 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010255 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
10256 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
10257 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010258 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010259 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
10260 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
10261 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010262 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010263 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
10264 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
10265 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010266 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010267 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
10268 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
10269 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010270 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010271 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
10272 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
10273 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010274 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010275 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
10276 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
10277 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010278 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010279 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
10280 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
10281 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010282 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010283 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
10284 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
10285 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010286 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010287 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
10288 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
10289 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010290 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010291 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
10292 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
10293 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010294 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010295 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
10296 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
10297 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010298 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010299 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
10300 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
10301 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010302 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010303 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
10304 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
10305 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010306 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010307 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
10308 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
10309 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010310 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010311 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
10312 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
10313 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010314 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010315 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
10316 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
10317 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010318 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010319 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
10320 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
10321 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010322 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010323 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
10324 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
10325 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010326 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010327 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
10328 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
10329 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010330 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010331 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
10332 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
10333 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010334 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010335 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
10336 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
10337 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010338 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010339 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
10340 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
10341 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010342 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010343 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
10344 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10345 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010346 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010347 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10348 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
10349 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010350 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010351 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
10352 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
10353 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010354 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010355 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
10356 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
10357 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010358 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010359 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
10360 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
10361 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010362 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010363 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
10364 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
10365 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010366 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010367 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
10368 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
10369 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010370 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010371 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
10372 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
10373 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010374 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010375 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
10376 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
10377 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010378 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010379 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
10380 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
10381 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010382 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010383 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
10384 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
10385 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010386 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010387 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
10388 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
10389 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010390 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010391 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
10392 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
10393 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010394 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010395 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
10396 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
10397 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010398 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010399 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
10400 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
10401 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010402 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010403 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
10404 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
10405 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010406 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010407 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
10408 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
10409 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010410 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010411 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
10412 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
10413 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010414 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010415 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
10416 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
10417 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010418 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010419 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
10420 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
10421 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010422 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010423 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
10424 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
10425 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010426 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010427 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
10428 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
10429 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010430 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010431 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
10432 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
10433 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010434 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010435 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
10436 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
10437 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010438 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010439 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
10440 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
10441 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010442 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010443};
10444
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010445static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
10446static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010447
10448/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010449static unsigned char _adv_asc38C1600_buf[] = {
10450 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010451 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
10452 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
10453 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010454 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010455 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
10456 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
10457 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010458 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010459 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
10460 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
10461 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010462 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010463 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
10464 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
10465 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010466 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010467 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
10468 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
10469 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010470 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010471 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
10472 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
10473 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010474 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010475 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
10476 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
10477 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010478 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010479 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
10480 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
10481 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010482 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010483 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
10484 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
10485 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010486 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010487 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
10488 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
10489 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010490 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010491 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
10492 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
10493 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010494 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010495 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
10496 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10497 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010498 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010499 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
10500 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
10501 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010502 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010503 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
10504 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
10505 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010506 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010507 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
10508 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
10509 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010510 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010511 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
10512 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
10513 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010514 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010515 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
10516 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
10517 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010518 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010519 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
10520 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
10521 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010522 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010523 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
10524 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
10525 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010526 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010527 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
10528 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
10529 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010530 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010531 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
10532 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
10533 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010534 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010535 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
10536 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
10537 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010538 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010539 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
10540 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
10541 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010542 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010543 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
10544 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
10545 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010546 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010547 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
10548 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
10549 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010550 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010551 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
10552 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
10553 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010554 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010555 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
10556 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
10557 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010558 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010559 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
10560 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
10561 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010562 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010563 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
10564 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
10565 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010566 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010567 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
10568 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
10569 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010570 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010571 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
10572 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
10573 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010574 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010575 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
10576 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
10577 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010578 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010579 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
10580 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
10581 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010582 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010583 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
10584 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
10585 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010586 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010587 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
10588 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
10589 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010590 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010591 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
10592 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
10593 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010594 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010595 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
10596 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
10597 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010598 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010599 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
10600 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
10601 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010602 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010603 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
10604 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
10605 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010606 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010607 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
10608 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
10609 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010610 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010611 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
10612 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
10613 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010614 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010615 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
10616 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
10617 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010618 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010619 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
10620 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
10621 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010622 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010623 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
10624 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
10625 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010626 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010627 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
10628 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
10629 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010630 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010631 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
10632 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
10633 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010634 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010635 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
10636 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
10637 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010638 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010639 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
10640 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
10641 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010642 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010643 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
10644 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
10645 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010646 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010647 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
10648 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
10649 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010650 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010651 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
10652 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
10653 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010654 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010655 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
10656 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
10657 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010658 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010659 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
10660 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
10661 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010662 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010663 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
10664 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
10665 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010666 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010667 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
10668 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
10669 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010670 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010671 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
10672 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
10673 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010674 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010675 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
10676 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
10677 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010678 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010679 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
10680 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
10681 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010682 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010683 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
10684 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
10685 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010686 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010687 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
10688 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
10689 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010690 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010691 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
10692 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
10693 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010694 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010695 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
10696 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
10697 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010698 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010699 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
10700 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
10701 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010702 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010703 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
10704 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
10705 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010706 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010707 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
10708 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
10709 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010710 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010711 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
10712 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
10713 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010714 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010715 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
10716 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
10717 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010718 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010719 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
10720 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
10721 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010722 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010723 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
10724 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
10725 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010726 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010727 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
10728 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
10729 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010730 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010731 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
10732 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
10733 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010734 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010735 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
10736 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
10737 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010738 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010739 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
10740 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
10741 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010742 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010743 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
10744 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
10745 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010746 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010747 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
10748 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
10749 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010750 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010751 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
10752 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
10753 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010754 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010755 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
10756 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
10757 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010758 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010759 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
10760 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
10761 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010762 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010763 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
10764 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
10765 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010766 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010767 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
10768 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
10769 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010770 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010771 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
10772 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
10773 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010774 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010775 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
10776 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
10777 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010778 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010779 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
10780 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
10781 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010782 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010783 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
10784 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
10785 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010786 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010787 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
10788 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
10789 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010790 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010791 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
10792 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
10793 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010794 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010795 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
10796 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
10797 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010798 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010799 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
10800 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
10801 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010802 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010803 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
10804 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
10805 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010806 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010807 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
10808 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
10809 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010810 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010811 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
10812 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
10813 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010814 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010815 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
10816 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
10817 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010818 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010819 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
10820 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
10821 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010822 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010823 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
10824 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
10825 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010826 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010827 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
10828 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
10829 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010830 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010831 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
10832 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
10833 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010834 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010835 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
10836 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
10837 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010838 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010839 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
10840 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
10841 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010842 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010843 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
10844 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
10845 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010846 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010847 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
10848 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
10849 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010850 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010851 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
10852 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
10853 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010854 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010855 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
10856 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
10857 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010858 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010859 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
10860 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
10861 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010862 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010863 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
10864 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
10865 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010866 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010867 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
10868 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
10869 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010870 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010871 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
10872 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
10873 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010874 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010875 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
10876 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
10877 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010878 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010879 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
10880 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
10881 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010882 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010883 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
10884 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
10885 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010886 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010887 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
10888 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
10889 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010890 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010891 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
10892 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
10893 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010894 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010895 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
10896 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
10897 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010898 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010899 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
10900 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
10901 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010902 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010903 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
10904 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
10905 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010906 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010907 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
10908 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
10909 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010910 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010911 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
10912 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
10913 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010914 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010915 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
10916 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
10917 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010918 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010919 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
10920 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
10921 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010922 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010923 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
10924 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
10925 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010926 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010927 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
10928 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
10929 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010930 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010931 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
10932 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
10933 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010934 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010935 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
10936 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
10937 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010938 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010939 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
10940 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
10941 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010942 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010943 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
10944 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
10945 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010946 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010947 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
10948 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
10949 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010950 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010951 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
10952 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
10953 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010954 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010955 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
10956 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
10957 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010958 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010959 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
10960 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
10961 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010962 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010963 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
10964 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
10965 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010966 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010967 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
10968 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
10969 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010970 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010971 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
10972 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
10973 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010974 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010975 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
10976 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
10977 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010978};
10979
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010980static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
10981static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010982
Linus Torvalds1da177e2005-04-16 15:20:36 -070010983/*
10984 * EEPROM Configuration.
10985 *
10986 * All drivers should use this structure to set the default EEPROM
10987 * configuration. The BIOS now uses this structure when it is built.
10988 * Additional structure information can be found in a_condor.h where
10989 * the structure is defined.
10990 *
10991 * The *_Field_IsChar structs are needed to correct for endianness.
10992 * These values are read from the board 16 bits at a time directly
10993 * into the structs. Because some fields are char, the values will be
10994 * in the wrong order. The *_Field_IsChar tells when to flip the
10995 * bytes. Data read and written to PCI memory is automatically swapped
10996 * on big-endian platforms so char fields read as words are actually being
10997 * unswapped on big-endian platforms.
10998 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010999static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011000 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
11001 0x0000, /* cfg_msw */
11002 0xFFFF, /* disc_enable */
11003 0xFFFF, /* wdtr_able */
11004 0xFFFF, /* sdtr_able */
11005 0xFFFF, /* start_motor */
11006 0xFFFF, /* tagqng_able */
11007 0xFFFF, /* bios_scan */
11008 0, /* scam_tolerant */
11009 7, /* adapter_scsi_id */
11010 0, /* bios_boot_delay */
11011 3, /* scsi_reset_delay */
11012 0, /* bios_id_lun */
11013 0, /* termination */
11014 0, /* reserved1 */
11015 0xFFE7, /* bios_ctrl */
11016 0xFFFF, /* ultra_able */
11017 0, /* reserved2 */
11018 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
11019 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11020 0, /* dvc_cntl */
11021 0, /* bug_fix */
11022 0, /* serial_number_word1 */
11023 0, /* serial_number_word2 */
11024 0, /* serial_number_word3 */
11025 0, /* check_sum */
11026 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11027 , /* oem_name[16] */
11028 0, /* dvc_err_code */
11029 0, /* adv_err_code */
11030 0, /* adv_err_addr */
11031 0, /* saved_dvc_err_code */
11032 0, /* saved_adv_err_code */
11033 0, /* saved_adv_err_addr */
11034 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011035};
11036
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011037static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011038 0, /* cfg_lsw */
11039 0, /* cfg_msw */
11040 0, /* -disc_enable */
11041 0, /* wdtr_able */
11042 0, /* sdtr_able */
11043 0, /* start_motor */
11044 0, /* tagqng_able */
11045 0, /* bios_scan */
11046 0, /* scam_tolerant */
11047 1, /* adapter_scsi_id */
11048 1, /* bios_boot_delay */
11049 1, /* scsi_reset_delay */
11050 1, /* bios_id_lun */
11051 1, /* termination */
11052 1, /* reserved1 */
11053 0, /* bios_ctrl */
11054 0, /* ultra_able */
11055 0, /* reserved2 */
11056 1, /* max_host_qng */
11057 1, /* max_dvc_qng */
11058 0, /* dvc_cntl */
11059 0, /* bug_fix */
11060 0, /* serial_number_word1 */
11061 0, /* serial_number_word2 */
11062 0, /* serial_number_word3 */
11063 0, /* check_sum */
11064 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11065 , /* oem_name[16] */
11066 0, /* dvc_err_code */
11067 0, /* adv_err_code */
11068 0, /* adv_err_addr */
11069 0, /* saved_dvc_err_code */
11070 0, /* saved_adv_err_code */
11071 0, /* saved_adv_err_addr */
11072 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011073};
11074
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011075static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011076 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11077 0x0000, /* 01 cfg_msw */
11078 0xFFFF, /* 02 disc_enable */
11079 0xFFFF, /* 03 wdtr_able */
11080 0x4444, /* 04 sdtr_speed1 */
11081 0xFFFF, /* 05 start_motor */
11082 0xFFFF, /* 06 tagqng_able */
11083 0xFFFF, /* 07 bios_scan */
11084 0, /* 08 scam_tolerant */
11085 7, /* 09 adapter_scsi_id */
11086 0, /* bios_boot_delay */
11087 3, /* 10 scsi_reset_delay */
11088 0, /* bios_id_lun */
11089 0, /* 11 termination_se */
11090 0, /* termination_lvd */
11091 0xFFE7, /* 12 bios_ctrl */
11092 0x4444, /* 13 sdtr_speed2 */
11093 0x4444, /* 14 sdtr_speed3 */
11094 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11095 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11096 0, /* 16 dvc_cntl */
11097 0x4444, /* 17 sdtr_speed4 */
11098 0, /* 18 serial_number_word1 */
11099 0, /* 19 serial_number_word2 */
11100 0, /* 20 serial_number_word3 */
11101 0, /* 21 check_sum */
11102 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11103 , /* 22-29 oem_name[16] */
11104 0, /* 30 dvc_err_code */
11105 0, /* 31 adv_err_code */
11106 0, /* 32 adv_err_addr */
11107 0, /* 33 saved_dvc_err_code */
11108 0, /* 34 saved_adv_err_code */
11109 0, /* 35 saved_adv_err_addr */
11110 0, /* 36 reserved */
11111 0, /* 37 reserved */
11112 0, /* 38 reserved */
11113 0, /* 39 reserved */
11114 0, /* 40 reserved */
11115 0, /* 41 reserved */
11116 0, /* 42 reserved */
11117 0, /* 43 reserved */
11118 0, /* 44 reserved */
11119 0, /* 45 reserved */
11120 0, /* 46 reserved */
11121 0, /* 47 reserved */
11122 0, /* 48 reserved */
11123 0, /* 49 reserved */
11124 0, /* 50 reserved */
11125 0, /* 51 reserved */
11126 0, /* 52 reserved */
11127 0, /* 53 reserved */
11128 0, /* 54 reserved */
11129 0, /* 55 reserved */
11130 0, /* 56 cisptr_lsw */
11131 0, /* 57 cisprt_msw */
11132 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11133 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
11134 0, /* 60 reserved */
11135 0, /* 61 reserved */
11136 0, /* 62 reserved */
11137 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011138};
11139
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011140static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011141 0, /* 00 cfg_lsw */
11142 0, /* 01 cfg_msw */
11143 0, /* 02 disc_enable */
11144 0, /* 03 wdtr_able */
11145 0, /* 04 sdtr_speed1 */
11146 0, /* 05 start_motor */
11147 0, /* 06 tagqng_able */
11148 0, /* 07 bios_scan */
11149 0, /* 08 scam_tolerant */
11150 1, /* 09 adapter_scsi_id */
11151 1, /* bios_boot_delay */
11152 1, /* 10 scsi_reset_delay */
11153 1, /* bios_id_lun */
11154 1, /* 11 termination_se */
11155 1, /* termination_lvd */
11156 0, /* 12 bios_ctrl */
11157 0, /* 13 sdtr_speed2 */
11158 0, /* 14 sdtr_speed3 */
11159 1, /* 15 max_host_qng */
11160 1, /* max_dvc_qng */
11161 0, /* 16 dvc_cntl */
11162 0, /* 17 sdtr_speed4 */
11163 0, /* 18 serial_number_word1 */
11164 0, /* 19 serial_number_word2 */
11165 0, /* 20 serial_number_word3 */
11166 0, /* 21 check_sum */
11167 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11168 , /* 22-29 oem_name[16] */
11169 0, /* 30 dvc_err_code */
11170 0, /* 31 adv_err_code */
11171 0, /* 32 adv_err_addr */
11172 0, /* 33 saved_dvc_err_code */
11173 0, /* 34 saved_adv_err_code */
11174 0, /* 35 saved_adv_err_addr */
11175 0, /* 36 reserved */
11176 0, /* 37 reserved */
11177 0, /* 38 reserved */
11178 0, /* 39 reserved */
11179 0, /* 40 reserved */
11180 0, /* 41 reserved */
11181 0, /* 42 reserved */
11182 0, /* 43 reserved */
11183 0, /* 44 reserved */
11184 0, /* 45 reserved */
11185 0, /* 46 reserved */
11186 0, /* 47 reserved */
11187 0, /* 48 reserved */
11188 0, /* 49 reserved */
11189 0, /* 50 reserved */
11190 0, /* 51 reserved */
11191 0, /* 52 reserved */
11192 0, /* 53 reserved */
11193 0, /* 54 reserved */
11194 0, /* 55 reserved */
11195 0, /* 56 cisptr_lsw */
11196 0, /* 57 cisprt_msw */
11197 0, /* 58 subsysvid */
11198 0, /* 59 subsysid */
11199 0, /* 60 reserved */
11200 0, /* 61 reserved */
11201 0, /* 62 reserved */
11202 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011203};
11204
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011205static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011206 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11207 0x0000, /* 01 cfg_msw */
11208 0xFFFF, /* 02 disc_enable */
11209 0xFFFF, /* 03 wdtr_able */
11210 0x5555, /* 04 sdtr_speed1 */
11211 0xFFFF, /* 05 start_motor */
11212 0xFFFF, /* 06 tagqng_able */
11213 0xFFFF, /* 07 bios_scan */
11214 0, /* 08 scam_tolerant */
11215 7, /* 09 adapter_scsi_id */
11216 0, /* bios_boot_delay */
11217 3, /* 10 scsi_reset_delay */
11218 0, /* bios_id_lun */
11219 0, /* 11 termination_se */
11220 0, /* termination_lvd */
11221 0xFFE7, /* 12 bios_ctrl */
11222 0x5555, /* 13 sdtr_speed2 */
11223 0x5555, /* 14 sdtr_speed3 */
11224 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11225 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11226 0, /* 16 dvc_cntl */
11227 0x5555, /* 17 sdtr_speed4 */
11228 0, /* 18 serial_number_word1 */
11229 0, /* 19 serial_number_word2 */
11230 0, /* 20 serial_number_word3 */
11231 0, /* 21 check_sum */
11232 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11233 , /* 22-29 oem_name[16] */
11234 0, /* 30 dvc_err_code */
11235 0, /* 31 adv_err_code */
11236 0, /* 32 adv_err_addr */
11237 0, /* 33 saved_dvc_err_code */
11238 0, /* 34 saved_adv_err_code */
11239 0, /* 35 saved_adv_err_addr */
11240 0, /* 36 reserved */
11241 0, /* 37 reserved */
11242 0, /* 38 reserved */
11243 0, /* 39 reserved */
11244 0, /* 40 reserved */
11245 0, /* 41 reserved */
11246 0, /* 42 reserved */
11247 0, /* 43 reserved */
11248 0, /* 44 reserved */
11249 0, /* 45 reserved */
11250 0, /* 46 reserved */
11251 0, /* 47 reserved */
11252 0, /* 48 reserved */
11253 0, /* 49 reserved */
11254 0, /* 50 reserved */
11255 0, /* 51 reserved */
11256 0, /* 52 reserved */
11257 0, /* 53 reserved */
11258 0, /* 54 reserved */
11259 0, /* 55 reserved */
11260 0, /* 56 cisptr_lsw */
11261 0, /* 57 cisprt_msw */
11262 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11263 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
11264 0, /* 60 reserved */
11265 0, /* 61 reserved */
11266 0, /* 62 reserved */
11267 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011268};
11269
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011270static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011271 0, /* 00 cfg_lsw */
11272 0, /* 01 cfg_msw */
11273 0, /* 02 disc_enable */
11274 0, /* 03 wdtr_able */
11275 0, /* 04 sdtr_speed1 */
11276 0, /* 05 start_motor */
11277 0, /* 06 tagqng_able */
11278 0, /* 07 bios_scan */
11279 0, /* 08 scam_tolerant */
11280 1, /* 09 adapter_scsi_id */
11281 1, /* bios_boot_delay */
11282 1, /* 10 scsi_reset_delay */
11283 1, /* bios_id_lun */
11284 1, /* 11 termination_se */
11285 1, /* termination_lvd */
11286 0, /* 12 bios_ctrl */
11287 0, /* 13 sdtr_speed2 */
11288 0, /* 14 sdtr_speed3 */
11289 1, /* 15 max_host_qng */
11290 1, /* max_dvc_qng */
11291 0, /* 16 dvc_cntl */
11292 0, /* 17 sdtr_speed4 */
11293 0, /* 18 serial_number_word1 */
11294 0, /* 19 serial_number_word2 */
11295 0, /* 20 serial_number_word3 */
11296 0, /* 21 check_sum */
11297 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11298 , /* 22-29 oem_name[16] */
11299 0, /* 30 dvc_err_code */
11300 0, /* 31 adv_err_code */
11301 0, /* 32 adv_err_addr */
11302 0, /* 33 saved_dvc_err_code */
11303 0, /* 34 saved_adv_err_code */
11304 0, /* 35 saved_adv_err_addr */
11305 0, /* 36 reserved */
11306 0, /* 37 reserved */
11307 0, /* 38 reserved */
11308 0, /* 39 reserved */
11309 0, /* 40 reserved */
11310 0, /* 41 reserved */
11311 0, /* 42 reserved */
11312 0, /* 43 reserved */
11313 0, /* 44 reserved */
11314 0, /* 45 reserved */
11315 0, /* 46 reserved */
11316 0, /* 47 reserved */
11317 0, /* 48 reserved */
11318 0, /* 49 reserved */
11319 0, /* 50 reserved */
11320 0, /* 51 reserved */
11321 0, /* 52 reserved */
11322 0, /* 53 reserved */
11323 0, /* 54 reserved */
11324 0, /* 55 reserved */
11325 0, /* 56 cisptr_lsw */
11326 0, /* 57 cisprt_msw */
11327 0, /* 58 subsysvid */
11328 0, /* 59 subsysid */
11329 0, /* 60 reserved */
11330 0, /* 61 reserved */
11331 0, /* 62 reserved */
11332 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011333};
11334
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011335#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -070011336/*
11337 * Initialize the ADV_DVC_VAR structure.
11338 *
11339 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11340 *
11341 * For a non-fatal error return a warning code. If there are no warnings
11342 * then 0 is returned.
11343 */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040011344static int __devinit
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011345AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011346{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011347 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011348 unsigned short warn_code = 0;
11349 AdvPortAddr iop_base = asc_dvc->iop_base;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011350 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011351 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011352
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011353 asc_dvc->err_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011354
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011355 /*
11356 * Save the state of the PCI Configuration Command Register
11357 * "Parity Error Response Control" Bit. If the bit is clear (0),
11358 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
11359 * DMA parity errors.
11360 */
11361 asc_dvc->cfg->control_flag = 0;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011362 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
11363 if ((cmd & PCI_COMMAND_PARITY) == 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011364 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011365
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011366 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
11367 ADV_LIB_VERSION_MINOR;
11368 asc_dvc->cfg->chip_version =
11369 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011370
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011371 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
11372 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
11373 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011374
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011375 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
11376 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
11377 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011378
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011379 /*
11380 * Reset the chip to start and allow register writes.
11381 */
11382 if (AdvFindSignature(iop_base) == 0) {
11383 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11384 return ADV_ERROR;
11385 } else {
11386 /*
11387 * The caller must set 'chip_type' to a valid setting.
11388 */
11389 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
11390 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
11391 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
11392 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
11393 return ADV_ERROR;
11394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011396 /*
11397 * Reset Chip.
11398 */
11399 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11400 ADV_CTRL_REG_CMD_RESET);
11401 DvcSleepMilliSecond(100);
11402 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11403 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011404
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011405 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011406 status = AdvInitFrom38C1600EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011407 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011408 status = AdvInitFrom38C0800EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011409 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011410 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011411 }
11412 warn_code |= status;
11413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011414
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011415 if (warn_code != 0) {
11416 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
11417 boardp->id, warn_code);
11418 }
11419
11420 if (asc_dvc->err_code) {
11421 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
11422 boardp->id, asc_dvc->err_code);
11423 }
11424
11425 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011426}
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011427#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070011428
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011429static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
11430{
11431 ADV_CARR_T *carrp;
11432 ADV_SDCNT buf_size;
11433 ADV_PADDR carr_paddr;
11434
11435 BUG_ON(!asc_dvc->carrier_buf);
11436
11437 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
11438 asc_dvc->carr_freelist = NULL;
11439 if (carrp == asc_dvc->carrier_buf) {
11440 buf_size = ADV_CARRIER_BUFSIZE;
11441 } else {
11442 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
11443 }
11444
11445 do {
11446 /* Get physical address of the carrier 'carrp'. */
11447 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
11448 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
11449 (uchar *)carrp,
11450 (ADV_SDCNT *)&contig_len,
11451 ADV_IS_CARRIER_FLAG));
11452
11453 buf_size -= sizeof(ADV_CARR_T);
11454
11455 /*
11456 * If the current carrier is not physically contiguous, then
11457 * maybe there was a page crossing. Try the next carrier
11458 * aligned start address.
11459 */
11460 if (contig_len < sizeof(ADV_CARR_T)) {
11461 carrp++;
11462 continue;
11463 }
11464
11465 carrp->carr_pa = carr_paddr;
11466 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
11467
11468 /*
11469 * Insert the carrier at the beginning of the freelist.
11470 */
11471 carrp->next_vpa =
11472 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
11473 asc_dvc->carr_freelist = carrp;
11474
11475 carrp++;
11476 } while (buf_size > 0);
11477}
11478
Linus Torvalds1da177e2005-04-16 15:20:36 -070011479/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011480 * Load the Microcode
11481 *
11482 * Write the microcode image to RISC memory starting at address 0.
11483 *
11484 * The microcode is stored compressed in the following format:
11485 *
11486 * 254 word (508 byte) table indexed by byte code followed
11487 * by the following byte codes:
11488 *
11489 * 1-Byte Code:
11490 * 00: Emit word 0 in table.
11491 * 01: Emit word 1 in table.
11492 * .
11493 * FD: Emit word 253 in table.
11494 *
11495 * Multi-Byte Code:
11496 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
11497 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
11498 *
11499 * Returns 0 or an error if the checksum doesn't match
11500 */
11501static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
11502 int memsize, int chksum)
11503{
11504 int i, j, end, len = 0;
11505 ADV_DCNT sum;
11506
11507 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11508
11509 for (i = 253 * 2; i < size; i++) {
11510 if (buf[i] == 0xff) {
11511 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
11512 for (j = 0; j < buf[i + 1]; j++) {
11513 AdvWriteWordAutoIncLram(iop_base, word);
11514 len += 2;
11515 }
11516 i += 3;
11517 } else if (buf[i] == 0xfe) {
11518 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
11519 AdvWriteWordAutoIncLram(iop_base, word);
11520 i += 2;
11521 len += 2;
11522 } else {
11523 unsigned char off = buf[i] * 2;
11524 unsigned short word = (buf[off + 1] << 8) | buf[off];
11525 AdvWriteWordAutoIncLram(iop_base, word);
11526 len += 2;
11527 }
11528 }
11529
11530 end = len;
11531
11532 while (len < memsize) {
11533 AdvWriteWordAutoIncLram(iop_base, 0);
11534 len += 2;
11535 }
11536
11537 /* Verify the microcode checksum. */
11538 sum = 0;
11539 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11540
11541 for (len = 0; len < end; len += 2) {
11542 sum += AdvReadWordAutoIncLram(iop_base);
11543 }
11544
11545 if (sum != chksum)
11546 return ASC_IERR_MCODE_CHKSUM;
11547
11548 return 0;
11549}
11550
11551/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070011552 * Initialize the ASC-3550.
11553 *
11554 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11555 *
11556 * For a non-fatal error return a warning code. If there are no warnings
11557 * then 0 is returned.
11558 *
11559 * Needed after initialization for error recovery.
11560 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011561static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011562{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011563 AdvPortAddr iop_base;
11564 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011565 int begin_addr;
11566 int end_addr;
11567 ushort code_sum;
11568 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011569 int i;
11570 ushort scsi_cfg1;
11571 uchar tid;
11572 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
11573 ushort wdtr_able = 0, sdtr_able, tagqng_able;
11574 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070011575
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011576 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011577 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011578 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011579
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011580 /*
11581 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
11582 */
11583 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011584 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011585 return ADV_ERROR;
11586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011588 warn_code = 0;
11589 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011590
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011591 /*
11592 * Save the RISC memory BIOS region before writing the microcode.
11593 * The BIOS may already be loaded and using its RISC LRAM region
11594 * so its region must be saved and restored.
11595 *
11596 * Note: This code makes the assumption, which is currently true,
11597 * that a chip reset does not clear RISC LRAM.
11598 */
11599 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11600 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11601 bios_mem[i]);
11602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011603
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011604 /*
11605 * Save current per TID negotiated values.
11606 */
11607 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
11608 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011609
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011610 bios_version =
11611 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
11612 major = (bios_version >> 12) & 0xF;
11613 minor = (bios_version >> 8) & 0xF;
11614 if (major < 3 || (major == 3 && minor == 1)) {
11615 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
11616 AdvReadWordLram(iop_base, 0x120, wdtr_able);
11617 } else {
11618 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11619 }
11620 }
11621 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11622 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
11623 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11624 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
11625 max_cmd[tid]);
11626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011627
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011628 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
11629 _adv_asc3550_size, ADV_3550_MEMSIZE,
11630 _adv_asc3550_chksum);
11631 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011632 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011633
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011634 /*
11635 * Restore the RISC memory BIOS region.
11636 */
11637 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11638 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11639 bios_mem[i]);
11640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011641
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011642 /*
11643 * Calculate and write the microcode code checksum to the microcode
11644 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
11645 */
11646 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
11647 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
11648 code_sum = 0;
11649 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
11650 for (word = begin_addr; word < end_addr; word += 2) {
11651 code_sum += AdvReadWordAutoIncLram(iop_base);
11652 }
11653 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011654
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011655 /*
11656 * Read and save microcode version and date.
11657 */
11658 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
11659 asc_dvc->cfg->mcode_date);
11660 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
11661 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011662
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011663 /*
11664 * Set the chip type to indicate the ASC3550.
11665 */
11666 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011667
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011668 /*
11669 * If the PCI Configuration Command Register "Parity Error Response
11670 * Control" Bit was clear (0), then set the microcode variable
11671 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
11672 * to ignore DMA parity errors.
11673 */
11674 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
11675 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11676 word |= CONTROL_FLAG_IGNORE_PERR;
11677 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011679
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011680 /*
11681 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
11682 * threshold of 128 bytes. This register is only accessible to the host.
11683 */
11684 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
11685 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011686
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011687 /*
11688 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040011689 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011690 * device reports it is capable of in Inquiry byte 7.
11691 *
11692 * If SCSI Bus Resets have been disabled, then directly set
11693 * SDTR and WDTR from the EEPROM configuration. This will allow
11694 * the BIOS and warm boot to work without a SCSI bus hang on
11695 * the Inquiry caused by host and target mismatched DTR values.
11696 * Without the SCSI Bus Reset, before an Inquiry a device can't
11697 * be assumed to be in Asynchronous, Narrow mode.
11698 */
11699 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
11700 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
11701 asc_dvc->wdtr_able);
11702 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
11703 asc_dvc->sdtr_able);
11704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011705
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011706 /*
11707 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
11708 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
11709 * bitmask. These values determine the maximum SDTR speed negotiated
11710 * with a device.
11711 *
11712 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
11713 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
11714 * without determining here whether the device supports SDTR.
11715 *
11716 * 4-bit speed SDTR speed name
11717 * =========== ===============
11718 * 0000b (0x0) SDTR disabled
11719 * 0001b (0x1) 5 Mhz
11720 * 0010b (0x2) 10 Mhz
11721 * 0011b (0x3) 20 Mhz (Ultra)
11722 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
11723 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
11724 * 0110b (0x6) Undefined
11725 * .
11726 * 1111b (0xF) Undefined
11727 */
11728 word = 0;
11729 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11730 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
11731 /* Set Ultra speed for TID 'tid'. */
11732 word |= (0x3 << (4 * (tid % 4)));
11733 } else {
11734 /* Set Fast speed for TID 'tid'. */
11735 word |= (0x2 << (4 * (tid % 4)));
11736 }
11737 if (tid == 3) { /* Check if done with sdtr_speed1. */
11738 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
11739 word = 0;
11740 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
11741 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
11742 word = 0;
11743 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
11744 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
11745 word = 0;
11746 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
11747 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
11748 /* End of loop. */
11749 }
11750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011751
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011752 /*
11753 * Set microcode operating variable for the disconnect per TID bitmask.
11754 */
11755 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
11756 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011758 /*
11759 * Set SCSI_CFG0 Microcode Default Value.
11760 *
11761 * The microcode will set the SCSI_CFG0 register using this value
11762 * after it is started below.
11763 */
11764 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
11765 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
11766 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011767
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011768 /*
11769 * Determine SCSI_CFG1 Microcode Default Value.
11770 *
11771 * The microcode will set the SCSI_CFG1 register using this value
11772 * after it is started below.
11773 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011774
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011775 /* Read current SCSI_CFG1 Register value. */
11776 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011777
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011778 /*
11779 * If all three connectors are in use, return an error.
11780 */
11781 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
11782 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
11783 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
11784 return ADV_ERROR;
11785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011786
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011787 /*
11788 * If the internal narrow cable is reversed all of the SCSI_CTRL
11789 * register signals will be set. Check for and return an error if
11790 * this condition is found.
11791 */
11792 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
11793 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
11794 return ADV_ERROR;
11795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011796
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011797 /*
11798 * If this is a differential board and a single-ended device
11799 * is attached to one of the connectors, return an error.
11800 */
11801 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
11802 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
11803 return ADV_ERROR;
11804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011805
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011806 /*
11807 * If automatic termination control is enabled, then set the
11808 * termination value based on a table listed in a_condor.h.
11809 *
11810 * If manual termination was specified with an EEPROM setting
11811 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
11812 * is ready to be 'ored' into SCSI_CFG1.
11813 */
11814 if (asc_dvc->cfg->termination == 0) {
11815 /*
11816 * The software always controls termination by setting TERM_CTL_SEL.
11817 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
11818 */
11819 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011820
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011821 switch (scsi_cfg1 & CABLE_DETECT) {
11822 /* TERM_CTL_H: on, TERM_CTL_L: on */
11823 case 0x3:
11824 case 0x7:
11825 case 0xB:
11826 case 0xD:
11827 case 0xE:
11828 case 0xF:
11829 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
11830 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011831
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011832 /* TERM_CTL_H: on, TERM_CTL_L: off */
11833 case 0x1:
11834 case 0x5:
11835 case 0x9:
11836 case 0xA:
11837 case 0xC:
11838 asc_dvc->cfg->termination |= TERM_CTL_H;
11839 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011841 /* TERM_CTL_H: off, TERM_CTL_L: off */
11842 case 0x2:
11843 case 0x6:
11844 break;
11845 }
11846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011847
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011848 /*
11849 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
11850 */
11851 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011852
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011853 /*
11854 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
11855 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
11856 * referenced, because the hardware internally inverts
11857 * the Termination High and Low bits if TERM_POL is set.
11858 */
11859 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011860
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011861 /*
11862 * Set SCSI_CFG1 Microcode Default Value
11863 *
11864 * Set filter value and possibly modified termination control
11865 * bits in the Microcode SCSI_CFG1 Register Value.
11866 *
11867 * The microcode will set the SCSI_CFG1 register using this value
11868 * after it is started below.
11869 */
11870 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
11871 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011872
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011873 /*
11874 * Set MEM_CFG Microcode Default Value
11875 *
11876 * The microcode will set the MEM_CFG register using this value
11877 * after it is started below.
11878 *
11879 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
11880 * are defined.
11881 *
11882 * ASC-3550 has 8KB internal memory.
11883 */
11884 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
11885 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011887 /*
11888 * Set SEL_MASK Microcode Default Value
11889 *
11890 * The microcode will set the SEL_MASK register using this value
11891 * after it is started below.
11892 */
11893 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
11894 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011895
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011896 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011897
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011898 /*
11899 * Set-up the Host->RISC Initiator Command Queue (ICQ).
11900 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011901
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011902 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
11903 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11904 return ADV_ERROR;
11905 }
11906 asc_dvc->carr_freelist = (ADV_CARR_T *)
11907 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011908
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011909 /*
11910 * The first command issued will be placed in the stopper carrier.
11911 */
11912 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011913
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011914 /*
11915 * Set RISC ICQ physical address start value.
11916 */
11917 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011918
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011919 /*
11920 * Set-up the RISC->Host Initiator Response Queue (IRQ).
11921 */
11922 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
11923 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11924 return ADV_ERROR;
11925 }
11926 asc_dvc->carr_freelist = (ADV_CARR_T *)
11927 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011928
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011929 /*
11930 * The first command completed by the RISC will be placed in
11931 * the stopper.
11932 *
11933 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
11934 * completed the RISC will set the ASC_RQ_STOPPER bit.
11935 */
11936 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011937
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011938 /*
11939 * Set RISC IRQ physical address start value.
11940 */
11941 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
11942 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011943
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011944 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
11945 (ADV_INTR_ENABLE_HOST_INTR |
11946 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011947
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011948 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
11949 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011950
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011951 /* finally, finally, gentlemen, start your engine */
11952 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011953
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011954 /*
11955 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
11956 * Resets should be performed. The RISC has to be running
11957 * to issue a SCSI Bus Reset.
11958 */
11959 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
11960 /*
11961 * If the BIOS Signature is present in memory, restore the
11962 * BIOS Handshake Configuration Table and do not perform
11963 * a SCSI Bus Reset.
11964 */
11965 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
11966 0x55AA) {
11967 /*
11968 * Restore per TID negotiated values.
11969 */
11970 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11971 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11972 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
11973 tagqng_able);
11974 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11975 AdvWriteByteLram(iop_base,
11976 ASC_MC_NUMBER_OF_MAX_CMD + tid,
11977 max_cmd[tid]);
11978 }
11979 } else {
11980 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
11981 warn_code = ASC_WARN_BUSRESET_ERROR;
11982 }
11983 }
11984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011985
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011986 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011987}
11988
11989/*
11990 * Initialize the ASC-38C0800.
11991 *
11992 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11993 *
11994 * For a non-fatal error return a warning code. If there are no warnings
11995 * then 0 is returned.
11996 *
11997 * Needed after initialization for error recovery.
11998 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011999static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012000{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012001 AdvPortAddr iop_base;
12002 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012003 int begin_addr;
12004 int end_addr;
12005 ushort code_sum;
12006 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012007 int i;
12008 ushort scsi_cfg1;
12009 uchar byte;
12010 uchar tid;
12011 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12012 ushort wdtr_able, sdtr_able, tagqng_able;
12013 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012014
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012015 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012016 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012017 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012018
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012019 /*
12020 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
12021 */
12022 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
12023 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12024 return ADV_ERROR;
12025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012026
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012027 warn_code = 0;
12028 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012029
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012030 /*
12031 * Save the RISC memory BIOS region before writing the microcode.
12032 * The BIOS may already be loaded and using its RISC LRAM region
12033 * so its region must be saved and restored.
12034 *
12035 * Note: This code makes the assumption, which is currently true,
12036 * that a chip reset does not clear RISC LRAM.
12037 */
12038 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12039 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12040 bios_mem[i]);
12041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012042
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012043 /*
12044 * Save current per TID negotiated values.
12045 */
12046 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12047 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12048 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12049 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12050 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12051 max_cmd[tid]);
12052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012053
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012054 /*
12055 * RAM BIST (RAM Built-In Self Test)
12056 *
12057 * Address : I/O base + offset 0x38h register (byte).
12058 * Function: Bit 7-6(RW) : RAM mode
12059 * Normal Mode : 0x00
12060 * Pre-test Mode : 0x40
12061 * RAM Test Mode : 0x80
12062 * Bit 5 : unused
12063 * Bit 4(RO) : Done bit
12064 * Bit 3-0(RO) : Status
12065 * Host Error : 0x08
12066 * Int_RAM Error : 0x04
12067 * RISC Error : 0x02
12068 * SCSI Error : 0x01
12069 * No Error : 0x00
12070 *
12071 * Note: RAM BIST code should be put right here, before loading the
12072 * microcode and after saving the RISC memory BIOS region.
12073 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012074
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012075 /*
12076 * LRAM Pre-test
12077 *
12078 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12079 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12080 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12081 * to NORMAL_MODE, return an error too.
12082 */
12083 for (i = 0; i < 2; i++) {
12084 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12085 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12086 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12087 if ((byte & RAM_TEST_DONE) == 0
12088 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012089 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012090 return ADV_ERROR;
12091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012092
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012093 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12094 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12095 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12096 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012097 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012098 return ADV_ERROR;
12099 }
12100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012102 /*
12103 * LRAM Test - It takes about 1.5 ms to run through the test.
12104 *
12105 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12106 * If Done bit not set or Status not 0, save register byte, set the
12107 * err_code, and return an error.
12108 */
12109 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12110 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012111
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012112 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12113 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12114 /* Get here if Done bit not set or Status not 0. */
12115 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012116 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012117 return ADV_ERROR;
12118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012119
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012120 /* We need to reset back to normal mode after LRAM test passes. */
12121 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012122
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012123 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
12124 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
12125 _adv_asc38C0800_chksum);
12126 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012127 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012128
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012129 /*
12130 * Restore the RISC memory BIOS region.
12131 */
12132 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12133 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12134 bios_mem[i]);
12135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012136
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012137 /*
12138 * Calculate and write the microcode code checksum to the microcode
12139 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12140 */
12141 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12142 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12143 code_sum = 0;
12144 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12145 for (word = begin_addr; word < end_addr; word += 2) {
12146 code_sum += AdvReadWordAutoIncLram(iop_base);
12147 }
12148 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012149
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012150 /*
12151 * Read microcode version and date.
12152 */
12153 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12154 asc_dvc->cfg->mcode_date);
12155 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12156 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012157
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012158 /*
12159 * Set the chip type to indicate the ASC38C0800.
12160 */
12161 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012162
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012163 /*
12164 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12165 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12166 * cable detection and then we are able to read C_DET[3:0].
12167 *
12168 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12169 * Microcode Default Value' section below.
12170 */
12171 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12172 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12173 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012174
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012175 /*
12176 * If the PCI Configuration Command Register "Parity Error Response
12177 * Control" Bit was clear (0), then set the microcode variable
12178 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12179 * to ignore DMA parity errors.
12180 */
12181 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12182 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12183 word |= CONTROL_FLAG_IGNORE_PERR;
12184 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012186
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012187 /*
12188 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
12189 * bits for the default FIFO threshold.
12190 *
12191 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
12192 *
12193 * For DMA Errata #4 set the BC_THRESH_ENB bit.
12194 */
12195 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12196 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
12197 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012198
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012199 /*
12200 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012201 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012202 * device reports it is capable of in Inquiry byte 7.
12203 *
12204 * If SCSI Bus Resets have been disabled, then directly set
12205 * SDTR and WDTR from the EEPROM configuration. This will allow
12206 * the BIOS and warm boot to work without a SCSI bus hang on
12207 * the Inquiry caused by host and target mismatched DTR values.
12208 * Without the SCSI Bus Reset, before an Inquiry a device can't
12209 * be assumed to be in Asynchronous, Narrow mode.
12210 */
12211 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12212 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12213 asc_dvc->wdtr_able);
12214 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12215 asc_dvc->sdtr_able);
12216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012217
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012218 /*
12219 * Set microcode operating variables for DISC and SDTR_SPEED1,
12220 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12221 * configuration values.
12222 *
12223 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12224 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12225 * without determining here whether the device supports SDTR.
12226 */
12227 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12228 asc_dvc->cfg->disc_enable);
12229 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12230 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12231 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12232 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012233
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012234 /*
12235 * Set SCSI_CFG0 Microcode Default Value.
12236 *
12237 * The microcode will set the SCSI_CFG0 register using this value
12238 * after it is started below.
12239 */
12240 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12241 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12242 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012243
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012244 /*
12245 * Determine SCSI_CFG1 Microcode Default Value.
12246 *
12247 * The microcode will set the SCSI_CFG1 register using this value
12248 * after it is started below.
12249 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012250
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012251 /* Read current SCSI_CFG1 Register value. */
12252 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012254 /*
12255 * If the internal narrow cable is reversed all of the SCSI_CTRL
12256 * register signals will be set. Check for and return an error if
12257 * this condition is found.
12258 */
12259 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12260 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12261 return ADV_ERROR;
12262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012263
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012264 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012265 * All kind of combinations of devices attached to one of four
12266 * connectors are acceptable except HVD device attached. For example,
12267 * LVD device can be attached to SE connector while SE device attached
12268 * to LVD connector. If LVD device attached to SE connector, it only
12269 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012270 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012271 * If an HVD device is attached to one of LVD connectors, return an
12272 * error. However, there is no way to detect HVD device attached to
12273 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012274 */
12275 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012276 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012277 return ADV_ERROR;
12278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012279
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012280 /*
12281 * If either SE or LVD automatic termination control is enabled, then
12282 * set the termination value based on a table listed in a_condor.h.
12283 *
12284 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012285 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
12286 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012287 */
12288 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
12289 /* SE automatic termination control is enabled. */
12290 switch (scsi_cfg1 & C_DET_SE) {
12291 /* TERM_SE_HI: on, TERM_SE_LO: on */
12292 case 0x1:
12293 case 0x2:
12294 case 0x3:
12295 asc_dvc->cfg->termination |= TERM_SE;
12296 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012298 /* TERM_SE_HI: on, TERM_SE_LO: off */
12299 case 0x0:
12300 asc_dvc->cfg->termination |= TERM_SE_HI;
12301 break;
12302 }
12303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012304
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012305 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
12306 /* LVD automatic termination control is enabled. */
12307 switch (scsi_cfg1 & C_DET_LVD) {
12308 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
12309 case 0x4:
12310 case 0x8:
12311 case 0xC:
12312 asc_dvc->cfg->termination |= TERM_LVD;
12313 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012314
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012315 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
12316 case 0x0:
12317 break;
12318 }
12319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012320
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012321 /*
12322 * Clear any set TERM_SE and TERM_LVD bits.
12323 */
12324 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012325
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012326 /*
12327 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
12328 */
12329 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012330
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012331 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012332 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
12333 * bits and set possibly modified termination control bits in the
12334 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012335 */
12336 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012337
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012338 /*
12339 * Set SCSI_CFG1 Microcode Default Value
12340 *
12341 * Set possibly modified termination control and reset DIS_TERM_DRV
12342 * bits in the Microcode SCSI_CFG1 Register Value.
12343 *
12344 * The microcode will set the SCSI_CFG1 register using this value
12345 * after it is started below.
12346 */
12347 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012348
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012349 /*
12350 * Set MEM_CFG Microcode Default Value
12351 *
12352 * The microcode will set the MEM_CFG register using this value
12353 * after it is started below.
12354 *
12355 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12356 * are defined.
12357 *
12358 * ASC-38C0800 has 16KB internal memory.
12359 */
12360 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12361 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012362
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012363 /*
12364 * Set SEL_MASK Microcode Default Value
12365 *
12366 * The microcode will set the SEL_MASK register using this value
12367 * after it is started below.
12368 */
12369 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12370 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012371
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012372 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012374 /*
12375 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12376 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012377
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012378 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12379 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12380 return ADV_ERROR;
12381 }
12382 asc_dvc->carr_freelist = (ADV_CARR_T *)
12383 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012384
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012385 /*
12386 * The first command issued will be placed in the stopper carrier.
12387 */
12388 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012389
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012390 /*
12391 * Set RISC ICQ physical address start value.
12392 * carr_pa is LE, must be native before write
12393 */
12394 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012396 /*
12397 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12398 */
12399 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12400 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12401 return ADV_ERROR;
12402 }
12403 asc_dvc->carr_freelist = (ADV_CARR_T *)
12404 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012405
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012406 /*
12407 * The first command completed by the RISC will be placed in
12408 * the stopper.
12409 *
12410 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12411 * completed the RISC will set the ASC_RQ_STOPPER bit.
12412 */
12413 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012414
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012415 /*
12416 * Set RISC IRQ physical address start value.
12417 *
12418 * carr_pa is LE, must be native before write *
12419 */
12420 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12421 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012422
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012423 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12424 (ADV_INTR_ENABLE_HOST_INTR |
12425 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012426
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012427 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12428 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012429
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012430 /* finally, finally, gentlemen, start your engine */
12431 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012432
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012433 /*
12434 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12435 * Resets should be performed. The RISC has to be running
12436 * to issue a SCSI Bus Reset.
12437 */
12438 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12439 /*
12440 * If the BIOS Signature is present in memory, restore the
12441 * BIOS Handshake Configuration Table and do not perform
12442 * a SCSI Bus Reset.
12443 */
12444 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12445 0x55AA) {
12446 /*
12447 * Restore per TID negotiated values.
12448 */
12449 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12450 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12451 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12452 tagqng_able);
12453 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12454 AdvWriteByteLram(iop_base,
12455 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12456 max_cmd[tid]);
12457 }
12458 } else {
12459 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12460 warn_code = ASC_WARN_BUSRESET_ERROR;
12461 }
12462 }
12463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012464
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012465 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012466}
12467
12468/*
12469 * Initialize the ASC-38C1600.
12470 *
12471 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
12472 *
12473 * For a non-fatal error return a warning code. If there are no warnings
12474 * then 0 is returned.
12475 *
12476 * Needed after initialization for error recovery.
12477 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012478static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012479{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012480 AdvPortAddr iop_base;
12481 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012482 int begin_addr;
12483 int end_addr;
12484 ushort code_sum;
12485 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012486 int i;
12487 ushort scsi_cfg1;
12488 uchar byte;
12489 uchar tid;
12490 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12491 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
12492 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012493
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012494 /* If there is already an error, don't continue. */
12495 if (asc_dvc->err_code != 0) {
12496 return ADV_ERROR;
12497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012498
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012499 /*
12500 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
12501 */
12502 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
12503 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12504 return ADV_ERROR;
12505 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012506
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012507 warn_code = 0;
12508 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012510 /*
12511 * Save the RISC memory BIOS region before writing the microcode.
12512 * The BIOS may already be loaded and using its RISC LRAM region
12513 * so its region must be saved and restored.
12514 *
12515 * Note: This code makes the assumption, which is currently true,
12516 * that a chip reset does not clear RISC LRAM.
12517 */
12518 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12519 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12520 bios_mem[i]);
12521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012522
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012523 /*
12524 * Save current per TID negotiated values.
12525 */
12526 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12527 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12528 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12529 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12530 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12531 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12532 max_cmd[tid]);
12533 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012534
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012535 /*
12536 * RAM BIST (Built-In Self Test)
12537 *
12538 * Address : I/O base + offset 0x38h register (byte).
12539 * Function: Bit 7-6(RW) : RAM mode
12540 * Normal Mode : 0x00
12541 * Pre-test Mode : 0x40
12542 * RAM Test Mode : 0x80
12543 * Bit 5 : unused
12544 * Bit 4(RO) : Done bit
12545 * Bit 3-0(RO) : Status
12546 * Host Error : 0x08
12547 * Int_RAM Error : 0x04
12548 * RISC Error : 0x02
12549 * SCSI Error : 0x01
12550 * No Error : 0x00
12551 *
12552 * Note: RAM BIST code should be put right here, before loading the
12553 * microcode and after saving the RISC memory BIOS region.
12554 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012555
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012556 /*
12557 * LRAM Pre-test
12558 *
12559 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12560 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12561 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12562 * to NORMAL_MODE, return an error too.
12563 */
12564 for (i = 0; i < 2; i++) {
12565 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12566 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12567 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12568 if ((byte & RAM_TEST_DONE) == 0
12569 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012570 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012571 return ADV_ERROR;
12572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012573
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012574 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12575 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12576 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12577 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012578 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012579 return ADV_ERROR;
12580 }
12581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012582
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012583 /*
12584 * LRAM Test - It takes about 1.5 ms to run through the test.
12585 *
12586 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12587 * If Done bit not set or Status not 0, save register byte, set the
12588 * err_code, and return an error.
12589 */
12590 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12591 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012592
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012593 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12594 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12595 /* Get here if Done bit not set or Status not 0. */
12596 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012597 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012598 return ADV_ERROR;
12599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012601 /* We need to reset back to normal mode after LRAM test passes. */
12602 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012603
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012604 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
12605 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
12606 _adv_asc38C1600_chksum);
12607 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012608 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012609
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012610 /*
12611 * Restore the RISC memory BIOS region.
12612 */
12613 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12614 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12615 bios_mem[i]);
12616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012617
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012618 /*
12619 * Calculate and write the microcode code checksum to the microcode
12620 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12621 */
12622 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12623 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12624 code_sum = 0;
12625 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12626 for (word = begin_addr; word < end_addr; word += 2) {
12627 code_sum += AdvReadWordAutoIncLram(iop_base);
12628 }
12629 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012630
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012631 /*
12632 * Read microcode version and date.
12633 */
12634 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12635 asc_dvc->cfg->mcode_date);
12636 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12637 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012638
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012639 /*
12640 * Set the chip type to indicate the ASC38C1600.
12641 */
12642 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012643
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012644 /*
12645 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12646 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12647 * cable detection and then we are able to read C_DET[3:0].
12648 *
12649 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12650 * Microcode Default Value' section below.
12651 */
12652 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12653 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12654 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012655
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012656 /*
12657 * If the PCI Configuration Command Register "Parity Error Response
12658 * Control" Bit was clear (0), then set the microcode variable
12659 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12660 * to ignore DMA parity errors.
12661 */
12662 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12663 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12664 word |= CONTROL_FLAG_IGNORE_PERR;
12665 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012667
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012668 /*
12669 * If the BIOS control flag AIPP (Asynchronous Information
12670 * Phase Protection) disable bit is not set, then set the firmware
12671 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
12672 * AIPP checking and encoding.
12673 */
12674 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
12675 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12676 word |= CONTROL_FLAG_ENABLE_AIPP;
12677 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012679
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012680 /*
12681 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
12682 * and START_CTL_TH [3:2].
12683 */
12684 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12685 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012686
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012687 /*
12688 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012689 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012690 * device reports it is capable of in Inquiry byte 7.
12691 *
12692 * If SCSI Bus Resets have been disabled, then directly set
12693 * SDTR and WDTR from the EEPROM configuration. This will allow
12694 * the BIOS and warm boot to work without a SCSI bus hang on
12695 * the Inquiry caused by host and target mismatched DTR values.
12696 * Without the SCSI Bus Reset, before an Inquiry a device can't
12697 * be assumed to be in Asynchronous, Narrow mode.
12698 */
12699 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12700 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12701 asc_dvc->wdtr_able);
12702 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12703 asc_dvc->sdtr_able);
12704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012705
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012706 /*
12707 * Set microcode operating variables for DISC and SDTR_SPEED1,
12708 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12709 * configuration values.
12710 *
12711 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12712 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12713 * without determining here whether the device supports SDTR.
12714 */
12715 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12716 asc_dvc->cfg->disc_enable);
12717 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12718 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12719 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12720 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012721
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012722 /*
12723 * Set SCSI_CFG0 Microcode Default Value.
12724 *
12725 * The microcode will set the SCSI_CFG0 register using this value
12726 * after it is started below.
12727 */
12728 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12729 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12730 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012731
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012732 /*
12733 * Calculate SCSI_CFG1 Microcode Default Value.
12734 *
12735 * The microcode will set the SCSI_CFG1 register using this value
12736 * after it is started below.
12737 *
12738 * Each ASC-38C1600 function has only two cable detect bits.
12739 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
12740 */
12741 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012742
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012743 /*
12744 * If the cable is reversed all of the SCSI_CTRL register signals
12745 * will be set. Check for and return an error if this condition is
12746 * found.
12747 */
12748 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12749 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12750 return ADV_ERROR;
12751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012752
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012753 /*
12754 * Each ASC-38C1600 function has two connectors. Only an HVD device
12755 * can not be connected to either connector. An LVD device or SE device
12756 * may be connected to either connecor. If an SE device is connected,
12757 * then at most Ultra speed (20 Mhz) can be used on both connectors.
12758 *
12759 * If an HVD device is attached, return an error.
12760 */
12761 if (scsi_cfg1 & HVD) {
12762 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
12763 return ADV_ERROR;
12764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012765
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012766 /*
12767 * Each function in the ASC-38C1600 uses only the SE cable detect and
12768 * termination because there are two connectors for each function. Each
12769 * function may use either LVD or SE mode. Corresponding the SE automatic
12770 * termination control EEPROM bits are used for each function. Each
12771 * function has its own EEPROM. If SE automatic control is enabled for
12772 * the function, then set the termination value based on a table listed
12773 * in a_condor.h.
12774 *
12775 * If manual termination is specified in the EEPROM for the function,
12776 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
12777 * ready to be 'ored' into SCSI_CFG1.
12778 */
12779 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012780 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012781 /* SE automatic termination control is enabled. */
12782 switch (scsi_cfg1 & C_DET_SE) {
12783 /* TERM_SE_HI: on, TERM_SE_LO: on */
12784 case 0x1:
12785 case 0x2:
12786 case 0x3:
12787 asc_dvc->cfg->termination |= TERM_SE;
12788 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012789
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012790 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012791 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012792 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
12793 } else {
12794 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
12795 asc_dvc->cfg->termination |= TERM_SE_HI;
12796 }
12797 break;
12798 }
12799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012800
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012801 /*
12802 * Clear any set TERM_SE bits.
12803 */
12804 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012805
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012806 /*
12807 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
12808 */
12809 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012810
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012811 /*
12812 * Clear Big Endian and Terminator Polarity bits and set possibly
12813 * modified termination control bits in the Microcode SCSI_CFG1
12814 * Register Value.
12815 *
12816 * Big Endian bit is not used even on big endian machines.
12817 */
12818 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012819
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012820 /*
12821 * Set SCSI_CFG1 Microcode Default Value
12822 *
12823 * Set possibly modified termination control bits in the Microcode
12824 * SCSI_CFG1 Register Value.
12825 *
12826 * The microcode will set the SCSI_CFG1 register using this value
12827 * after it is started below.
12828 */
12829 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012831 /*
12832 * Set MEM_CFG Microcode Default Value
12833 *
12834 * The microcode will set the MEM_CFG register using this value
12835 * after it is started below.
12836 *
12837 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12838 * are defined.
12839 *
12840 * ASC-38C1600 has 32KB internal memory.
12841 *
12842 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
12843 * out a special 16K Adv Library and Microcode version. After the issue
12844 * resolved, we should turn back to the 32K support. Both a_condor.h and
12845 * mcode.sas files also need to be updated.
12846 *
12847 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12848 * BIOS_EN | RAM_SZ_32KB);
12849 */
12850 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12851 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012852
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012853 /*
12854 * Set SEL_MASK Microcode Default Value
12855 *
12856 * The microcode will set the SEL_MASK register using this value
12857 * after it is started below.
12858 */
12859 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12860 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012861
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012862 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012863
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012864 /*
12865 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12866 */
12867 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12868 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12869 return ADV_ERROR;
12870 }
12871 asc_dvc->carr_freelist = (ADV_CARR_T *)
12872 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012873
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012874 /*
12875 * The first command issued will be placed in the stopper carrier.
12876 */
12877 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012878
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012879 /*
12880 * Set RISC ICQ physical address start value. Initialize the
12881 * COMMA register to the same value otherwise the RISC will
12882 * prematurely detect a command is available.
12883 */
12884 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
12885 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
12886 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012887
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012888 /*
12889 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12890 */
12891 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12892 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12893 return ADV_ERROR;
12894 }
12895 asc_dvc->carr_freelist = (ADV_CARR_T *)
12896 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012897
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012898 /*
12899 * The first command completed by the RISC will be placed in
12900 * the stopper.
12901 *
12902 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12903 * completed the RISC will set the ASC_RQ_STOPPER bit.
12904 */
12905 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012906
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012907 /*
12908 * Set RISC IRQ physical address start value.
12909 */
12910 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12911 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012912
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012913 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12914 (ADV_INTR_ENABLE_HOST_INTR |
12915 ADV_INTR_ENABLE_GLOBAL_INTR));
12916 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12917 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012918
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012919 /* finally, finally, gentlemen, start your engine */
12920 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012921
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012922 /*
12923 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12924 * Resets should be performed. The RISC has to be running
12925 * to issue a SCSI Bus Reset.
12926 */
12927 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12928 /*
12929 * If the BIOS Signature is present in memory, restore the
12930 * per TID microcode operating variables.
12931 */
12932 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12933 0x55AA) {
12934 /*
12935 * Restore per TID negotiated values.
12936 */
12937 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12938 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12939 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12940 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12941 tagqng_able);
12942 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12943 AdvWriteByteLram(iop_base,
12944 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12945 max_cmd[tid]);
12946 }
12947 } else {
12948 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12949 warn_code = ASC_WARN_BUSRESET_ERROR;
12950 }
12951 }
12952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012953
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012954 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012955}
12956
12957/*
12958 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12959 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12960 * all of this is done.
12961 *
12962 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12963 *
12964 * For a non-fatal error return a warning code. If there are no warnings
12965 * then 0 is returned.
12966 *
12967 * Note: Chip is stopped on entry.
12968 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012969static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012970{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012971 AdvPortAddr iop_base;
12972 ushort warn_code;
12973 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012974
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012975 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012976
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012977 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012978
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012979 /*
12980 * Read the board's EEPROM configuration.
12981 *
12982 * Set default values if a bad checksum is found.
12983 */
12984 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12985 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012986
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012987 /*
12988 * Set EEPROM default values.
12989 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012990 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12991 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012992
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012993 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012994 * Assume the 6 byte board serial number that was read from
12995 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012996 */
12997 eep_config.serial_number_word3 =
12998 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012999
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013000 eep_config.serial_number_word2 =
13001 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013002
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013003 eep_config.serial_number_word1 =
13004 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013005
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013006 AdvSet3550EEPConfig(iop_base, &eep_config);
13007 }
13008 /*
13009 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13010 * EEPROM configuration that was read.
13011 *
13012 * This is the mapping of EEPROM fields to Adv Library fields.
13013 */
13014 asc_dvc->wdtr_able = eep_config.wdtr_able;
13015 asc_dvc->sdtr_able = eep_config.sdtr_able;
13016 asc_dvc->ultra_able = eep_config.ultra_able;
13017 asc_dvc->tagqng_able = eep_config.tagqng_able;
13018 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13019 asc_dvc->max_host_qng = eep_config.max_host_qng;
13020 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13021 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13022 asc_dvc->start_motor = eep_config.start_motor;
13023 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13024 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13025 asc_dvc->no_scam = eep_config.scam_tolerant;
13026 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13027 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13028 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013029
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013030 /*
13031 * Set the host maximum queuing (max. 253, min. 16) and the per device
13032 * maximum queuing (max. 63, min. 4).
13033 */
13034 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13035 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13036 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13037 /* If the value is zero, assume it is uninitialized. */
13038 if (eep_config.max_host_qng == 0) {
13039 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13040 } else {
13041 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13042 }
13043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013044
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013045 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13046 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13047 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13048 /* If the value is zero, assume it is uninitialized. */
13049 if (eep_config.max_dvc_qng == 0) {
13050 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13051 } else {
13052 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13053 }
13054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013055
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013056 /*
13057 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13058 * set 'max_dvc_qng' to 'max_host_qng'.
13059 */
13060 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13061 eep_config.max_dvc_qng = eep_config.max_host_qng;
13062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013063
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013064 /*
13065 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13066 * values based on possibly adjusted EEPROM values.
13067 */
13068 asc_dvc->max_host_qng = eep_config.max_host_qng;
13069 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013071 /*
13072 * If the EEPROM 'termination' field is set to automatic (0), then set
13073 * the ADV_DVC_CFG 'termination' field to automatic also.
13074 *
13075 * If the termination is specified with a non-zero 'termination'
13076 * value check that a legal value is set and set the ADV_DVC_CFG
13077 * 'termination' field appropriately.
13078 */
13079 if (eep_config.termination == 0) {
13080 asc_dvc->cfg->termination = 0; /* auto termination */
13081 } else {
13082 /* Enable manual control with low off / high off. */
13083 if (eep_config.termination == 1) {
13084 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013085
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013086 /* Enable manual control with low off / high on. */
13087 } else if (eep_config.termination == 2) {
13088 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013089
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013090 /* Enable manual control with low on / high on. */
13091 } else if (eep_config.termination == 3) {
13092 asc_dvc->cfg->termination =
13093 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
13094 } else {
13095 /*
13096 * The EEPROM 'termination' field contains a bad value. Use
13097 * automatic termination instead.
13098 */
13099 asc_dvc->cfg->termination = 0;
13100 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13101 }
13102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013103
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013104 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013105}
13106
13107/*
13108 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13109 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13110 * all of this is done.
13111 *
13112 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13113 *
13114 * For a non-fatal error return a warning code. If there are no warnings
13115 * then 0 is returned.
13116 *
13117 * Note: Chip is stopped on entry.
13118 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013119static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013120{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013121 AdvPortAddr iop_base;
13122 ushort warn_code;
13123 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013124 uchar tid, termination;
13125 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013126
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013127 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013128
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013129 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013130
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013131 /*
13132 * Read the board's EEPROM configuration.
13133 *
13134 * Set default values if a bad checksum is found.
13135 */
13136 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13137 eep_config.check_sum) {
13138 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013140 /*
13141 * Set EEPROM default values.
13142 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013143 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13144 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013145
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013146 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013147 * Assume the 6 byte board serial number that was read from
13148 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013149 */
13150 eep_config.serial_number_word3 =
13151 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013152
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013153 eep_config.serial_number_word2 =
13154 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013155
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013156 eep_config.serial_number_word1 =
13157 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013158
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013159 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13160 }
13161 /*
13162 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13163 * EEPROM configuration that was read.
13164 *
13165 * This is the mapping of EEPROM fields to Adv Library fields.
13166 */
13167 asc_dvc->wdtr_able = eep_config.wdtr_able;
13168 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13169 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13170 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13171 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13172 asc_dvc->tagqng_able = eep_config.tagqng_able;
13173 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13174 asc_dvc->max_host_qng = eep_config.max_host_qng;
13175 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13176 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13177 asc_dvc->start_motor = eep_config.start_motor;
13178 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13179 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13180 asc_dvc->no_scam = eep_config.scam_tolerant;
13181 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13182 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13183 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013184
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013185 /*
13186 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13187 * are set, then set an 'sdtr_able' bit for it.
13188 */
13189 asc_dvc->sdtr_able = 0;
13190 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13191 if (tid == 0) {
13192 sdtr_speed = asc_dvc->sdtr_speed1;
13193 } else if (tid == 4) {
13194 sdtr_speed = asc_dvc->sdtr_speed2;
13195 } else if (tid == 8) {
13196 sdtr_speed = asc_dvc->sdtr_speed3;
13197 } else if (tid == 12) {
13198 sdtr_speed = asc_dvc->sdtr_speed4;
13199 }
13200 if (sdtr_speed & ADV_MAX_TID) {
13201 asc_dvc->sdtr_able |= (1 << tid);
13202 }
13203 sdtr_speed >>= 4;
13204 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013205
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013206 /*
13207 * Set the host maximum queuing (max. 253, min. 16) and the per device
13208 * maximum queuing (max. 63, min. 4).
13209 */
13210 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13211 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13212 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13213 /* If the value is zero, assume it is uninitialized. */
13214 if (eep_config.max_host_qng == 0) {
13215 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13216 } else {
13217 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13218 }
13219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013220
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013221 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13222 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13223 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13224 /* If the value is zero, assume it is uninitialized. */
13225 if (eep_config.max_dvc_qng == 0) {
13226 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13227 } else {
13228 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13229 }
13230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013231
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013232 /*
13233 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13234 * set 'max_dvc_qng' to 'max_host_qng'.
13235 */
13236 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13237 eep_config.max_dvc_qng = eep_config.max_host_qng;
13238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013239
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013240 /*
13241 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13242 * values based on possibly adjusted EEPROM values.
13243 */
13244 asc_dvc->max_host_qng = eep_config.max_host_qng;
13245 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013246
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013247 /*
13248 * If the EEPROM 'termination' field is set to automatic (0), then set
13249 * the ADV_DVC_CFG 'termination' field to automatic also.
13250 *
13251 * If the termination is specified with a non-zero 'termination'
13252 * value check that a legal value is set and set the ADV_DVC_CFG
13253 * 'termination' field appropriately.
13254 */
13255 if (eep_config.termination_se == 0) {
13256 termination = 0; /* auto termination for SE */
13257 } else {
13258 /* Enable manual control with low off / high off. */
13259 if (eep_config.termination_se == 1) {
13260 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013261
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013262 /* Enable manual control with low off / high on. */
13263 } else if (eep_config.termination_se == 2) {
13264 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013265
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013266 /* Enable manual control with low on / high on. */
13267 } else if (eep_config.termination_se == 3) {
13268 termination = TERM_SE;
13269 } else {
13270 /*
13271 * The EEPROM 'termination_se' field contains a bad value.
13272 * Use automatic termination instead.
13273 */
13274 termination = 0;
13275 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13276 }
13277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013278
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013279 if (eep_config.termination_lvd == 0) {
13280 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13281 } else {
13282 /* Enable manual control with low off / high off. */
13283 if (eep_config.termination_lvd == 1) {
13284 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013285
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013286 /* Enable manual control with low off / high on. */
13287 } else if (eep_config.termination_lvd == 2) {
13288 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013289
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013290 /* Enable manual control with low on / high on. */
13291 } else if (eep_config.termination_lvd == 3) {
13292 asc_dvc->cfg->termination = termination | TERM_LVD;
13293 } else {
13294 /*
13295 * The EEPROM 'termination_lvd' field contains a bad value.
13296 * Use automatic termination instead.
13297 */
13298 asc_dvc->cfg->termination = termination;
13299 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13300 }
13301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013302
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013303 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013304}
13305
13306/*
13307 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13308 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13309 * all of this is done.
13310 *
13311 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13312 *
13313 * For a non-fatal error return a warning code. If there are no warnings
13314 * then 0 is returned.
13315 *
13316 * Note: Chip is stopped on entry.
13317 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013318static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013319{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013320 AdvPortAddr iop_base;
13321 ushort warn_code;
13322 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013323 uchar tid, termination;
13324 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013325
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013326 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013328 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013329
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013330 /*
13331 * Read the board's EEPROM configuration.
13332 *
13333 * Set default values if a bad checksum is found.
13334 */
13335 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13336 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013337 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013338 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013339
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013340 /*
13341 * Set EEPROM default values.
13342 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013343 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13344 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013345
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013346 if (PCI_FUNC(pdev->devfn) != 0) {
13347 u8 ints;
13348 /*
13349 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13350 * and old Mac system booting problem. The Expansion
13351 * ROM must be disabled in Function 1 for these systems
13352 */
13353 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13354 /*
13355 * Clear the INTAB (bit 11) if the GPIO 0 input
13356 * indicates the Function 1 interrupt line is wired
13357 * to INTB.
13358 *
13359 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13360 * 1 - Function 1 interrupt line wired to INT A.
13361 * 0 - Function 1 interrupt line wired to INT B.
13362 *
13363 * Note: Function 0 is always wired to INTA.
13364 * Put all 5 GPIO bits in input mode and then read
13365 * their input values.
13366 */
13367 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13368 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13369 if ((ints & 0x01) == 0)
13370 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013372
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013373 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013374 * Assume the 6 byte board serial number that was read from
13375 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013376 */
13377 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013378 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013379 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013380 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013381 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013382 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013383
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013384 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013386
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013387 /*
13388 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13389 * EEPROM configuration that was read.
13390 *
13391 * This is the mapping of EEPROM fields to Adv Library fields.
13392 */
13393 asc_dvc->wdtr_able = eep_config.wdtr_able;
13394 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13395 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13396 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13397 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13398 asc_dvc->ppr_able = 0;
13399 asc_dvc->tagqng_able = eep_config.tagqng_able;
13400 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13401 asc_dvc->max_host_qng = eep_config.max_host_qng;
13402 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13403 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13404 asc_dvc->start_motor = eep_config.start_motor;
13405 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13406 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13407 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013408
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013409 /*
13410 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13411 * are set, then set an 'sdtr_able' bit for it.
13412 */
13413 asc_dvc->sdtr_able = 0;
13414 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13415 if (tid == 0) {
13416 sdtr_speed = asc_dvc->sdtr_speed1;
13417 } else if (tid == 4) {
13418 sdtr_speed = asc_dvc->sdtr_speed2;
13419 } else if (tid == 8) {
13420 sdtr_speed = asc_dvc->sdtr_speed3;
13421 } else if (tid == 12) {
13422 sdtr_speed = asc_dvc->sdtr_speed4;
13423 }
13424 if (sdtr_speed & ASC_MAX_TID) {
13425 asc_dvc->sdtr_able |= (1 << tid);
13426 }
13427 sdtr_speed >>= 4;
13428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013429
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013430 /*
13431 * Set the host maximum queuing (max. 253, min. 16) and the per device
13432 * maximum queuing (max. 63, min. 4).
13433 */
13434 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13435 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13436 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13437 /* If the value is zero, assume it is uninitialized. */
13438 if (eep_config.max_host_qng == 0) {
13439 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13440 } else {
13441 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13442 }
13443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013444
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013445 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13446 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13447 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13448 /* If the value is zero, assume it is uninitialized. */
13449 if (eep_config.max_dvc_qng == 0) {
13450 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13451 } else {
13452 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13453 }
13454 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013455
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013456 /*
13457 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13458 * set 'max_dvc_qng' to 'max_host_qng'.
13459 */
13460 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13461 eep_config.max_dvc_qng = eep_config.max_host_qng;
13462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013463
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013464 /*
13465 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13466 * values based on possibly adjusted EEPROM values.
13467 */
13468 asc_dvc->max_host_qng = eep_config.max_host_qng;
13469 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013470
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013471 /*
13472 * If the EEPROM 'termination' field is set to automatic (0), then set
13473 * the ASC_DVC_CFG 'termination' field to automatic also.
13474 *
13475 * If the termination is specified with a non-zero 'termination'
13476 * value check that a legal value is set and set the ASC_DVC_CFG
13477 * 'termination' field appropriately.
13478 */
13479 if (eep_config.termination_se == 0) {
13480 termination = 0; /* auto termination for SE */
13481 } else {
13482 /* Enable manual control with low off / high off. */
13483 if (eep_config.termination_se == 1) {
13484 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013485
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013486 /* Enable manual control with low off / high on. */
13487 } else if (eep_config.termination_se == 2) {
13488 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013489
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013490 /* Enable manual control with low on / high on. */
13491 } else if (eep_config.termination_se == 3) {
13492 termination = TERM_SE;
13493 } else {
13494 /*
13495 * The EEPROM 'termination_se' field contains a bad value.
13496 * Use automatic termination instead.
13497 */
13498 termination = 0;
13499 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13500 }
13501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013502
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013503 if (eep_config.termination_lvd == 0) {
13504 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13505 } else {
13506 /* Enable manual control with low off / high off. */
13507 if (eep_config.termination_lvd == 1) {
13508 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013510 /* Enable manual control with low off / high on. */
13511 } else if (eep_config.termination_lvd == 2) {
13512 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013513
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013514 /* Enable manual control with low on / high on. */
13515 } else if (eep_config.termination_lvd == 3) {
13516 asc_dvc->cfg->termination = termination | TERM_LVD;
13517 } else {
13518 /*
13519 * The EEPROM 'termination_lvd' field contains a bad value.
13520 * Use automatic termination instead.
13521 */
13522 asc_dvc->cfg->termination = termination;
13523 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13524 }
13525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013526
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013527 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013528}
13529
13530/*
13531 * Read EEPROM configuration into the specified buffer.
13532 *
13533 * Return a checksum based on the EEPROM configuration read.
13534 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013535static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013536AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13537{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013538 ushort wval, chksum;
13539 ushort *wbuf;
13540 int eep_addr;
13541 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013542
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013543 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13544 wbuf = (ushort *)cfg_buf;
13545 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013546
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013547 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13548 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13549 wval = AdvReadEEPWord(iop_base, eep_addr);
13550 chksum += wval; /* Checksum is calculated from word values. */
13551 if (*charfields++) {
13552 *wbuf = le16_to_cpu(wval);
13553 } else {
13554 *wbuf = wval;
13555 }
13556 }
13557 /* Read checksum word. */
13558 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13559 wbuf++;
13560 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013561
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013562 /* Read rest of EEPROM not covered by the checksum. */
13563 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13564 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13565 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13566 if (*charfields++) {
13567 *wbuf = le16_to_cpu(*wbuf);
13568 }
13569 }
13570 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013571}
13572
13573/*
13574 * Read EEPROM configuration into the specified buffer.
13575 *
13576 * Return a checksum based on the EEPROM configuration read.
13577 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013578static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013579AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013580{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013581 ushort wval, chksum;
13582 ushort *wbuf;
13583 int eep_addr;
13584 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013585
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013586 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13587 wbuf = (ushort *)cfg_buf;
13588 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013589
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013590 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13591 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13592 wval = AdvReadEEPWord(iop_base, eep_addr);
13593 chksum += wval; /* Checksum is calculated from word values. */
13594 if (*charfields++) {
13595 *wbuf = le16_to_cpu(wval);
13596 } else {
13597 *wbuf = wval;
13598 }
13599 }
13600 /* Read checksum word. */
13601 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13602 wbuf++;
13603 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013604
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013605 /* Read rest of EEPROM not covered by the checksum. */
13606 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13607 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13608 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13609 if (*charfields++) {
13610 *wbuf = le16_to_cpu(*wbuf);
13611 }
13612 }
13613 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013614}
13615
13616/*
13617 * Read EEPROM configuration into the specified buffer.
13618 *
13619 * Return a checksum based on the EEPROM configuration read.
13620 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013621static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013622AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013623{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013624 ushort wval, chksum;
13625 ushort *wbuf;
13626 int eep_addr;
13627 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013628
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013629 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13630 wbuf = (ushort *)cfg_buf;
13631 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013632
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013633 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13634 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13635 wval = AdvReadEEPWord(iop_base, eep_addr);
13636 chksum += wval; /* Checksum is calculated from word values. */
13637 if (*charfields++) {
13638 *wbuf = le16_to_cpu(wval);
13639 } else {
13640 *wbuf = wval;
13641 }
13642 }
13643 /* Read checksum word. */
13644 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13645 wbuf++;
13646 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013647
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013648 /* Read rest of EEPROM not covered by the checksum. */
13649 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13650 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13651 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13652 if (*charfields++) {
13653 *wbuf = le16_to_cpu(*wbuf);
13654 }
13655 }
13656 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013657}
13658
13659/*
13660 * Read the EEPROM from specified location
13661 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013662static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013663{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013664 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13665 ASC_EEP_CMD_READ | eep_word_addr);
13666 AdvWaitEEPCmd(iop_base);
13667 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013668}
13669
13670/*
13671 * Wait for EEPROM command to complete
13672 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013673static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013674{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013675 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013676
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013677 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
13678 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
13679 ASC_EEP_CMD_DONE) {
13680 break;
13681 }
13682 DvcSleepMilliSecond(1);
13683 }
13684 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
13685 0) {
13686 ASC_ASSERT(0);
13687 }
13688 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013689}
13690
13691/*
13692 * Write the EEPROM from 'cfg_buf'.
13693 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013694void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013695AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13696{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013697 ushort *wbuf;
13698 ushort addr, chksum;
13699 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013700
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013701 wbuf = (ushort *)cfg_buf;
13702 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13703 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013704
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013705 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13706 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013707
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013708 /*
13709 * Write EEPROM from word 0 to word 20.
13710 */
13711 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13712 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13713 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013714
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013715 if (*charfields++) {
13716 word = cpu_to_le16(*wbuf);
13717 } else {
13718 word = *wbuf;
13719 }
13720 chksum += *wbuf; /* Checksum is calculated from word values. */
13721 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13722 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13723 ASC_EEP_CMD_WRITE | addr);
13724 AdvWaitEEPCmd(iop_base);
13725 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13726 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013727
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013728 /*
13729 * Write EEPROM checksum at word 21.
13730 */
13731 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13732 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13733 AdvWaitEEPCmd(iop_base);
13734 wbuf++;
13735 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013736
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013737 /*
13738 * Write EEPROM OEM name at words 22 to 29.
13739 */
13740 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13741 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13742 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013743
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013744 if (*charfields++) {
13745 word = cpu_to_le16(*wbuf);
13746 } else {
13747 word = *wbuf;
13748 }
13749 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13750 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13751 ASC_EEP_CMD_WRITE | addr);
13752 AdvWaitEEPCmd(iop_base);
13753 }
13754 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13755 AdvWaitEEPCmd(iop_base);
13756 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013757}
13758
13759/*
13760 * Write the EEPROM from 'cfg_buf'.
13761 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013762void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013763AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013764{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013765 ushort *wbuf;
13766 ushort *charfields;
13767 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013768
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013769 wbuf = (ushort *)cfg_buf;
13770 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13771 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013772
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013773 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13774 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013775
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013776 /*
13777 * Write EEPROM from word 0 to word 20.
13778 */
13779 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13780 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13781 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013782
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013783 if (*charfields++) {
13784 word = cpu_to_le16(*wbuf);
13785 } else {
13786 word = *wbuf;
13787 }
13788 chksum += *wbuf; /* Checksum is calculated from word values. */
13789 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13790 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13791 ASC_EEP_CMD_WRITE | addr);
13792 AdvWaitEEPCmd(iop_base);
13793 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013795
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013796 /*
13797 * Write EEPROM checksum at word 21.
13798 */
13799 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13800 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13801 AdvWaitEEPCmd(iop_base);
13802 wbuf++;
13803 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013804
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013805 /*
13806 * Write EEPROM OEM name at words 22 to 29.
13807 */
13808 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13809 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13810 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013811
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013812 if (*charfields++) {
13813 word = cpu_to_le16(*wbuf);
13814 } else {
13815 word = *wbuf;
13816 }
13817 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13818 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13819 ASC_EEP_CMD_WRITE | addr);
13820 AdvWaitEEPCmd(iop_base);
13821 }
13822 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13823 AdvWaitEEPCmd(iop_base);
13824 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013825}
13826
13827/*
13828 * Write the EEPROM from 'cfg_buf'.
13829 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013830void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013831AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013832{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013833 ushort *wbuf;
13834 ushort *charfields;
13835 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013836
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013837 wbuf = (ushort *)cfg_buf;
13838 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13839 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013841 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13842 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013843
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013844 /*
13845 * Write EEPROM from word 0 to word 20.
13846 */
13847 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13848 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13849 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013850
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013851 if (*charfields++) {
13852 word = cpu_to_le16(*wbuf);
13853 } else {
13854 word = *wbuf;
13855 }
13856 chksum += *wbuf; /* Checksum is calculated from word values. */
13857 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13858 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13859 ASC_EEP_CMD_WRITE | addr);
13860 AdvWaitEEPCmd(iop_base);
13861 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013863
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013864 /*
13865 * Write EEPROM checksum at word 21.
13866 */
13867 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13868 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13869 AdvWaitEEPCmd(iop_base);
13870 wbuf++;
13871 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013872
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013873 /*
13874 * Write EEPROM OEM name at words 22 to 29.
13875 */
13876 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13877 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13878 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013879
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013880 if (*charfields++) {
13881 word = cpu_to_le16(*wbuf);
13882 } else {
13883 word = *wbuf;
13884 }
13885 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13886 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13887 ASC_EEP_CMD_WRITE | addr);
13888 AdvWaitEEPCmd(iop_base);
13889 }
13890 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13891 AdvWaitEEPCmd(iop_base);
13892 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013893}
13894
13895/* a_advlib.c */
13896/*
13897 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
13898 *
13899 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
13900 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
13901 * RISC to notify it a new command is ready to be executed.
13902 *
13903 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
13904 * set to SCSI_MAX_RETRY.
13905 *
13906 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
13907 * for DMA addresses or math operations are byte swapped to little-endian
13908 * order.
13909 *
13910 * Return:
13911 * ADV_SUCCESS(1) - The request was successfully queued.
13912 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
13913 * request completes.
13914 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
13915 * host IC error.
13916 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013917static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013918{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013919 ulong last_int_level;
13920 AdvPortAddr iop_base;
13921 ADV_DCNT req_size;
13922 ADV_PADDR req_paddr;
13923 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013924
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013925 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013926
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013927 /*
13928 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
13929 */
13930 if (scsiq->target_id > ADV_MAX_TID) {
13931 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
13932 scsiq->done_status = QD_WITH_ERROR;
13933 return ADV_ERROR;
13934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013935
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013936 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013937
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013938 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070013939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013940 /*
13941 * Allocate a carrier ensuring at least one carrier always
13942 * remains on the freelist and initialize fields.
13943 */
13944 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
13945 DvcLeaveCritical(last_int_level);
13946 return ADV_BUSY;
13947 }
13948 asc_dvc->carr_freelist = (ADV_CARR_T *)
13949 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
13950 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013951
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013952 /*
13953 * Set the carrier to be a stopper by setting 'next_vpa'
13954 * to the stopper value. The current stopper will be changed
13955 * below to point to the new stopper.
13956 */
13957 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013958
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013959 /*
13960 * Clear the ADV_SCSI_REQ_Q done flag.
13961 */
13962 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013963
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013964 req_size = sizeof(ADV_SCSI_REQ_Q);
13965 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
13966 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013967
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013968 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
13969 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013970
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013971 /* Wait for assertion before making little-endian */
13972 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013973
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013974 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
13975 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
13976 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013977
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013978 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
13979 /*
13980 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
13981 * order during initialization.
13982 */
13983 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013984
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013985 /*
13986 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
13987 * the microcode. The newly allocated stopper will become the new
13988 * stopper.
13989 */
13990 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013991
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013992 /*
13993 * Set the 'next_vpa' pointer for the old stopper to be the
13994 * physical address of the new stopper. The RISC can only
13995 * follow physical addresses.
13996 */
13997 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013998
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013999 /*
14000 * Set the host adapter stopper pointer to point to the new carrier.
14001 */
14002 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014003
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014004 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14005 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14006 /*
14007 * Tickle the RISC to tell it to read its Command Queue Head pointer.
14008 */
14009 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
14010 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14011 /*
14012 * Clear the tickle value. In the ASC-3550 the RISC flag
14013 * command 'clr_tickle_a' does not work unless the host
14014 * value is cleared.
14015 */
14016 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14017 ADV_TICKLE_NOP);
14018 }
14019 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14020 /*
14021 * Notify the RISC a carrier is ready by writing the physical
14022 * address of the new carrier stopper to the COMMA register.
14023 */
14024 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
14025 le32_to_cpu(new_carrp->carr_pa));
14026 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014027
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014028 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014029
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014030 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014031}
14032
14033/*
14034 * Reset SCSI Bus and purge all outstanding requests.
14035 *
14036 * Return Value:
14037 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
14038 * ADV_FALSE(0) - Microcode command failed.
14039 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
14040 * may be hung which requires driver recovery.
14041 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014042static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014043{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014044 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014045
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014046 /*
14047 * Send the SCSI Bus Reset idle start idle command which asserts
14048 * the SCSI Bus Reset signal.
14049 */
14050 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
14051 if (status != ADV_TRUE) {
14052 return status;
14053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014054
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014055 /*
14056 * Delay for the specified SCSI Bus Reset hold time.
14057 *
14058 * The hold time delay is done on the host because the RISC has no
14059 * microsecond accurate timer.
14060 */
14061 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014062
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014063 /*
14064 * Send the SCSI Bus Reset end idle command which de-asserts
14065 * the SCSI Bus Reset signal and purges any pending requests.
14066 */
14067 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
14068 if (status != ADV_TRUE) {
14069 return status;
14070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014071
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014072 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014073
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014074 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014075}
14076
14077/*
14078 * Reset chip and SCSI Bus.
14079 *
14080 * Return Value:
14081 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
14082 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
14083 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014084static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014085{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014086 int status;
14087 ushort wdtr_able, sdtr_able, tagqng_able;
14088 ushort ppr_able = 0;
14089 uchar tid, max_cmd[ADV_MAX_TID + 1];
14090 AdvPortAddr iop_base;
14091 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014092
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014093 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014094
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014095 /*
14096 * Save current per TID negotiated values.
14097 */
14098 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14099 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14100 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14101 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14102 }
14103 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14104 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14105 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14106 max_cmd[tid]);
14107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014108
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014109 /*
14110 * Force the AdvInitAsc3550/38C0800Driver() function to
14111 * perform a SCSI Bus Reset by clearing the BIOS signature word.
14112 * The initialization functions assumes a SCSI Bus Reset is not
14113 * needed if the BIOS signature word is present.
14114 */
14115 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
14116 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014117
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014118 /*
14119 * Stop chip and reset it.
14120 */
14121 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
14122 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14123 DvcSleepMilliSecond(100);
14124 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
14125 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014126
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014127 /*
14128 * Reset Adv Library error code, if any, and try
14129 * re-initializing the chip.
14130 */
14131 asc_dvc->err_code = 0;
14132 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14133 status = AdvInitAsc38C1600Driver(asc_dvc);
14134 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14135 status = AdvInitAsc38C0800Driver(asc_dvc);
14136 } else {
14137 status = AdvInitAsc3550Driver(asc_dvc);
14138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014140 /* Translate initialization return value to status value. */
14141 if (status == 0) {
14142 status = ADV_TRUE;
14143 } else {
14144 status = ADV_FALSE;
14145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014146
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014147 /*
14148 * Restore the BIOS signature word.
14149 */
14150 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014151
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014152 /*
14153 * Restore per TID negotiated values.
14154 */
14155 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14156 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14157 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14158 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14159 }
14160 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14161 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14162 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14163 max_cmd[tid]);
14164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014165
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014166 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014167}
14168
14169/*
14170 * Adv Library Interrupt Service Routine
14171 *
14172 * This function is called by a driver's interrupt service routine.
14173 * The function disables and re-enables interrupts.
14174 *
14175 * When a microcode idle command is completed, the ADV_DVC_VAR
14176 * 'idle_cmd_done' field is set to ADV_TRUE.
14177 *
14178 * Note: AdvISR() can be called when interrupts are disabled or even
14179 * when there is no hardware interrupt condition present. It will
14180 * always check for completed idle commands and microcode requests.
14181 * This is an important feature that shouldn't be changed because it
14182 * allows commands to be completed from polling mode loops.
14183 *
14184 * Return:
14185 * ADV_TRUE(1) - interrupt was pending
14186 * ADV_FALSE(0) - no interrupt was pending
14187 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014188static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014189{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014190 AdvPortAddr iop_base;
14191 uchar int_stat;
14192 ushort target_bit;
14193 ADV_CARR_T *free_carrp;
14194 ADV_VADDR irq_next_vpa;
14195 int flags;
14196 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014197
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014198 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014200 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014201
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014202 /* Reading the register clears the interrupt. */
14203 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014204
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014205 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
14206 ADV_INTR_STATUS_INTRC)) == 0) {
14207 DvcLeaveCritical(flags);
14208 return ADV_FALSE;
14209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014210
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014211 /*
14212 * Notify the driver of an asynchronous microcode condition by
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014213 * calling the adv_async_callback function. The function
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014214 * is passed the microcode ASC_MC_INTRB_CODE byte value.
14215 */
14216 if (int_stat & ADV_INTR_STATUS_INTRB) {
14217 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014218
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014219 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014220
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014221 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14222 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14223 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
14224 asc_dvc->carr_pending_cnt != 0) {
14225 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14226 ADV_TICKLE_A);
14227 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14228 AdvWriteByteRegister(iop_base,
14229 IOPB_TICKLE,
14230 ADV_TICKLE_NOP);
14231 }
14232 }
14233 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014234
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014235 adv_async_callback(asc_dvc, intrb_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014237
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014238 /*
14239 * Check if the IRQ stopper carrier contains a completed request.
14240 */
14241 while (((irq_next_vpa =
14242 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
14243 /*
14244 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
14245 * The RISC will have set 'areq_vpa' to a virtual address.
14246 *
14247 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
14248 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
14249 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
14250 * in AdvExeScsiQueue().
14251 */
14252 scsiq = (ADV_SCSI_REQ_Q *)
14253 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014254
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014255 /*
14256 * Request finished with good status and the queue was not
14257 * DMAed to host memory by the firmware. Set all status fields
14258 * to indicate good status.
14259 */
14260 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
14261 scsiq->done_status = QD_NO_ERROR;
14262 scsiq->host_status = scsiq->scsi_status = 0;
14263 scsiq->data_cnt = 0L;
14264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014265
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014266 /*
14267 * Advance the stopper pointer to the next carrier
14268 * ignoring the lower four bits. Free the previous
14269 * stopper carrier.
14270 */
14271 free_carrp = asc_dvc->irq_sp;
14272 asc_dvc->irq_sp = (ADV_CARR_T *)
14273 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014274
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014275 free_carrp->next_vpa =
14276 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14277 asc_dvc->carr_freelist = free_carrp;
14278 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014279
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014280 ASC_ASSERT(scsiq != NULL);
14281 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014282
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014283 /*
14284 * Clear request microcode control flag.
14285 */
14286 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014287
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014288 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014289 * Notify the driver of the completed request by passing
14290 * the ADV_SCSI_REQ_Q pointer to its callback function.
14291 */
14292 scsiq->a_flag |= ADV_SCSIQ_DONE;
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014293 adv_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014294 /*
14295 * Note: After the driver callback function is called, 'scsiq'
14296 * can no longer be referenced.
14297 *
14298 * Fall through and continue processing other completed
14299 * requests...
14300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014301
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014302 /*
14303 * Disable interrupts again in case the driver inadvertently
14304 * enabled interrupts in its callback function.
14305 *
14306 * The DvcEnterCritical() return value is ignored, because
14307 * the 'flags' saved when AdvISR() was first entered will be
14308 * used to restore the interrupt flag on exit.
14309 */
14310 (void)DvcEnterCritical();
14311 }
14312 DvcLeaveCritical(flags);
14313 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014314}
14315
14316/*
14317 * Send an idle command to the chip and wait for completion.
14318 *
14319 * Command completion is polled for once per microsecond.
14320 *
14321 * The function can be called from anywhere including an interrupt handler.
14322 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
14323 * functions to prevent reentrancy.
14324 *
14325 * Return Values:
14326 * ADV_TRUE - command completed successfully
14327 * ADV_FALSE - command failed
14328 * ADV_ERROR - command timed out
14329 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014330static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070014331AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014332 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014333{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014334 ulong last_int_level;
14335 int result;
14336 ADV_DCNT i, j;
14337 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014338
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014339 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014340
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014341 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014342
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014343 /*
14344 * Clear the idle command status which is set by the microcode
14345 * to a non-zero value to indicate when the command is completed.
14346 * The non-zero result is one of the IDLE_CMD_STATUS_* values
14347 * defined in a_advlib.h.
14348 */
14349 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014350
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014351 /*
14352 * Write the idle command value after the idle command parameter
14353 * has been written to avoid a race condition. If the order is not
14354 * followed, the microcode may process the idle command before the
14355 * parameters have been written to LRAM.
14356 */
14357 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
14358 cpu_to_le32(idle_cmd_parameter));
14359 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014360
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014361 /*
14362 * Tickle the RISC to tell it to process the idle command.
14363 */
14364 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
14365 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14366 /*
14367 * Clear the tickle value. In the ASC-3550 the RISC flag
14368 * command 'clr_tickle_b' does not work unless the host
14369 * value is cleared.
14370 */
14371 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
14372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014374 /* Wait for up to 100 millisecond for the idle command to timeout. */
14375 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
14376 /* Poll once each microsecond for command completion. */
14377 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
14378 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
14379 result);
14380 if (result != 0) {
14381 DvcLeaveCritical(last_int_level);
14382 return result;
14383 }
14384 DvcDelayMicroSecond(asc_dvc, (ushort)1);
14385 }
14386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014387
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014388 ASC_ASSERT(0); /* The idle command should never timeout. */
14389 DvcLeaveCritical(last_int_level);
14390 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014391}
14392
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014393static int __devinit
14394advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
14395{
14396 int req_cnt = 0;
14397 adv_req_t *reqp = NULL;
14398 int sg_cnt = 0;
14399 adv_sgblk_t *sgp;
14400 int warn_code, err_code;
14401
14402 /*
14403 * Allocate buffer carrier structures. The total size
14404 * is about 4 KB, so allocate all at once.
14405 */
14406 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
14407 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
14408
14409 if (!boardp->carrp)
14410 goto kmalloc_failed;
14411
14412 /*
14413 * Allocate up to 'max_host_qng' request structures for the Wide
14414 * board. The total size is about 16 KB, so allocate all at once.
14415 * If the allocation fails decrement and try again.
14416 */
14417 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
14418 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
14419
14420 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
14421 "bytes %lu\n", reqp, req_cnt,
14422 (ulong)sizeof(adv_req_t) * req_cnt);
14423
14424 if (reqp)
14425 break;
14426 }
14427
14428 if (!reqp)
14429 goto kmalloc_failed;
14430
14431 boardp->orig_reqp = reqp;
14432
14433 /*
14434 * Allocate up to ADV_TOT_SG_BLOCK request structures for
14435 * the Wide board. Each structure is about 136 bytes.
14436 */
14437 boardp->adv_sgblkp = NULL;
14438 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
14439 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
14440
14441 if (!sgp)
14442 break;
14443
14444 sgp->next_sgblkp = boardp->adv_sgblkp;
14445 boardp->adv_sgblkp = sgp;
14446
14447 }
14448
14449 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
14450 sg_cnt, sizeof(adv_sgblk_t),
14451 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
14452
14453 if (!boardp->adv_sgblkp)
14454 goto kmalloc_failed;
14455
14456 adv_dvc_varp->carrier_buf = boardp->carrp;
14457
14458 /*
14459 * Point 'adv_reqp' to the request structures and
14460 * link them together.
14461 */
14462 req_cnt--;
14463 reqp[req_cnt].next_reqp = NULL;
14464 for (; req_cnt > 0; req_cnt--) {
14465 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
14466 }
14467 boardp->adv_reqp = &reqp[0];
14468
14469 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14470 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
14471 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
14472 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14473 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
14474 "\n");
14475 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
14476 } else {
14477 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
14478 "\n");
14479 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
14480 }
14481 err_code = adv_dvc_varp->err_code;
14482
14483 if (warn_code || err_code) {
14484 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
14485 " error 0x%x\n", boardp->id, warn_code, err_code);
14486 }
14487
14488 goto exit;
14489
14490 kmalloc_failed:
14491 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
14492 "failed\n", boardp->id);
14493 err_code = ADV_ERROR;
14494 exit:
14495 return err_code;
14496}
14497
14498static void advansys_wide_free_mem(asc_board_t *boardp)
14499{
14500 kfree(boardp->carrp);
14501 boardp->carrp = NULL;
14502 kfree(boardp->orig_reqp);
14503 boardp->orig_reqp = boardp->adv_reqp = NULL;
14504 while (boardp->adv_sgblkp) {
14505 adv_sgblk_t *sgp = boardp->adv_sgblkp;
14506 boardp->adv_sgblkp = sgp->next_sgblkp;
14507 kfree(sgp);
14508 }
14509}
14510
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014511static struct Scsi_Host *__devinit
14512advansys_board_found(int iop, struct device *dev, int bus_type)
14513{
14514 struct Scsi_Host *shost;
14515 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
14516 asc_board_t *boardp;
14517 ASC_DVC_VAR *asc_dvc_varp = NULL;
14518 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014519 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014520 int warn_code, err_code;
14521 int ret;
14522
14523 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014524 * Register the adapter, get its configuration, and
14525 * initialize it.
14526 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014527 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
14528 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014529 if (!shost)
14530 return NULL;
14531
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014532 /* Initialize private per board data */
14533 boardp = ASC_BOARDP(shost);
14534 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014535 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014536 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014537 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014538
14539 /*
14540 * Handle both narrow and wide boards.
14541 *
14542 * If a Wide board was detected, set the board structure
14543 * wide board flag. Set-up the board structure based on
14544 * the board type.
14545 */
14546#ifdef CONFIG_PCI
14547 if (bus_type == ASC_IS_PCI &&
14548 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14549 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14550 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
14551 boardp->flags |= ASC_IS_WIDE_BOARD;
14552 }
14553#endif /* CONFIG_PCI */
14554
14555 if (ASC_NARROW_BOARD(boardp)) {
14556 ASC_DBG(1, "advansys_board_found: narrow board\n");
14557 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
14558 asc_dvc_varp->bus_type = bus_type;
14559 asc_dvc_varp->drv_ptr = boardp;
14560 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
14561 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
14562 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014563 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014564#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014565 ASC_DBG(1, "advansys_board_found: wide board\n");
14566 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
14567 adv_dvc_varp->drv_ptr = boardp;
14568 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014569 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
14570 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
14571 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
14572 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
14573 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
14574 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
14575 } else {
14576 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
14577 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
14578 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014579
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014580 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
14581 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
14582 boardp->asc_n_io_port);
14583 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014584 ASC_PRINT3
14585 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014586 boardp->id, pci_resource_start(pdev, 1),
14587 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014588 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014589 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014590 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060014591 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014592 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014593
14594 /*
14595 * Even though it isn't used to access wide boards, other
14596 * than for the debug line below, save I/O Port address so
14597 * that it can be reported.
14598 */
14599 boardp->ioport = iop;
14600
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014601 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
14602 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
14603 (ushort)inpw(iop));
14604#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014605 }
14606
14607#ifdef CONFIG_PROC_FS
14608 /*
14609 * Allocate buffer for printing information from
14610 * /proc/scsi/advansys/[0...].
14611 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014612 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
14613 if (!boardp->prtbuf) {
14614 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
14615 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
14616 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014617 }
14618#endif /* CONFIG_PROC_FS */
14619
14620 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014621 /*
14622 * Set the board bus type and PCI IRQ before
14623 * calling AscInitGetConfig().
14624 */
14625 switch (asc_dvc_varp->bus_type) {
14626#ifdef CONFIG_ISA
14627 case ASC_IS_ISA:
14628 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014629 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014630 break;
14631 case ASC_IS_VL:
14632 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014633 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014634 break;
14635 case ASC_IS_EISA:
14636 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014637 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014638 break;
14639#endif /* CONFIG_ISA */
14640#ifdef CONFIG_PCI
14641 case ASC_IS_PCI:
14642 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014643 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014644 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014645 break;
14646#endif /* CONFIG_PCI */
14647 default:
14648 ASC_PRINT2
14649 ("advansys_board_found: board %d: unknown adapter type: %d\n",
14650 boardp->id, asc_dvc_varp->bus_type);
14651 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014652 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014653 break;
14654 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014655
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014656 /*
14657 * NOTE: AscInitGetConfig() may change the board's
14658 * bus_type value. The bus_type value should no
14659 * longer be used. If the bus_type field must be
14660 * referenced only use the bit-wise AND operator "&".
14661 */
14662 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014663 err_code = AscInitGetConfig(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014664 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014665#ifdef CONFIG_PCI
14666 /*
14667 * For Wide boards set PCI information before calling
14668 * AdvInitGetConfig().
14669 */
14670 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
14671 shost->unchecked_isa_dma = FALSE;
14672 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014673 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014674
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014675 err_code = AdvInitGetConfig(pdev, boardp);
14676#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014677 }
14678
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014679 if (err_code != 0)
14680 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014681
14682 /*
14683 * Save the EEPROM configuration so that it can be displayed
14684 * from /proc/scsi/advansys/[0...].
14685 */
14686 if (ASC_NARROW_BOARD(boardp)) {
14687
14688 ASCEEP_CONFIG *ep;
14689
14690 /*
14691 * Set the adapter's target id bit in the 'init_tidmask' field.
14692 */
14693 boardp->init_tidmask |=
14694 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
14695
14696 /*
14697 * Save EEPROM settings for the board.
14698 */
14699 ep = &boardp->eep_config.asc_eep;
14700
14701 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
14702 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
14703 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
14704 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
14705 ep->start_motor = asc_dvc_varp->start_motor;
14706 ep->cntl = asc_dvc_varp->dvc_cntl;
14707 ep->no_scam = asc_dvc_varp->no_scam;
14708 ep->max_total_qng = asc_dvc_varp->max_total_qng;
14709 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
14710 /* 'max_tag_qng' is set to the same value for every device. */
14711 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
14712 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
14713 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
14714 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
14715 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
14716 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
14717 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
14718
14719 /*
14720 * Modify board configuration.
14721 */
14722 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014723 err_code = AscInitSetConfig(pdev, boardp);
14724 if (err_code)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014725 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014726
14727 /*
14728 * Finish initializing the 'Scsi_Host' structure.
14729 */
14730 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
14731 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
14732 shost->irq = asc_dvc_varp->irq_no;
14733 }
14734 } else {
14735 ADVEEP_3550_CONFIG *ep_3550;
14736 ADVEEP_38C0800_CONFIG *ep_38C0800;
14737 ADVEEP_38C1600_CONFIG *ep_38C1600;
14738
14739 /*
14740 * Save Wide EEP Configuration Information.
14741 */
14742 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14743 ep_3550 = &boardp->eep_config.adv_3550_eep;
14744
14745 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
14746 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
14747 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14748 ep_3550->termination = adv_dvc_varp->cfg->termination;
14749 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
14750 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
14751 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
14752 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
14753 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
14754 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
14755 ep_3550->start_motor = adv_dvc_varp->start_motor;
14756 ep_3550->scsi_reset_delay =
14757 adv_dvc_varp->scsi_reset_wait;
14758 ep_3550->serial_number_word1 =
14759 adv_dvc_varp->cfg->serial1;
14760 ep_3550->serial_number_word2 =
14761 adv_dvc_varp->cfg->serial2;
14762 ep_3550->serial_number_word3 =
14763 adv_dvc_varp->cfg->serial3;
14764 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14765 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
14766
14767 ep_38C0800->adapter_scsi_id =
14768 adv_dvc_varp->chip_scsi_id;
14769 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
14770 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14771 ep_38C0800->termination_lvd =
14772 adv_dvc_varp->cfg->termination;
14773 ep_38C0800->disc_enable =
14774 adv_dvc_varp->cfg->disc_enable;
14775 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
14776 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
14777 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14778 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14779 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14780 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14781 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14782 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14783 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
14784 ep_38C0800->scsi_reset_delay =
14785 adv_dvc_varp->scsi_reset_wait;
14786 ep_38C0800->serial_number_word1 =
14787 adv_dvc_varp->cfg->serial1;
14788 ep_38C0800->serial_number_word2 =
14789 adv_dvc_varp->cfg->serial2;
14790 ep_38C0800->serial_number_word3 =
14791 adv_dvc_varp->cfg->serial3;
14792 } else {
14793 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
14794
14795 ep_38C1600->adapter_scsi_id =
14796 adv_dvc_varp->chip_scsi_id;
14797 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
14798 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14799 ep_38C1600->termination_lvd =
14800 adv_dvc_varp->cfg->termination;
14801 ep_38C1600->disc_enable =
14802 adv_dvc_varp->cfg->disc_enable;
14803 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
14804 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
14805 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14806 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14807 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14808 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14809 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14810 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14811 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
14812 ep_38C1600->scsi_reset_delay =
14813 adv_dvc_varp->scsi_reset_wait;
14814 ep_38C1600->serial_number_word1 =
14815 adv_dvc_varp->cfg->serial1;
14816 ep_38C1600->serial_number_word2 =
14817 adv_dvc_varp->cfg->serial2;
14818 ep_38C1600->serial_number_word3 =
14819 adv_dvc_varp->cfg->serial3;
14820 }
14821
14822 /*
14823 * Set the adapter's target id bit in the 'init_tidmask' field.
14824 */
14825 boardp->init_tidmask |=
14826 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014827 }
14828
14829 /*
14830 * Channels are numbered beginning with 0. For AdvanSys one host
14831 * structure supports one channel. Multi-channel boards have a
14832 * separate host structure for each channel.
14833 */
14834 shost->max_channel = 0;
14835 if (ASC_NARROW_BOARD(boardp)) {
14836 shost->max_id = ASC_MAX_TID + 1;
14837 shost->max_lun = ASC_MAX_LUN + 1;
14838
14839 shost->io_port = asc_dvc_varp->iop_base;
14840 boardp->asc_n_io_port = ASC_IOADR_GAP;
14841 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
14842
14843 /* Set maximum number of queues the adapter can handle. */
14844 shost->can_queue = asc_dvc_varp->max_total_qng;
14845 } else {
14846 shost->max_id = ADV_MAX_TID + 1;
14847 shost->max_lun = ADV_MAX_LUN + 1;
14848
14849 /*
14850 * Save the I/O Port address and length even though
14851 * I/O ports are not used to access Wide boards.
14852 * Instead the Wide boards are accessed with
14853 * PCI Memory Mapped I/O.
14854 */
14855 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014856
14857 shost->this_id = adv_dvc_varp->chip_scsi_id;
14858
14859 /* Set maximum number of queues the adapter can handle. */
14860 shost->can_queue = adv_dvc_varp->max_host_qng;
14861 }
14862
14863 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014864 * Following v1.3.89, 'cmd_per_lun' is no longer needed
14865 * and should be set to zero.
14866 *
14867 * But because of a bug introduced in v1.3.89 if the driver is
14868 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
14869 * SCSI function 'allocate_device' will panic. To allow the driver
14870 * to work as a module in these kernels set 'cmd_per_lun' to 1.
14871 *
14872 * Note: This is wrong. cmd_per_lun should be set to the depth
14873 * you want on untagged devices always.
14874 #ifdef MODULE
14875 */
14876 shost->cmd_per_lun = 1;
14877/* #else
14878 shost->cmd_per_lun = 0;
14879#endif */
14880
14881 /*
14882 * Set the maximum number of scatter-gather elements the
14883 * adapter can handle.
14884 */
14885 if (ASC_NARROW_BOARD(boardp)) {
14886 /*
14887 * Allow two commands with 'sg_tablesize' scatter-gather
14888 * elements to be executed simultaneously. This value is
14889 * the theoretical hardware limit. It may be decreased
14890 * below.
14891 */
14892 shost->sg_tablesize =
14893 (((asc_dvc_varp->max_total_qng - 2) / 2) *
14894 ASC_SG_LIST_PER_Q) + 1;
14895 } else {
14896 shost->sg_tablesize = ADV_MAX_SG_LIST;
14897 }
14898
14899 /*
14900 * The value of 'sg_tablesize' can not exceed the SCSI
14901 * mid-level driver definition of SG_ALL. SG_ALL also
14902 * must not be exceeded, because it is used to define the
14903 * size of the scatter-gather table in 'struct asc_sg_head'.
14904 */
14905 if (shost->sg_tablesize > SG_ALL) {
14906 shost->sg_tablesize = SG_ALL;
14907 }
14908
14909 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
14910
14911 /* BIOS start address. */
14912 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014913 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
14914 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014915 } else {
14916 /*
14917 * Fill-in BIOS board variables. The Wide BIOS saves
14918 * information in LRAM that is used by the driver.
14919 */
14920 AdvReadWordLram(adv_dvc_varp->iop_base,
14921 BIOS_SIGNATURE, boardp->bios_signature);
14922 AdvReadWordLram(adv_dvc_varp->iop_base,
14923 BIOS_VERSION, boardp->bios_version);
14924 AdvReadWordLram(adv_dvc_varp->iop_base,
14925 BIOS_CODESEG, boardp->bios_codeseg);
14926 AdvReadWordLram(adv_dvc_varp->iop_base,
14927 BIOS_CODELEN, boardp->bios_codelen);
14928
14929 ASC_DBG2(1,
14930 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
14931 boardp->bios_signature, boardp->bios_version);
14932
14933 ASC_DBG2(1,
14934 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
14935 boardp->bios_codeseg, boardp->bios_codelen);
14936
14937 /*
14938 * If the BIOS saved a valid signature, then fill in
14939 * the BIOS code segment base address.
14940 */
14941 if (boardp->bios_signature == 0x55AA) {
14942 /*
14943 * Convert x86 realmode code segment to a linear
14944 * address by shifting left 4.
14945 */
14946 shost->base = ((ulong)boardp->bios_codeseg << 4);
14947 } else {
14948 shost->base = 0;
14949 }
14950 }
14951
14952 /*
14953 * Register Board Resources - I/O Port, DMA, IRQ
14954 */
14955
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014956 /* Register DMA Channel for Narrow boards. */
14957 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14958#ifdef CONFIG_ISA
14959 if (ASC_NARROW_BOARD(boardp)) {
14960 /* Register DMA channel for ISA bus. */
14961 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14962 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014963 ret = request_dma(shost->dma_channel, "advansys");
14964 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014965 ASC_PRINT3
14966 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14967 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014968 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014969 }
14970 AscEnableIsaDma(shost->dma_channel);
14971 }
14972 }
14973#endif /* CONFIG_ISA */
14974
14975 /* Register IRQ Number. */
14976 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014977
14978 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
14979 "advansys", shost);
14980
14981 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014982 if (ret == -EBUSY) {
14983 ASC_PRINT2
14984 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
14985 boardp->id, shost->irq);
14986 } else if (ret == -EINVAL) {
14987 ASC_PRINT2
14988 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
14989 boardp->id, shost->irq);
14990 } else {
14991 ASC_PRINT3
14992 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
14993 boardp->id, shost->irq, ret);
14994 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014995 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014996 }
14997
14998 /*
14999 * Initialize board RISC chip and enable interrupts.
15000 */
15001 if (ASC_NARROW_BOARD(boardp)) {
15002 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
15003 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
15004 err_code = asc_dvc_varp->err_code;
15005
15006 if (warn_code || err_code) {
15007 ASC_PRINT4
15008 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
15009 boardp->id,
15010 asc_dvc_varp->init_state, warn_code, err_code);
15011 }
15012 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015013 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015014 }
15015
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015016 if (err_code != 0)
15017 goto err_free_wide_mem;
15018
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015019 ASC_DBG_PRT_SCSI_HOST(2, shost);
15020
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015021 ret = scsi_add_host(shost, dev);
15022 if (ret)
15023 goto err_free_wide_mem;
15024
15025 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015026 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015027
15028 err_free_wide_mem:
15029 advansys_wide_free_mem(boardp);
15030 free_irq(shost->irq, shost);
15031 err_free_dma:
15032 if (shost->dma_channel != NO_ISA_DMA)
15033 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015034 err_free_proc:
15035 kfree(boardp->prtbuf);
15036 err_unmap:
15037 if (boardp->ioremap_addr)
15038 iounmap(boardp->ioremap_addr);
15039 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015040 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015041 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015042}
15043
15044/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015045 * advansys_release()
15046 *
15047 * Release resources allocated for a single AdvanSys adapter.
15048 */
15049static int advansys_release(struct Scsi_Host *shost)
15050{
15051 asc_board_t *boardp;
15052
15053 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015054 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015055 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015056 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015057 if (shost->dma_channel != NO_ISA_DMA) {
15058 ASC_DBG(1, "advansys_release: free_dma()\n");
15059 free_dma(shost->dma_channel);
15060 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015061 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015062 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015063 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015064 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015065 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015066 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015067 ASC_DBG(1, "advansys_release: end\n");
15068 return 0;
15069}
15070
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015071static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
15072 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
15073 0x0210, 0x0230, 0x0250, 0x0330
15074};
15075
15076static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
15077{
15078 PortAddr iop_base = _asc_def_iop_base[id];
15079 struct Scsi_Host *shost;
15080
15081 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015082 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
15083 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015084 return -ENODEV;
15085 }
15086 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015087 if (!AscFindSignature(iop_base))
15088 goto nodev;
15089 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
15090 goto nodev;
15091
15092 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015093 if (!shost)
15094 goto nodev;
15095
15096 dev_set_drvdata(dev, shost);
15097 return 0;
15098
15099 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015100 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015101 return -ENODEV;
15102}
15103
15104static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
15105{
Matthew Wilcox71f36112007-07-30 08:04:53 -060015106 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015107 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015108 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015109 return 0;
15110}
15111
15112static struct isa_driver advansys_isa_driver = {
15113 .probe = advansys_isa_probe,
15114 .remove = __devexit_p(advansys_isa_remove),
15115 .driver = {
15116 .owner = THIS_MODULE,
15117 .name = "advansys",
15118 },
15119};
15120
15121static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
15122{
15123 PortAddr iop_base = _asc_def_iop_base[id];
15124 struct Scsi_Host *shost;
15125
15126 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015127 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
15128 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015129 return -ENODEV;
15130 }
15131 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015132 if (!AscFindSignature(iop_base))
15133 goto nodev;
15134 /*
15135 * I don't think this condition can actually happen, but the old
15136 * driver did it, and the chances of finding a VLB setup in 2007
15137 * to do testing with is slight to none.
15138 */
15139 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
15140 goto nodev;
15141
15142 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015143 if (!shost)
15144 goto nodev;
15145
15146 dev_set_drvdata(dev, shost);
15147 return 0;
15148
15149 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015150 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015151 return -ENODEV;
15152}
15153
15154static struct isa_driver advansys_vlb_driver = {
15155 .probe = advansys_vlb_probe,
15156 .remove = __devexit_p(advansys_isa_remove),
15157 .driver = {
15158 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060015159 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015160 },
15161};
15162
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015163static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
15164 { "ABP7401" },
15165 { "ABP7501" },
15166 { "" }
15167};
15168
15169MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
15170
15171/*
15172 * EISA is a little more tricky than PCI; each EISA device may have two
15173 * channels, and this driver is written to make each channel its own Scsi_Host
15174 */
15175struct eisa_scsi_data {
15176 struct Scsi_Host *host[2];
15177};
15178
15179static int __devinit advansys_eisa_probe(struct device *dev)
15180{
15181 int i, ioport;
15182 int err;
15183 struct eisa_device *edev = to_eisa_device(dev);
15184 struct eisa_scsi_data *data;
15185
15186 err = -ENOMEM;
15187 data = kzalloc(sizeof(*data), GFP_KERNEL);
15188 if (!data)
15189 goto fail;
15190 ioport = edev->base_addr + 0xc30;
15191
15192 err = -ENODEV;
15193 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015194 if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
15195 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
15196 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015197 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015198 }
15199 if (!AscFindSignature(ioport)) {
15200 release_region(ioport, ASC_IOADR_GAP);
15201 continue;
15202 }
15203
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015204 /*
15205 * I don't know why we need to do this for EISA chips, but
15206 * not for any others. It looks to be equivalent to
15207 * AscGetChipCfgMsw, but I may have overlooked something,
15208 * so I'm not converting it until I get an EISA board to
15209 * test with.
15210 */
15211 inw(ioport + 4);
15212 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015213 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015214 err = 0;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015215 } else {
15216 release_region(ioport, ASC_IOADR_GAP);
15217 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015218 }
15219
15220 if (err) {
15221 kfree(data);
15222 } else {
15223 dev_set_drvdata(dev, data);
15224 }
15225
15226 fail:
15227 return err;
15228}
15229
15230static __devexit int advansys_eisa_remove(struct device *dev)
15231{
15232 int i;
15233 struct eisa_scsi_data *data = dev_get_drvdata(dev);
15234
15235 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015236 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015237 struct Scsi_Host *shost = data->host[i];
15238 if (!shost)
15239 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015240 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015241 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015242 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015243 }
15244
15245 kfree(data);
15246 return 0;
15247}
15248
15249static struct eisa_driver advansys_eisa_driver = {
15250 .id_table = advansys_eisa_table,
15251 .driver = {
15252 .name = "advansys",
15253 .probe = advansys_eisa_probe,
15254 .remove = __devexit_p(advansys_eisa_remove),
15255 }
15256};
15257
Dave Jones2672ea82006-08-02 17:11:49 -040015258/* PCI Devices supported by this driver */
15259static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015260 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
15261 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15262 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
15263 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15264 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
15265 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15266 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
15267 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15268 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
15269 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15270 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
15271 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15272 {}
Dave Jones2672ea82006-08-02 17:11:49 -040015273};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015274
Dave Jones2672ea82006-08-02 17:11:49 -040015275MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015276
Matthew Wilcox9649af32007-07-26 21:51:47 -060015277static void __devinit advansys_set_latency(struct pci_dev *pdev)
15278{
15279 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
15280 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
15281 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
15282 } else {
15283 u8 latency;
15284 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
15285 if (latency < 0x20)
15286 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
15287 }
15288}
15289
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015290static int __devinit
15291advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15292{
15293 int err, ioport;
15294 struct Scsi_Host *shost;
15295
15296 err = pci_enable_device(pdev);
15297 if (err)
15298 goto fail;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015299 err = pci_request_regions(pdev, "advansys");
15300 if (err)
15301 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060015302 pci_set_master(pdev);
15303 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015304
15305 if (pci_resource_len(pdev, 0) == 0)
15306 goto nodev;
15307
15308 ioport = pci_resource_start(pdev, 0);
15309 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
15310
15311 if (!shost)
15312 goto nodev;
15313
15314 pci_set_drvdata(pdev, shost);
15315 return 0;
15316
15317 nodev:
15318 err = -ENODEV;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015319 pci_release_regions(pdev);
15320 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015321 pci_disable_device(pdev);
15322 fail:
15323 return err;
15324}
15325
15326static void __devexit advansys_pci_remove(struct pci_dev *pdev)
15327{
15328 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015329 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015330 pci_disable_device(pdev);
15331}
15332
15333static struct pci_driver advansys_pci_driver = {
15334 .name = "advansys",
15335 .id_table = advansys_pci_tbl,
15336 .probe = advansys_pci_probe,
15337 .remove = __devexit_p(advansys_pci_remove),
15338};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015339
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015340static int __init advansys_init(void)
15341{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015342 int error;
15343
15344 error = isa_register_driver(&advansys_isa_driver,
15345 ASC_IOADR_TABLE_MAX_IX);
15346 if (error)
15347 goto fail;
15348
15349 error = isa_register_driver(&advansys_vlb_driver,
15350 ASC_IOADR_TABLE_MAX_IX);
15351 if (error)
15352 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015353
15354 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015355 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015356 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015357
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015358 error = pci_register_driver(&advansys_pci_driver);
15359 if (error)
15360 goto unregister_eisa;
15361
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015362 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015363
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015364 unregister_eisa:
15365 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015366 unregister_vlb:
15367 isa_unregister_driver(&advansys_vlb_driver);
15368 unregister_isa:
15369 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015370 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015371 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015372}
15373
15374static void __exit advansys_exit(void)
15375{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015376 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015377 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015378 isa_unregister_driver(&advansys_vlb_driver);
15379 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015380}
15381
15382module_init(advansys_init);
15383module_exit(advansys_exit);
15384
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015385MODULE_LICENSE("GPL");