blob: ef4f6790a25164011937db7979b6ebfa459678d8 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213#define ASC_SCSI_RESET_HOLD_TIME_US 60
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215/*
Matthew Wilcoxf05ec592007-09-09 08:56:36 -0600216 * Narrow boards only support 12-byte commands, while wide boards
217 * extend to 16-byte commands.
218 */
219#define ASC_MAX_CDB_LEN 12
220#define ADV_MAX_CDB_LEN 16
221
222/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
224 * and CmdDt (Command Support Data) field bit definitions.
225 */
226#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
227#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
228#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
229#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
230
231#define ASC_SCSIDIR_NOCHK 0x00
232#define ASC_SCSIDIR_T2H 0x08
233#define ASC_SCSIDIR_H2T 0x10
234#define ASC_SCSIDIR_NODATA 0x18
235#define SCSI_ASC_NOMEDIA 0x3A
236#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
237#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
238#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
239#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
243#define ASC_SG_LIST_PER_Q 7
244#define QS_FREE 0x00
245#define QS_READY 0x01
246#define QS_DISC1 0x02
247#define QS_DISC2 0x04
248#define QS_BUSY 0x08
249#define QS_ABORTED 0x40
250#define QS_DONE 0x80
251#define QC_NO_CALLBACK 0x01
252#define QC_SG_SWAP_QUEUE 0x02
253#define QC_SG_HEAD 0x04
254#define QC_DATA_IN 0x08
255#define QC_DATA_OUT 0x10
256#define QC_URGENT 0x20
257#define QC_MSG_OUT 0x40
258#define QC_REQ_SENSE 0x80
259#define QCSG_SG_XFER_LIST 0x02
260#define QCSG_SG_XFER_MORE 0x04
261#define QCSG_SG_XFER_END 0x08
262#define QD_IN_PROGRESS 0x00
263#define QD_NO_ERROR 0x01
264#define QD_ABORTED_BY_HOST 0x02
265#define QD_WITH_ERROR 0x04
266#define QD_INVALID_REQUEST 0x80
267#define QD_INVALID_HOST_NUM 0x81
268#define QD_INVALID_DEVICE 0x82
269#define QD_ERR_INTERNAL 0xFF
270#define QHSTA_NO_ERROR 0x00
271#define QHSTA_M_SEL_TIMEOUT 0x11
272#define QHSTA_M_DATA_OVER_RUN 0x12
273#define QHSTA_M_DATA_UNDER_RUN 0x12
274#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
275#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
276#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
277#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
278#define QHSTA_D_HOST_ABORT_FAILED 0x23
279#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
280#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
281#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
282#define QHSTA_M_WTM_TIMEOUT 0x41
283#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
284#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
285#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
286#define QHSTA_M_TARGET_STATUS_BUSY 0x45
287#define QHSTA_M_BAD_TAG_CODE 0x46
288#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
289#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
290#define QHSTA_D_LRAM_CMP_ERROR 0x81
291#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
292#define ASC_FLAG_SCSIQ_REQ 0x01
293#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
294#define ASC_FLAG_BIOS_ASYNC_IO 0x04
295#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
296#define ASC_FLAG_WIN16 0x10
297#define ASC_FLAG_WIN32 0x20
298#define ASC_FLAG_ISA_OVER_16MB 0x40
299#define ASC_FLAG_DOS_VM_CALLBACK 0x80
300#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
301#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
302#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
303#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
304#define ASC_SCSIQ_CPY_BEG 4
305#define ASC_SCSIQ_SGHD_CPY_BEG 2
306#define ASC_SCSIQ_B_FWD 0
307#define ASC_SCSIQ_B_BWD 1
308#define ASC_SCSIQ_B_STATUS 2
309#define ASC_SCSIQ_B_QNO 3
310#define ASC_SCSIQ_B_CNTL 4
311#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
312#define ASC_SCSIQ_D_DATA_ADDR 8
313#define ASC_SCSIQ_D_DATA_CNT 12
314#define ASC_SCSIQ_B_SENSE_LEN 20
315#define ASC_SCSIQ_DONE_INFO_BEG 22
316#define ASC_SCSIQ_D_SRBPTR 22
317#define ASC_SCSIQ_B_TARGET_IX 26
318#define ASC_SCSIQ_B_CDB_LEN 28
319#define ASC_SCSIQ_B_TAG_CODE 29
320#define ASC_SCSIQ_W_VM_ID 30
321#define ASC_SCSIQ_DONE_STATUS 32
322#define ASC_SCSIQ_HOST_STATUS 33
323#define ASC_SCSIQ_SCSI_STATUS 34
324#define ASC_SCSIQ_CDB_BEG 36
325#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
326#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
327#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
328#define ASC_SCSIQ_B_SG_WK_QP 49
329#define ASC_SCSIQ_B_SG_WK_IX 50
330#define ASC_SCSIQ_W_ALT_DC1 52
331#define ASC_SCSIQ_B_LIST_CNT 6
332#define ASC_SCSIQ_B_CUR_LIST_CNT 7
333#define ASC_SGQ_B_SG_CNTL 4
334#define ASC_SGQ_B_SG_HEAD_QP 5
335#define ASC_SGQ_B_SG_LIST_CNT 6
336#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
337#define ASC_SGQ_LIST_BEG 8
338#define ASC_DEF_SCSI1_QNG 4
339#define ASC_MAX_SCSI1_QNG 4
340#define ASC_DEF_SCSI2_QNG 16
341#define ASC_MAX_SCSI2_QNG 32
342#define ASC_TAG_CODE_MASK 0x23
343#define ASC_STOP_REQ_RISC_STOP 0x01
344#define ASC_STOP_ACK_RISC_STOP 0x03
345#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
346#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
347#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
348#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
349#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
350#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
351#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
352#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
353#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
354#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
355
356typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400357 uchar status;
358 uchar q_no;
359 uchar cntl;
360 uchar sg_queue_cnt;
361 uchar target_id;
362 uchar target_lun;
363 ASC_PADDR data_addr;
364 ASC_DCNT data_cnt;
365 ASC_PADDR sense_addr;
366 uchar sense_len;
367 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368} ASC_SCSIQ_1;
369
370typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400371 ASC_VADDR srb_ptr;
372 uchar target_ix;
373 uchar flag;
374 uchar cdb_len;
375 uchar tag_code;
376 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377} ASC_SCSIQ_2;
378
379typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400380 uchar done_stat;
381 uchar host_stat;
382 uchar scsi_stat;
383 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384} ASC_SCSIQ_3;
385
386typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400387 uchar cdb[ASC_MAX_CDB_LEN];
388 uchar y_first_sg_list_qp;
389 uchar y_working_sg_qp;
390 uchar y_working_sg_ix;
391 uchar y_res;
392 ushort x_req_count;
393 ushort x_reconnect_rtn;
394 ASC_PADDR x_saved_data_addr;
395 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396} ASC_SCSIQ_4;
397
398typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400399 ASC_SCSIQ_2 d2;
400 ASC_SCSIQ_3 d3;
401 uchar q_status;
402 uchar q_no;
403 uchar cntl;
404 uchar sense_len;
405 uchar extra_bytes;
406 uchar res;
407 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408} ASC_QDONE_INFO;
409
410typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400411 ASC_PADDR addr;
412 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413} ASC_SG_LIST;
414
415typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400416 ushort entry_cnt;
417 ushort queue_cnt;
418 ushort entry_to_copy;
419 ushort res;
420 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421} ASC_SG_HEAD;
422
423#define ASC_MIN_SG_LIST 2
424
425typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400426 ushort entry_cnt;
427 ushort queue_cnt;
428 ushort entry_to_copy;
429 ushort res;
430 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431} ASC_MIN_SG_HEAD;
432
433#define QCX_SORT (0x0001)
434#define QCX_COALEASE (0x0002)
435
436typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400437 ASC_SCSIQ_1 q1;
438 ASC_SCSIQ_2 q2;
439 uchar *cdbptr;
440 ASC_SG_HEAD *sg_head;
441 ushort remain_sg_entry_cnt;
442 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443} ASC_SCSI_Q;
444
445typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400446 ASC_SCSIQ_1 r1;
447 ASC_SCSIQ_2 r2;
448 uchar *cdbptr;
449 ASC_SG_HEAD *sg_head;
450 uchar *sense_ptr;
451 ASC_SCSIQ_3 r3;
452 uchar cdb[ASC_MAX_CDB_LEN];
453 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454} ASC_SCSI_REQ_Q;
455
456typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400457 ASC_SCSIQ_1 r1;
458 ASC_SCSIQ_2 r2;
459 uchar *cdbptr;
460 ASC_SG_HEAD *sg_head;
461 uchar *sense_ptr;
462 ASC_SCSIQ_3 r3;
463 uchar cdb[ASC_MAX_CDB_LEN];
464 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465} ASC_SCSI_BIOS_REQ_Q;
466
467typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400468 uchar fwd;
469 uchar bwd;
470 ASC_SCSIQ_1 i1;
471 ASC_SCSIQ_2 i2;
472 ASC_SCSIQ_3 i3;
473 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474} ASC_RISC_Q;
475
476typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400477 uchar seq_no;
478 uchar q_no;
479 uchar cntl;
480 uchar sg_head_qp;
481 uchar sg_list_cnt;
482 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483} ASC_SG_LIST_Q;
484
485typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400486 uchar fwd;
487 uchar bwd;
488 ASC_SG_LIST_Q sg;
489 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490} ASC_RISC_SG_LIST_Q;
491
492#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
493#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
494#define ASCQ_ERR_NO_ERROR 0
495#define ASCQ_ERR_IO_NOT_FOUND 1
496#define ASCQ_ERR_LOCAL_MEM 2
497#define ASCQ_ERR_CHKSUM 3
498#define ASCQ_ERR_START_CHIP 4
499#define ASCQ_ERR_INT_TARGET_ID 5
500#define ASCQ_ERR_INT_LOCAL_MEM 6
501#define ASCQ_ERR_HALT_RISC 7
502#define ASCQ_ERR_GET_ASPI_ENTRY 8
503#define ASCQ_ERR_CLOSE_ASPI 9
504#define ASCQ_ERR_HOST_INQUIRY 0x0A
505#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
506#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
507#define ASCQ_ERR_Q_STATUS 0x0D
508#define ASCQ_ERR_WR_SCSIQ 0x0E
509#define ASCQ_ERR_PC_ADDR 0x0F
510#define ASCQ_ERR_SYN_OFFSET 0x10
511#define ASCQ_ERR_SYN_XFER_TIME 0x11
512#define ASCQ_ERR_LOCK_DMA 0x12
513#define ASCQ_ERR_UNLOCK_DMA 0x13
514#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
515#define ASCQ_ERR_MICRO_CODE_HALT 0x15
516#define ASCQ_ERR_SET_LRAM_ADDR 0x16
517#define ASCQ_ERR_CUR_QNG 0x17
518#define ASCQ_ERR_SG_Q_LINKS 0x18
519#define ASCQ_ERR_SCSIQ_PTR 0x19
520#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
521#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
522#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
523#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
524#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
525#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
526#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
527#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
528#define ASCQ_ERR_SEND_SCSI_Q 0x22
529#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
530#define ASCQ_ERR_RESET_SDTR 0x24
531
532/*
533 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
534 */
535#define ASC_WARN_NO_ERROR 0x0000
536#define ASC_WARN_IO_PORT_ROTATE 0x0001
537#define ASC_WARN_EEPROM_CHKSUM 0x0002
538#define ASC_WARN_IRQ_MODIFIED 0x0004
539#define ASC_WARN_AUTO_CONFIG 0x0008
540#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
541#define ASC_WARN_EEPROM_RECOVER 0x0020
542#define ASC_WARN_CFG_MSW_RECOVER 0x0040
543#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
544
545/*
546 * Error code values are set in ASC_DVC_VAR 'err_code'.
547 */
548#define ASC_IERR_WRITE_EEPROM 0x0001
549#define ASC_IERR_MCODE_CHKSUM 0x0002
550#define ASC_IERR_SET_PC_ADDR 0x0004
551#define ASC_IERR_START_STOP_CHIP 0x0008
552#define ASC_IERR_IRQ_NO 0x0010
553#define ASC_IERR_SET_IRQ_NO 0x0020
554#define ASC_IERR_CHIP_VERSION 0x0040
555#define ASC_IERR_SET_SCSI_ID 0x0080
556#define ASC_IERR_GET_PHY_ADDR 0x0100
557#define ASC_IERR_BAD_SIGNATURE 0x0200
558#define ASC_IERR_NO_BUS_TYPE 0x0400
559#define ASC_IERR_SCAM 0x0800
560#define ASC_IERR_SET_SDTR 0x1000
561#define ASC_IERR_RW_LRAM 0x8000
562
563#define ASC_DEF_IRQ_NO 10
564#define ASC_MAX_IRQ_NO 15
565#define ASC_MIN_IRQ_NO 10
566#define ASC_MIN_REMAIN_Q (0x02)
567#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
568#define ASC_MIN_TAG_Q_PER_DVC (0x04)
569#define ASC_DEF_TAG_Q_PER_DVC (0x04)
570#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
571#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
572#define ASC_MAX_TOTAL_QNG 240
573#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
574#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
575#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
576#define ASC_MAX_INRAM_TAG_QNG 16
577#define ASC_IOADR_TABLE_MAX_IX 11
578#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579#define ASC_LIB_SCSIQ_WK_SP 256
580#define ASC_MAX_SYN_XFER_NO 16
581#define ASC_SYN_MAX_OFFSET 0x0F
582#define ASC_DEF_SDTR_OFFSET 0x0F
583#define ASC_DEF_SDTR_INDEX 0x00
584#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
585#define SYN_XFER_NS_0 25
586#define SYN_XFER_NS_1 30
587#define SYN_XFER_NS_2 35
588#define SYN_XFER_NS_3 40
589#define SYN_XFER_NS_4 50
590#define SYN_XFER_NS_5 60
591#define SYN_XFER_NS_6 70
592#define SYN_XFER_NS_7 85
593#define SYN_ULTRA_XFER_NS_0 12
594#define SYN_ULTRA_XFER_NS_1 19
595#define SYN_ULTRA_XFER_NS_2 25
596#define SYN_ULTRA_XFER_NS_3 32
597#define SYN_ULTRA_XFER_NS_4 38
598#define SYN_ULTRA_XFER_NS_5 44
599#define SYN_ULTRA_XFER_NS_6 50
600#define SYN_ULTRA_XFER_NS_7 57
601#define SYN_ULTRA_XFER_NS_8 63
602#define SYN_ULTRA_XFER_NS_9 69
603#define SYN_ULTRA_XFER_NS_10 75
604#define SYN_ULTRA_XFER_NS_11 82
605#define SYN_ULTRA_XFER_NS_12 88
606#define SYN_ULTRA_XFER_NS_13 94
607#define SYN_ULTRA_XFER_NS_14 100
608#define SYN_ULTRA_XFER_NS_15 107
609
610typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400611 uchar msg_type;
612 uchar msg_len;
613 uchar msg_req;
614 union {
615 struct {
616 uchar sdtr_xfer_period;
617 uchar sdtr_req_ack_offset;
618 } sdtr;
619 struct {
620 uchar wdtr_width;
621 } wdtr;
622 struct {
623 uchar mdp_b3;
624 uchar mdp_b2;
625 uchar mdp_b1;
626 uchar mdp_b0;
627 } mdp;
628 } u_ext_msg;
629 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630} EXT_MSG;
631
632#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
633#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
634#define wdtr_width u_ext_msg.wdtr.wdtr_width
635#define mdp_b3 u_ext_msg.mdp_b3
636#define mdp_b2 u_ext_msg.mdp_b2
637#define mdp_b1 u_ext_msg.mdp_b1
638#define mdp_b0 u_ext_msg.mdp_b0
639
640typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400641 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
642 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
643 ASC_SCSI_BIT_ID_TYPE disc_enable;
644 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
645 uchar chip_scsi_id;
646 uchar isa_dma_speed;
647 uchar isa_dma_channel;
648 uchar chip_version;
649 ushort lib_serial_no;
650 ushort lib_version;
651 ushort mcode_date;
652 ushort mcode_version;
653 uchar max_tag_qng[ASC_MAX_TID + 1];
654 uchar *overrun_buf;
655 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400656 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657} ASC_DVC_CFG;
658
659#define ASC_DEF_DVC_CNTL 0xFFFF
660#define ASC_DEF_CHIP_SCSI_ID 7
661#define ASC_DEF_ISA_DMA_SPEED 4
662#define ASC_INIT_STATE_NULL 0x0000
663#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
664#define ASC_INIT_STATE_END_GET_CFG 0x0002
665#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
666#define ASC_INIT_STATE_END_SET_CFG 0x0008
667#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
668#define ASC_INIT_STATE_END_LOAD_MC 0x0020
669#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
670#define ASC_INIT_STATE_END_INQUIRY 0x0080
671#define ASC_INIT_RESET_SCSI_DONE 0x0100
672#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
674#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
675#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
676#define ASC_MIN_TAGGED_CMD 7
677#define ASC_MAX_SCSI_RESET_WAIT 30
678
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400679struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400682 PortAddr iop_base;
683 ushort err_code;
684 ushort dvc_cntl;
685 ushort bug_fix_cntl;
686 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400687 ASC_SCSI_BIT_ID_TYPE init_sdtr;
688 ASC_SCSI_BIT_ID_TYPE sdtr_done;
689 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
690 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
691 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
692 ASC_SCSI_BIT_ID_TYPE start_motor;
693 uchar scsi_reset_wait;
694 uchar chip_no;
695 char is_in_int;
696 uchar max_total_qng;
697 uchar cur_total_qng;
698 uchar in_critical_cnt;
699 uchar irq_no;
700 uchar last_q_shortage;
701 ushort init_state;
702 uchar cur_dvc_qng[ASC_MAX_TID + 1];
703 uchar max_dvc_qng[ASC_MAX_TID + 1];
704 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
705 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
706 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
707 ASC_DVC_CFG *cfg;
708 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
709 char redo_scam;
710 ushort res2;
711 uchar dos_int13_table[ASC_MAX_TID + 1];
712 ASC_DCNT max_dma_count;
713 ASC_SCSI_BIT_ID_TYPE no_scam;
714 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
715 uchar max_sdtr_index;
716 uchar host_init_sdtr_index;
717 struct asc_board *drv_ptr;
718 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719} ASC_DVC_VAR;
720
721typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400722 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723} ASC_DVC_INQ_INFO;
724
725typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400726 ASC_DCNT lba;
727 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728} ASC_CAP_INFO;
729
730typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400731 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732} ASC_CAP_INFO_ARRAY;
733
734#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
735#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
736#define ASC_CNTL_INITIATOR (ushort)0x0001
737#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
738#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
739#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
740#define ASC_CNTL_NO_SCAM (ushort)0x0010
741#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
742#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
743#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
744#define ASC_CNTL_RESET_SCSI (ushort)0x0200
745#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
746#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
747#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
748#define ASC_CNTL_BURST_MODE (ushort)0x2000
749#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
750#define ASC_EEP_DVC_CFG_BEG_VL 2
751#define ASC_EEP_MAX_DVC_ADDR_VL 15
752#define ASC_EEP_DVC_CFG_BEG 32
753#define ASC_EEP_MAX_DVC_ADDR 45
754#define ASC_EEP_DEFINED_WORDS 10
755#define ASC_EEP_MAX_ADDR 63
756#define ASC_EEP_RES_WORDS 0
757#define ASC_EEP_MAX_RETRY 20
758#define ASC_MAX_INIT_BUSY_RETRY 8
759#define ASC_EEP_ISA_PNP_WSIZE 16
760
761/*
762 * These macros keep the chip SCSI id and ISA DMA speed
763 * bitfields in board order. C bitfields aren't portable
764 * between big and little-endian platforms so they are
765 * not used.
766 */
767
768#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
769#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
770#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
771 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
772#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
773 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
774
775typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400776 ushort cfg_lsw;
777 ushort cfg_msw;
778 uchar init_sdtr;
779 uchar disc_enable;
780 uchar use_cmd_qng;
781 uchar start_motor;
782 uchar max_total_qng;
783 uchar max_tag_qng;
784 uchar bios_scan;
785 uchar power_up_wait;
786 uchar no_scam;
787 uchar id_speed; /* low order 4 bits is chip scsi id */
788 /* high order 4 bits is isa dma speed */
789 uchar dos_int13_table[ASC_MAX_TID + 1];
790 uchar adapter_info[6];
791 ushort cntl;
792 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793} ASCEEP_CONFIG;
794
795#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
796#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
797#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
798
799#define ASC_EEP_CMD_READ 0x80
800#define ASC_EEP_CMD_WRITE 0x40
801#define ASC_EEP_CMD_WRITE_ABLE 0x30
802#define ASC_EEP_CMD_WRITE_DISABLE 0x00
803#define ASC_OVERRUN_BSIZE 0x00000048UL
804#define ASC_CTRL_BREAK_ONCE 0x0001
805#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
806#define ASCV_MSGOUT_BEG 0x0000
807#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
808#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
809#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
810#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
811#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
812#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
813#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
814#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
815#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
816#define ASCV_BREAK_ADDR (ushort)0x0028
817#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
818#define ASCV_BREAK_CONTROL (ushort)0x002C
819#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
820
821#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
822#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
823#define ASCV_MCODE_SIZE_W (ushort)0x0034
824#define ASCV_STOP_CODE_B (ushort)0x0036
825#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
826#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
827#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
828#define ASCV_HALTCODE_W (ushort)0x0040
829#define ASCV_CHKSUM_W (ushort)0x0042
830#define ASCV_MC_DATE_W (ushort)0x0044
831#define ASCV_MC_VER_W (ushort)0x0046
832#define ASCV_NEXTRDY_B (ushort)0x0048
833#define ASCV_DONENEXT_B (ushort)0x0049
834#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
835#define ASCV_SCSIBUSY_B (ushort)0x004B
836#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
837#define ASCV_CURCDB_B (ushort)0x004D
838#define ASCV_RCLUN_B (ushort)0x004E
839#define ASCV_BUSY_QHEAD_B (ushort)0x004F
840#define ASCV_DISC1_QHEAD_B (ushort)0x0050
841#define ASCV_DISC_ENABLE_B (ushort)0x0052
842#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
843#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
844#define ASCV_MCODE_CNTL_B (ushort)0x0056
845#define ASCV_NULL_TARGET_B (ushort)0x0057
846#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
847#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
848#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
849#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
850#define ASCV_HOST_FLAG_B (ushort)0x005D
851#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
852#define ASCV_VER_SERIAL_B (ushort)0x0065
853#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
854#define ASCV_WTM_FLAG_B (ushort)0x0068
855#define ASCV_RISC_FLAG_B (ushort)0x006A
856#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
857#define ASC_HOST_FLAG_IN_ISR 0x01
858#define ASC_HOST_FLAG_ACK_INT 0x02
859#define ASC_RISC_FLAG_GEN_INT 0x01
860#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
861#define IOP_CTRL (0x0F)
862#define IOP_STATUS (0x0E)
863#define IOP_INT_ACK IOP_STATUS
864#define IOP_REG_IFC (0x0D)
865#define IOP_SYN_OFFSET (0x0B)
866#define IOP_EXTRA_CONTROL (0x0D)
867#define IOP_REG_PC (0x0C)
868#define IOP_RAM_ADDR (0x0A)
869#define IOP_RAM_DATA (0x08)
870#define IOP_EEP_DATA (0x06)
871#define IOP_EEP_CMD (0x07)
872#define IOP_VERSION (0x03)
873#define IOP_CONFIG_HIGH (0x04)
874#define IOP_CONFIG_LOW (0x02)
875#define IOP_SIG_BYTE (0x01)
876#define IOP_SIG_WORD (0x00)
877#define IOP_REG_DC1 (0x0E)
878#define IOP_REG_DC0 (0x0C)
879#define IOP_REG_SB (0x0B)
880#define IOP_REG_DA1 (0x0A)
881#define IOP_REG_DA0 (0x08)
882#define IOP_REG_SC (0x09)
883#define IOP_DMA_SPEED (0x07)
884#define IOP_REG_FLAG (0x07)
885#define IOP_FIFO_H (0x06)
886#define IOP_FIFO_L (0x04)
887#define IOP_REG_ID (0x05)
888#define IOP_REG_QP (0x03)
889#define IOP_REG_IH (0x02)
890#define IOP_REG_IX (0x01)
891#define IOP_REG_AX (0x00)
892#define IFC_REG_LOCK (0x00)
893#define IFC_REG_UNLOCK (0x09)
894#define IFC_WR_EN_FILTER (0x10)
895#define IFC_RD_NO_EEPROM (0x10)
896#define IFC_SLEW_RATE (0x20)
897#define IFC_ACT_NEG (0x40)
898#define IFC_INP_FILTER (0x80)
899#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
900#define SC_SEL (uchar)(0x80)
901#define SC_BSY (uchar)(0x40)
902#define SC_ACK (uchar)(0x20)
903#define SC_REQ (uchar)(0x10)
904#define SC_ATN (uchar)(0x08)
905#define SC_IO (uchar)(0x04)
906#define SC_CD (uchar)(0x02)
907#define SC_MSG (uchar)(0x01)
908#define SEC_SCSI_CTL (uchar)(0x80)
909#define SEC_ACTIVE_NEGATE (uchar)(0x40)
910#define SEC_SLEW_RATE (uchar)(0x20)
911#define SEC_ENABLE_FILTER (uchar)(0x10)
912#define ASC_HALT_EXTMSG_IN (ushort)0x8000
913#define ASC_HALT_CHK_CONDITION (ushort)0x8100
914#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
915#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
916#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
917#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
918#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
919#define ASC_MAX_QNO 0xF8
920#define ASC_DATA_SEC_BEG (ushort)0x0080
921#define ASC_DATA_SEC_END (ushort)0x0080
922#define ASC_CODE_SEC_BEG (ushort)0x0080
923#define ASC_CODE_SEC_END (ushort)0x0080
924#define ASC_QADR_BEG (0x4000)
925#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
926#define ASC_QADR_END (ushort)0x7FFF
927#define ASC_QLAST_ADR (ushort)0x7FC0
928#define ASC_QBLK_SIZE 0x40
929#define ASC_BIOS_DATA_QBEG 0xF8
930#define ASC_MIN_ACTIVE_QNO 0x01
931#define ASC_QLINK_END 0xFF
932#define ASC_EEPROM_WORDS 0x10
933#define ASC_MAX_MGS_LEN 0x10
934#define ASC_BIOS_ADDR_DEF 0xDC00
935#define ASC_BIOS_SIZE 0x3800
936#define ASC_BIOS_RAM_OFF 0x3800
937#define ASC_BIOS_RAM_SIZE 0x800
938#define ASC_BIOS_MIN_ADDR 0xC000
939#define ASC_BIOS_MAX_ADDR 0xEC00
940#define ASC_BIOS_BANK_SIZE 0x0400
941#define ASC_MCODE_START_ADDR 0x0080
942#define ASC_CFG0_HOST_INT_ON 0x0020
943#define ASC_CFG0_BIOS_ON 0x0040
944#define ASC_CFG0_VERA_BURST_ON 0x0080
945#define ASC_CFG0_SCSI_PARITY_ON 0x0800
946#define ASC_CFG1_SCSI_TARGET_ON 0x0080
947#define ASC_CFG1_LRAM_8BITS_ON 0x0800
948#define ASC_CFG_MSW_CLR_MASK 0x3080
949#define CSW_TEST1 (ASC_CS_TYPE)0x8000
950#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
951#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
952#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
953#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
954#define CSW_TEST2 (ASC_CS_TYPE)0x0400
955#define CSW_TEST3 (ASC_CS_TYPE)0x0200
956#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
957#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
958#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
959#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
960#define CSW_HALTED (ASC_CS_TYPE)0x0010
961#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
962#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
963#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
964#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
965#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
966#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
967#define CIW_TEST1 (ASC_CS_TYPE)0x0200
968#define CIW_TEST2 (ASC_CS_TYPE)0x0400
969#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
970#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
971#define CC_CHIP_RESET (uchar)0x80
972#define CC_SCSI_RESET (uchar)0x40
973#define CC_HALT (uchar)0x20
974#define CC_SINGLE_STEP (uchar)0x10
975#define CC_DMA_ABLE (uchar)0x08
976#define CC_TEST (uchar)0x04
977#define CC_BANK_ONE (uchar)0x02
978#define CC_DIAG (uchar)0x01
979#define ASC_1000_ID0W 0x04C1
980#define ASC_1000_ID0W_FIX 0x00C1
981#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982#define ASC_EISA_REV_IOP_MASK (0x0C83)
983#define ASC_EISA_PID_IOP_MASK (0x0C80)
984#define ASC_EISA_CFG_IOP_MASK (0x0C86)
985#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986#define INS_HALTINT (ushort)0x6281
987#define INS_HALT (ushort)0x6280
988#define INS_SINT (ushort)0x6200
989#define INS_RFLAG_WTM (ushort)0x7380
990#define ASC_MC_SAVE_CODE_WSIZE 0x500
991#define ASC_MC_SAVE_DATA_WSIZE 0x40
992
993typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400994 ushort data[ASC_MC_SAVE_DATA_WSIZE];
995 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996} ASC_MC_SAVED;
997
998#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
999#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1000#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1001#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1002#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1003#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1004#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1005#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1006#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1007#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1008#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1009#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1010#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1011#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1012#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1013#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1014#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1015#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1016#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1017#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1018#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1019#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1020#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1021#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1022#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1023#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1024#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1025#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1026#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1027#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1028#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1029#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1030#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1031#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1032#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1033#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1034#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1035#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1036#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1037#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1038#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1039#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1040#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1041#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1042#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1043#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1044#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1045#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1046#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1047#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1048#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1049#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1050#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1051#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1052#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1053#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1054#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1055#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1056#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1057#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1058#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1059#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1060#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1061#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1062#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1063#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1064#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1065#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001067static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1068static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1069static void AscWaitEEPRead(void);
1070static void AscWaitEEPWrite(void);
1071static ushort AscReadEEPWord(PortAddr, uchar);
1072static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1073static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1074static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1075static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1076static int AscStartChip(PortAddr);
1077static int AscStopChip(PortAddr);
1078static void AscSetChipIH(PortAddr, ushort);
1079static int AscIsChipHalted(PortAddr);
1080static void AscAckInterrupt(PortAddr);
1081static void AscDisableInterrupt(PortAddr);
1082static void AscEnableInterrupt(PortAddr);
1083static void AscSetBank(PortAddr, uchar);
1084static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001086static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001088static uchar AscReadLramByte(PortAddr, ushort);
1089static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001091static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001093static void AscWriteLramWord(PortAddr, ushort, ushort);
1094static void AscWriteLramByte(PortAddr, ushort, uchar);
1095static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1096static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1097static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1098static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1099static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1100static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1101static ushort AscInitFromEEP(ASC_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001102static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1103static int AscTestExternalLram(ASC_DVC_VAR *);
1104static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1105static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1106static void AscSetChipSDTR(PortAddr, uchar, uchar);
1107static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1108static uchar AscAllocFreeQueue(PortAddr, uchar);
1109static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1110static int AscHostReqRiscHalt(PortAddr);
1111static int AscStopQueueExe(PortAddr);
1112static int AscSendScsiQueue(ASC_DVC_VAR *,
1113 ASC_SCSI_Q *scsiq, uchar n_q_required);
1114static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1115static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1116static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1117static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1118static ushort AscInitLram(ASC_DVC_VAR *);
1119static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1120static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1121static int AscIsrChipHalted(ASC_DVC_VAR *);
1122static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1123 ASC_QDONE_INFO *, ASC_DCNT);
1124static int AscIsrQDone(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001126static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001128static uchar AscGetChipScsiCtrl(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001129static uchar AscGetChipVersion(PortAddr, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001130static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001131static void AscToggleIRQAct(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001132static inline ulong DvcEnterCritical(void);
1133static inline void DvcLeaveCritical(ulong);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001134static void DvcSleepMilliSecond(ASC_DCNT);
1135static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1136static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1137static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001138static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04001139static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001140static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1141static int AscISR(ASC_DVC_VAR *);
1142static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1143static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001145static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001147static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
1149/*
1150 * --- Adv Library Constants and Macros
1151 */
1152
1153#define ADV_LIB_VERSION_MAJOR 5
1154#define ADV_LIB_VERSION_MINOR 14
1155
1156/*
1157 * Define Adv Library required special types.
1158 */
1159
1160/*
1161 * Portable Data Types
1162 *
1163 * Any instance where a 32-bit long or pointer type is assumed
1164 * for precision or HW defined structures, the following define
1165 * types must be used. In Linux the char, short, and int types
1166 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1167 * and long types are 64 bits on Alpha and UltraSPARC.
1168 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001169#define ADV_PADDR __u32 /* Physical address data type. */
1170#define ADV_VADDR __u32 /* Virtual address data type. */
1171#define ADV_DCNT __u32 /* Unsigned Data count type. */
1172#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
1174/*
1175 * These macros are used to convert a virtual address to a
1176 * 32-bit value. This currently can be used on Linux Alpha
1177 * which uses 64-bit virtual address but a 32-bit bus address.
1178 * This is likely to break in the future, but doing this now
1179 * will give us time to change the HW and FW to handle 64-bit
1180 * addresses.
1181 */
1182#define ADV_VADDR_TO_U32 virt_to_bus
1183#define ADV_U32_TO_VADDR bus_to_virt
1184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001185#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
1187/*
1188 * Define Adv Library required memory access macros.
1189 */
1190#define ADV_MEM_READB(addr) readb(addr)
1191#define ADV_MEM_READW(addr) readw(addr)
1192#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1193#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1194#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1195
1196#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1197
1198/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 * 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 Wilcoxb2a7a4b2007-09-09 08:56:35 -06003179advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180{
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003181 struct Scsi_Host *shost = scp->device->host;
3182 asc_board_t *boardp = ASC_BOARDP(shost);
3183 unsigned long 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 ASC_STATS(shost, queuecommand);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003187 scp->scsi_done = done;
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003188
3189 /*
3190 * host_lock taken by mid-level prior to call, but need
3191 * to protect against own ISR
3192 */
3193 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003194 asc_res = asc_execute_scsi_cmnd(scp);
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003195 spin_unlock_irqrestore(&boardp->lock, flags);
3196
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003197 switch (asc_res) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003198 case ASC_NOERROR:
3199 break;
3200 case ASC_BUSY:
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003201 result = SCSI_MLQUEUE_HOST_BUSY;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003202 break;
3203 case ASC_ERROR:
3204 default:
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
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003209 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210}
3211
3212/*
3213 * advansys_reset()
3214 *
3215 * Reset the bus associated with the command 'scp'.
3216 *
3217 * This function runs its own thread. Interrupts must be blocked but
3218 * sleeping is allowed and no locking other than for host structures is
3219 * required. Returns SUCCESS or FAILED.
3220 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003221static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003223 struct Scsi_Host *shost;
3224 asc_board_t *boardp;
3225 ASC_DVC_VAR *asc_dvc_varp;
3226 ADV_DVC_VAR *adv_dvc_varp;
3227 ulong flags;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003228 int status;
3229 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003231 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232
3233#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003234 if (scp->device->host != NULL) {
3235 ASC_STATS(scp->device->host, reset);
3236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237#endif /* ADVANSYS_STATS */
3238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003239 if ((shost = scp->device->host) == NULL) {
3240 scp->result = HOST_BYTE(DID_ERROR);
3241 return FAILED;
3242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003244 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003246 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
3247 boardp->id);
3248 /*
3249 * Check for re-entrancy.
3250 */
3251 spin_lock_irqsave(&boardp->lock, flags);
3252 if (boardp->flags & ASC_HOST_IN_RESET) {
3253 spin_unlock_irqrestore(&boardp->lock, flags);
3254 return FAILED;
3255 }
3256 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003259 if (ASC_NARROW_BOARD(boardp)) {
3260 /*
3261 * Narrow Board
3262 */
3263 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003265 /*
3266 * Reset the chip and SCSI bus.
3267 */
3268 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
3269 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003271 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
3272 if (asc_dvc_varp->err_code) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003273 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3274 "error: 0x%x\n", boardp->id,
3275 asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003276 ret = FAILED;
3277 } else if (status) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003278 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3279 "warning: 0x%x\n", boardp->id, status);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003280 } else {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003281 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3282 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003285 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
3286 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003288 } else {
3289 /*
3290 * Wide Board
3291 *
3292 * If the suggest reset bus flags are set, then reset the bus.
3293 * Otherwise only reset the device.
3294 */
3295 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003297 /*
3298 * Reset the target's SCSI bus.
3299 */
3300 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
3301 switch (AdvResetChipAndSB(adv_dvc_varp)) {
3302 case ASC_TRUE:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003303 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3304 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003305 break;
3306 case ASC_FALSE:
3307 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003308 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3309 "error.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003310 ret = FAILED;
3311 break;
3312 }
3313 spin_lock_irqsave(&boardp->lock, flags);
3314 (void)AdvISR(adv_dvc_varp);
3315 }
3316 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003318 /* Save the time of the most recently completed reset. */
3319 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003321 /* Clear reset flag. */
3322 boardp->flags &= ~ASC_HOST_IN_RESET;
3323 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003325 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003327 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328}
3329
3330/*
3331 * advansys_biosparam()
3332 *
3333 * Translate disk drive geometry if the "BIOS greater than 1 GB"
3334 * support is enabled for a drive.
3335 *
3336 * ip (information pointer) is an int array with the following definition:
3337 * ip[0]: heads
3338 * ip[1]: sectors
3339 * ip[2]: cylinders
3340 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003341static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003343 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003345 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003347 ASC_DBG(1, "advansys_biosparam: begin\n");
3348 ASC_STATS(sdev->host, biosparam);
3349 boardp = ASC_BOARDP(sdev->host);
3350 if (ASC_NARROW_BOARD(boardp)) {
3351 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
3352 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
3353 ip[0] = 255;
3354 ip[1] = 63;
3355 } else {
3356 ip[0] = 64;
3357 ip[1] = 32;
3358 }
3359 } else {
3360 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
3361 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
3362 ip[0] = 255;
3363 ip[1] = 63;
3364 } else {
3365 ip[0] = 64;
3366 ip[1] = 32;
3367 }
3368 }
3369 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
3370 ASC_DBG(1, "advansys_biosparam: end\n");
3371 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372}
3373
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003374static struct scsi_host_template advansys_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003375 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003377 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003379 .name = "advansys",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003380 .info = advansys_info,
3381 .queuecommand = advansys_queuecommand,
3382 .eh_bus_reset_handler = advansys_reset,
3383 .bios_param = advansys_biosparam,
3384 .slave_configure = advansys_slave_configure,
3385 /*
3386 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003387 * must be set. The flag will be cleared in advansys_board_found
3388 * for non-ISA adapters.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003389 */
3390 .unchecked_isa_dma = 1,
3391 /*
3392 * All adapters controlled by this driver are capable of large
3393 * scatter-gather lists. According to the mid-level SCSI documentation
3394 * this obviates any performance gain provided by setting
3395 * 'use_clustering'. But empirically while CPU utilization is increased
3396 * by enabling clustering, I/O throughput increases as well.
3397 */
3398 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401/*
3402 * --- Miscellaneous Driver Functions
3403 */
3404
3405/*
3406 * First-level interrupt handler.
3407 *
3408 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
3409 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
3410 * is not referenced. 'dev_id' could be used to identify an interrupt passed
3411 * to the AdvanSys driver which is for a device sharing an interrupt with
3412 * an AdvanSys adapter.
3413 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003414static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415{
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003416 unsigned long flags;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003417 struct Scsi_Host *shost = dev_id;
3418 asc_board_t *boardp = ASC_BOARDP(shost);
3419 irqreturn_t result = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003421 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
3422 spin_lock_irqsave(&boardp->lock, flags);
3423 if (ASC_NARROW_BOARD(boardp)) {
3424 /*
3425 * Narrow Board
3426 */
3427 if (AscIsIntPending(shost->io_port)) {
3428 result = IRQ_HANDLED;
3429 ASC_STATS(shost, interrupt);
3430 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
3431 AscISR(&boardp->dvc_var.asc_dvc_var);
3432 }
3433 } else {
3434 /*
3435 * Wide Board
3436 */
3437 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
3438 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
3439 result = IRQ_HANDLED;
3440 ASC_STATS(shost, interrupt);
3441 }
3442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003444 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003446 /*
3447 * If interrupts were enabled on entry, then they
3448 * are now enabled here.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003449 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003451 ASC_DBG(1, "advansys_interrupt: end\n");
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003452 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453}
3454
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003455static void
3456advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
3457{
3458 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
3459 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
3460
3461 if (sdev->lun == 0) {
3462 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
3463 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
3464 asc_dvc->init_sdtr |= tid_bit;
3465 } else {
3466 asc_dvc->init_sdtr &= ~tid_bit;
3467 }
3468
3469 if (orig_init_sdtr != asc_dvc->init_sdtr)
3470 AscAsyncFix(asc_dvc, sdev);
3471 }
3472
3473 if (sdev->tagged_supported) {
3474 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
3475 if (sdev->lun == 0) {
3476 asc_dvc->cfg->can_tagged_qng |= tid_bit;
3477 asc_dvc->use_tagged_qng |= tid_bit;
3478 }
3479 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3480 asc_dvc->max_dvc_qng[sdev->id]);
3481 }
3482 } else {
3483 if (sdev->lun == 0) {
3484 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
3485 asc_dvc->use_tagged_qng &= ~tid_bit;
3486 }
3487 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3488 }
3489
3490 if ((sdev->lun == 0) &&
3491 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
3492 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
3493 asc_dvc->cfg->disc_enable);
3494 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
3495 asc_dvc->use_tagged_qng);
3496 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
3497 asc_dvc->cfg->can_tagged_qng);
3498
3499 asc_dvc->max_dvc_qng[sdev->id] =
3500 asc_dvc->cfg->max_tag_qng[sdev->id];
3501 AscWriteLramByte(asc_dvc->iop_base,
3502 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
3503 asc_dvc->max_dvc_qng[sdev->id]);
3504 }
3505}
3506
3507/*
3508 * Wide Transfers
3509 *
3510 * If the EEPROM enabled WDTR for the device and the device supports wide
3511 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
3512 * write the new value to the microcode.
3513 */
3514static void
3515advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
3516{
3517 unsigned short cfg_word;
3518 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3519 if ((cfg_word & tidmask) != 0)
3520 return;
3521
3522 cfg_word |= tidmask;
3523 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3524
3525 /*
3526 * Clear the microcode SDTR and WDTR negotiation done indicators for
3527 * the target to cause it to negotiate with the new setting set above.
3528 * WDTR when accepted causes the target to enter asynchronous mode, so
3529 * SDTR must be negotiated.
3530 */
3531 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3532 cfg_word &= ~tidmask;
3533 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3534 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3535 cfg_word &= ~tidmask;
3536 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3537}
3538
3539/*
3540 * Synchronous Transfers
3541 *
3542 * If the EEPROM enabled SDTR for the device and the device
3543 * supports synchronous transfers, then turn on the device's
3544 * 'sdtr_able' bit. Write the new value to the microcode.
3545 */
3546static void
3547advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
3548{
3549 unsigned short cfg_word;
3550 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3551 if ((cfg_word & tidmask) != 0)
3552 return;
3553
3554 cfg_word |= tidmask;
3555 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3556
3557 /*
3558 * Clear the microcode "SDTR negotiation" done indicator for the
3559 * target to cause it to negotiate with the new setting set above.
3560 */
3561 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3562 cfg_word &= ~tidmask;
3563 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3564}
3565
3566/*
3567 * PPR (Parallel Protocol Request) Capable
3568 *
3569 * If the device supports DT mode, then it must be PPR capable.
3570 * The PPR message will be used in place of the SDTR and WDTR
3571 * messages to negotiate synchronous speed and offset, transfer
3572 * width, and protocol options.
3573 */
3574static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
3575 AdvPortAddr iop_base, unsigned short tidmask)
3576{
3577 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3578 adv_dvc->ppr_able |= tidmask;
3579 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3580}
3581
3582static void
3583advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
3584{
3585 AdvPortAddr iop_base = adv_dvc->iop_base;
3586 unsigned short tidmask = 1 << sdev->id;
3587
3588 if (sdev->lun == 0) {
3589 /*
3590 * Handle WDTR, SDTR, and Tag Queuing. If the feature
3591 * is enabled in the EEPROM and the device supports the
3592 * feature, then enable it in the microcode.
3593 */
3594
3595 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
3596 advansys_wide_enable_wdtr(iop_base, tidmask);
3597 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
3598 advansys_wide_enable_sdtr(iop_base, tidmask);
3599 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
3600 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
3601
3602 /*
3603 * Tag Queuing is disabled for the BIOS which runs in polled
3604 * mode and would see no benefit from Tag Queuing. Also by
3605 * disabling Tag Queuing in the BIOS devices with Tag Queuing
3606 * bugs will at least work with the BIOS.
3607 */
3608 if ((adv_dvc->tagqng_able & tidmask) &&
3609 sdev->tagged_supported) {
3610 unsigned short cfg_word;
3611 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
3612 cfg_word |= tidmask;
3613 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
3614 cfg_word);
3615 AdvWriteByteLram(iop_base,
3616 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
3617 adv_dvc->max_dvc_qng);
3618 }
3619 }
3620
3621 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
3622 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3623 adv_dvc->max_dvc_qng);
3624 } else {
3625 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3626 }
3627}
3628
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629/*
3630 * Set the number of commands to queue per device for the
3631 * specified host adapter.
3632 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003633static int advansys_slave_configure(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003635 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003636 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003637
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003638 /*
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003639 * Save a pointer to the sdev and set its initial/maximum
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003640 * queue depth. Only save the pointer for a lun0 dev though.
3641 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003642 if (sdev->lun == 0)
3643 boardp->device[sdev->id] = sdev;
3644
3645 if (ASC_NARROW_BOARD(boardp))
3646 advansys_narrow_slave_configure(sdev,
3647 &boardp->dvc_var.asc_dvc_var);
3648 else
3649 advansys_wide_slave_configure(sdev,
3650 &boardp->dvc_var.adv_dvc_var);
3651
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003652 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653}
3654
3655/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 * Execute a single 'Scsi_Cmnd'.
3657 *
3658 * The function 'done' is called when the request has been completed.
3659 *
3660 * Scsi_Cmnd:
3661 *
3662 * host - board controlling device
3663 * device - device to send command
3664 * target - target of device
3665 * lun - lun of device
3666 * cmd_len - length of SCSI CDB
3667 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
3668 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
3669 *
3670 * if (use_sg == 0) {
3671 * request_buffer - buffer address for request
3672 * request_bufflen - length of request buffer
3673 * } else {
3674 * request_buffer - pointer to scatterlist structure
3675 * }
3676 *
3677 * sense_buffer - sense command buffer
3678 *
3679 * result (4 bytes of an int):
3680 * Byte Meaning
3681 * 0 SCSI Status Byte Code
3682 * 1 SCSI One Byte Message Code
3683 * 2 Host Error Code
3684 * 3 Mid-Level Error Code
3685 *
3686 * host driver fields:
3687 * SCp - Scsi_Pointer used for command processing status
3688 * scsi_done - used to save caller's done function
3689 * host_scribble - used for pointer to another struct scsi_cmnd
3690 *
Matthew Wilcox349d2c42007-09-09 08:56:34 -06003691 * If this function returns ASC_NOERROR the request will be completed
3692 * from the interrupt handler.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003694 * If this function returns ASC_ERROR the host error code has been set,
3695 * and the called must call asc_scsi_done.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 *
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003697 * If ASC_BUSY is returned the request will be returned to the midlayer
3698 * and re-tried later.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003700static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003702 asc_board_t *boardp;
3703 ASC_DVC_VAR *asc_dvc_varp;
3704 ADV_DVC_VAR *adv_dvc_varp;
3705 ADV_SCSI_REQ_Q *adv_scsiqp;
3706 struct scsi_device *device;
3707 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003709 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
3710 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003712 boardp = ASC_BOARDP(scp->device->host);
3713 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003715 if (ASC_NARROW_BOARD(boardp)) {
3716 /*
3717 * Build and execute Narrow Board request.
3718 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003720 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003722 /*
3723 * Build Asc Library request structure using the
3724 * global structures 'asc_scsi_req' and 'asc_sg_head'.
3725 *
3726 * If an error is returned, then the request has been
3727 * queued on the board done queue. It will be completed
3728 * by the caller.
3729 *
3730 * asc_build_req() can not return ASC_BUSY.
3731 */
3732 if (asc_build_req(boardp, scp) == ASC_ERROR) {
3733 ASC_STATS(scp->device->host, build_error);
3734 return ASC_ERROR;
3735 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003737 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
3738 case ASC_NOERROR:
3739 ASC_STATS(scp->device->host, exe_noerror);
3740 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003741 * Increment monotonically increasing per device
3742 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003743 */
3744 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003745 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), "
3746 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003747 break;
3748 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003749 ASC_STATS(scp->device->host, exe_busy);
3750 break;
3751 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003752 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3753 "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3754 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003755 ASC_STATS(scp->device->host, exe_error);
3756 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003757 break;
3758 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003759 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3760 "AscExeScsiQueue() unknown, err_code 0x%x\n",
3761 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003762 ASC_STATS(scp->device->host, exe_unknown);
3763 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003764 break;
3765 }
3766 } else {
3767 /*
3768 * Build and execute Wide Board request.
3769 */
3770 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003772 /*
3773 * Build and get a pointer to an Adv Library request structure.
3774 *
3775 * If the request is successfully built then send it below,
3776 * otherwise return with an error.
3777 */
3778 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
3779 case ASC_NOERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003780 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
3781 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003782 break;
3783 case ASC_BUSY:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003784 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3785 "ASC_BUSY\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003786 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003787 * The asc_stats fields 'adv_build_noreq' and
3788 * 'adv_build_nosg' count wide board busy conditions.
3789 * They are updated in adv_build_req and
3790 * adv_get_sglist, respectively.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003791 */
3792 return ASC_BUSY;
3793 case ASC_ERROR:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003794 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003795 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3796 "ASC_ERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003797 ASC_STATS(scp->device->host, build_error);
3798 return ASC_ERROR;
3799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003801 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
3802 case ASC_NOERROR:
3803 ASC_STATS(scp->device->host, exe_noerror);
3804 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003805 * Increment monotonically increasing per device
3806 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003807 */
3808 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003809 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), "
3810 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003811 break;
3812 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003813 ASC_STATS(scp->device->host, exe_busy);
3814 break;
3815 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003816 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3817 "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3818 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003819 ASC_STATS(scp->device->host, exe_error);
3820 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003821 break;
3822 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003823 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3824 "AdvExeScsiQueue() unknown, err_code 0x%x\n",
3825 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003826 ASC_STATS(scp->device->host, exe_unknown);
3827 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003828 break;
3829 }
3830 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003832 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
3833 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834}
3835
3836/*
3837 * Build a request structure for the Asc Library (Narrow Board).
3838 *
3839 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
3840 * used to build the request.
3841 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003842 * If an error occurs, then return ASC_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003844static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003846 /*
3847 * Mutually exclusive access is required to 'asc_scsi_q' and
3848 * 'asc_sg_head' until after the request is started.
3849 */
3850 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003852 /*
3853 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
3854 */
3855 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003857 /*
3858 * Build the ASC_SCSI_Q request.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003859 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003860 asc_scsi_q.cdbptr = &scp->cmnd[0];
3861 asc_scsi_q.q2.cdb_len = scp->cmd_len;
3862 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
3863 asc_scsi_q.q1.target_lun = scp->device->lun;
3864 asc_scsi_q.q2.target_ix =
3865 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
3866 asc_scsi_q.q1.sense_addr =
3867 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
3868 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003870 /*
3871 * If there are any outstanding requests for the current target,
3872 * then every 255th request send an ORDERED request. This heuristic
3873 * tries to retain the benefit of request sorting while preventing
3874 * request starvation. 255 is the max number of tags or pending commands
3875 * a device may have outstanding.
3876 *
3877 * The request count is incremented below for every successfully
3878 * started request.
3879 *
3880 */
3881 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
3882 (boardp->reqcnt[scp->device->id] % 255) == 0) {
3883 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
3884 } else {
3885 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
3886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003888 /*
3889 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
3890 * buffer command.
3891 */
3892 if (scp->use_sg == 0) {
3893 /*
3894 * CDB request of single contiguous buffer.
3895 */
3896 ASC_STATS(scp->device->host, cont_cnt);
3897 scp->SCp.dma_handle = scp->request_bufflen ?
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003898 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003899 scp->request_bufflen,
3900 scp->sc_data_direction) : 0;
3901 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
3902 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
3903 ASC_STATS_ADD(scp->device->host, cont_xfer,
3904 ASC_CEILING(scp->request_bufflen, 512));
3905 asc_scsi_q.q1.sg_queue_cnt = 0;
3906 asc_scsi_q.sg_head = NULL;
3907 } else {
3908 /*
3909 * CDB scatter-gather request list.
3910 */
3911 int sgcnt;
3912 int use_sg;
3913 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003915 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003916 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
3917 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003919 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003920 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
3921 "sg_tablesize %d\n", boardp->id, use_sg,
3922 scp->device->host->sg_tablesize);
3923 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003924 scp->sc_data_direction);
3925 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003926 return ASC_ERROR;
3927 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003929 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003931 /*
3932 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
3933 * structure to point to it.
3934 */
3935 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003937 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
3938 asc_scsi_q.sg_head = &asc_sg_head;
3939 asc_scsi_q.q1.data_cnt = 0;
3940 asc_scsi_q.q1.data_addr = 0;
3941 /* This is a byte value, otherwise it would need to be swapped. */
3942 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
3943 ASC_STATS_ADD(scp->device->host, sg_elem,
3944 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003946 /*
3947 * Convert scatter-gather list into ASC_SG_HEAD list.
3948 */
3949 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
3950 asc_sg_head.sg_list[sgcnt].addr =
3951 cpu_to_le32(sg_dma_address(slp));
3952 asc_sg_head.sg_list[sgcnt].bytes =
3953 cpu_to_le32(sg_dma_len(slp));
3954 ASC_STATS_ADD(scp->device->host, sg_xfer,
3955 ASC_CEILING(sg_dma_len(slp), 512));
3956 }
3957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003959 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
3960 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003962 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963}
3964
3965/*
3966 * Build a request structure for the Adv Library (Wide Board).
3967 *
3968 * If an adv_req_t can not be allocated to issue the request,
3969 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
3970 *
3971 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
3972 * microcode for DMA addresses or math operations are byte swapped
3973 * to little-endian order.
3974 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003975static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003977 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003979 adv_req_t *reqp;
3980 ADV_SCSI_REQ_Q *scsiqp;
3981 int i;
3982 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003984 /*
3985 * Allocate an adv_req_t structure from the board to execute
3986 * the command.
3987 */
3988 if (boardp->adv_reqp == NULL) {
3989 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
3990 ASC_STATS(scp->device->host, adv_build_noreq);
3991 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003993 reqp = boardp->adv_reqp;
3994 boardp->adv_reqp = reqp->next_reqp;
3995 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003998 /*
3999 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
4000 */
4001 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004003 /*
4004 * Initialize the structure.
4005 */
4006 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004008 /*
4009 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
4010 */
4011 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004013 /*
4014 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
4015 */
4016 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004018 /*
4019 * Build the ADV_SCSI_REQ_Q request.
4020 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021
Matthew Wilcoxf05ec592007-09-09 08:56:36 -06004022 /* Set CDB length and copy it to the request structure. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004023 scsiqp->cdb_len = scp->cmd_len;
4024 /* Copy first 12 CDB bytes to cdb[]. */
4025 for (i = 0; i < scp->cmd_len && i < 12; i++) {
4026 scsiqp->cdb[i] = scp->cmnd[i];
4027 }
4028 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
4029 for (; i < scp->cmd_len; i++) {
4030 scsiqp->cdb16[i - 12] = scp->cmnd[i];
4031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004033 scsiqp->target_id = scp->device->id;
4034 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004036 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4037 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004039 /*
4040 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
4041 * buffer command.
4042 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004044 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4045 scsiqp->vdata_addr = scp->request_buffer;
4046 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
4047
4048 if (scp->use_sg == 0) {
4049 /*
4050 * CDB request of single contiguous buffer.
4051 */
4052 reqp->sgblkp = NULL;
4053 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4054 if (scp->request_bufflen) {
4055 scsiqp->vdata_addr = scp->request_buffer;
4056 scp->SCp.dma_handle =
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004057 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004058 scp->request_bufflen,
4059 scp->sc_data_direction);
4060 } else {
4061 scsiqp->vdata_addr = NULL;
4062 scp->SCp.dma_handle = 0;
4063 }
4064 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
4065 scsiqp->sg_list_ptr = NULL;
4066 scsiqp->sg_real_addr = 0;
4067 ASC_STATS(scp->device->host, cont_cnt);
4068 ASC_STATS_ADD(scp->device->host, cont_xfer,
4069 ASC_CEILING(scp->request_bufflen, 512));
4070 } else {
4071 /*
4072 * CDB scatter-gather request list.
4073 */
4074 struct scatterlist *slp;
4075 int use_sg;
4076
4077 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004078 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4079 scp->sc_data_direction);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004080
4081 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004082 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
4083 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
4084 scp->device->host->sg_tablesize);
4085 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004086 scp->sc_data_direction);
4087 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004088
4089 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004090 * Free the 'adv_req_t' structure by adding it back
4091 * to the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004092 */
4093 reqp->next_reqp = boardp->adv_reqp;
4094 boardp->adv_reqp = reqp;
4095
4096 return ASC_ERROR;
4097 }
4098
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004099 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
4100 if (ret != ADV_SUCCESS) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004101 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004102 * Free the adv_req_t structure by adding it back to
4103 * the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004104 */
4105 reqp->next_reqp = boardp->adv_reqp;
4106 boardp->adv_reqp = reqp;
4107
4108 return ret;
4109 }
4110
4111 ASC_STATS(scp->device->host, sg_cnt);
4112 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
4113 }
4114
4115 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
4116 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
4117
4118 *adv_scsiqpp = scsiqp;
4119
4120 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121}
4122
4123/*
4124 * Build scatter-gather list for Adv Library (Wide Board).
4125 *
4126 * Additional ADV_SG_BLOCK structures will need to be allocated
4127 * if the total number of scatter-gather elements exceeds
4128 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
4129 * assumed to be physically contiguous.
4130 *
4131 * Return:
4132 * ADV_SUCCESS(1) - SG List successfully created
4133 * ADV_ERROR(-1) - SG List creation failed
4134 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004135static int
4136adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
4137 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004139 adv_sgblk_t *sgblkp;
4140 ADV_SCSI_REQ_Q *scsiqp;
4141 struct scatterlist *slp;
4142 int sg_elem_cnt;
4143 ADV_SG_BLOCK *sg_block, *prev_sg_block;
4144 ADV_PADDR sg_block_paddr;
4145 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004147 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
4148 slp = (struct scatterlist *)scp->request_buffer;
4149 sg_elem_cnt = use_sg;
4150 prev_sg_block = NULL;
4151 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004153 do {
4154 /*
4155 * Allocate a 'adv_sgblk_t' structure from the board free
4156 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
4157 * (15) scatter-gather elements.
4158 */
4159 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
4160 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
4161 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004163 /*
4164 * Allocation failed. Free 'adv_sgblk_t' structures already
4165 * allocated for the request.
4166 */
4167 while ((sgblkp = reqp->sgblkp) != NULL) {
4168 /* Remove 'sgblkp' from the request list. */
4169 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004171 /* Add 'sgblkp' to the board free list. */
4172 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4173 boardp->adv_sgblkp = sgblkp;
4174 }
4175 return ASC_BUSY;
4176 } else {
4177 /* Complete 'adv_sgblk_t' board allocation. */
4178 boardp->adv_sgblkp = sgblkp->next_sgblkp;
4179 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004181 /*
4182 * Get 8 byte aligned virtual and physical addresses for
4183 * the allocated ADV_SG_BLOCK structure.
4184 */
4185 sg_block =
4186 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
4187 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004189 /*
4190 * Check if this is the first 'adv_sgblk_t' for the request.
4191 */
4192 if (reqp->sgblkp == NULL) {
4193 /* Request's first scatter-gather block. */
4194 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004196 /*
4197 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
4198 * address pointers.
4199 */
4200 scsiqp->sg_list_ptr = sg_block;
4201 scsiqp->sg_real_addr =
4202 cpu_to_le32(sg_block_paddr);
4203 } else {
4204 /* Request's second or later scatter-gather block. */
4205 sgblkp->next_sgblkp = reqp->sgblkp;
4206 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004208 /*
4209 * Point the previous ADV_SG_BLOCK structure to
4210 * the newly allocated ADV_SG_BLOCK structure.
4211 */
4212 ASC_ASSERT(prev_sg_block != NULL);
4213 prev_sg_block->sg_ptr =
4214 cpu_to_le32(sg_block_paddr);
4215 }
4216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004218 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
4219 sg_block->sg_list[i].sg_addr =
4220 cpu_to_le32(sg_dma_address(slp));
4221 sg_block->sg_list[i].sg_count =
4222 cpu_to_le32(sg_dma_len(slp));
4223 ASC_STATS_ADD(scp->device->host, sg_xfer,
4224 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004226 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
4227 sg_block->sg_cnt = i + 1;
4228 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
4229 return ADV_SUCCESS;
4230 }
4231 slp++;
4232 }
4233 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
4234 prev_sg_block = sg_block;
4235 }
4236 while (1);
4237 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238}
4239
4240/*
4241 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
4242 *
4243 * Interrupt callback function for the Narrow SCSI Asc Library.
4244 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004245static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004247 asc_board_t *boardp;
4248 struct scsi_cmnd *scp;
4249 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004251 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
4252 (ulong)asc_dvc_varp, (ulong)qdonep);
4253 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004255 /*
4256 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4257 * command that has been completed.
4258 */
4259 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
4260 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004262 if (scp == NULL) {
4263 ASC_PRINT("asc_isr_callback: scp is NULL\n");
4264 return;
4265 }
4266 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004268 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004269 ASC_STATS(shost, callback);
4270 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004272 boardp = ASC_BOARDP(shost);
4273 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004275 /*
4276 * 'qdonep' contains the command's ending status.
4277 */
4278 switch (qdonep->d3.done_stat) {
4279 case QD_NO_ERROR:
4280 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
4281 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004283 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004284 * Check for an underrun condition.
4285 *
4286 * If there was no error and an underrun condition, then
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004287 * return the number of underrun bytes.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004288 */
4289 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
4290 qdonep->remain_bytes <= scp->request_bufflen) {
4291 ASC_DBG1(1,
4292 "asc_isr_callback: underrun condition %u bytes\n",
4293 (unsigned)qdonep->remain_bytes);
4294 scp->resid = qdonep->remain_bytes;
4295 }
4296 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004298 case QD_WITH_ERROR:
4299 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
4300 switch (qdonep->d3.host_stat) {
4301 case QHSTA_NO_ERROR:
4302 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
4303 ASC_DBG(2,
4304 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4305 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4306 sizeof(scp->sense_buffer));
4307 /*
4308 * Note: The 'status_byte()' macro used by target drivers
4309 * defined in scsi.h shifts the status byte returned by
4310 * host drivers right by 1 bit. This is why target drivers
4311 * also use right shifted status byte definitions. For
4312 * instance target drivers use CHECK_CONDITION, defined to
4313 * 0x1, instead of the SCSI defined check condition value
4314 * of 0x2. Host drivers are supposed to return the status
4315 * byte as it is defined by SCSI.
4316 */
4317 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4318 STATUS_BYTE(qdonep->d3.scsi_stat);
4319 } else {
4320 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
4321 }
4322 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004324 default:
4325 /* QHSTA error occurred */
4326 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
4327 qdonep->d3.host_stat);
4328 scp->result = HOST_BYTE(DID_BAD_TARGET);
4329 break;
4330 }
4331 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004333 case QD_ABORTED_BY_HOST:
4334 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
4335 scp->result =
4336 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
4337 scsi_msg) |
4338 STATUS_BYTE(qdonep->d3.scsi_stat);
4339 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004341 default:
4342 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
4343 qdonep->d3.done_stat);
4344 scp->result =
4345 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
4346 scsi_msg) |
4347 STATUS_BYTE(qdonep->d3.scsi_stat);
4348 break;
4349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004351 /*
4352 * If the 'init_tidmask' bit isn't already set for the target and the
4353 * current request finished normally, then set the bit for the target
4354 * to indicate that a device is present.
4355 */
4356 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4357 qdonep->d3.done_stat == QD_NO_ERROR &&
4358 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
4359 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004362 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004364 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365}
4366
4367/*
4368 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
4369 *
4370 * Callback function for the Wide SCSI Adv Library.
4371 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004372static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004374 asc_board_t *boardp;
4375 adv_req_t *reqp;
4376 adv_sgblk_t *sgblkp;
4377 struct scsi_cmnd *scp;
4378 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004379 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004381 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
4382 (ulong)adv_dvc_varp, (ulong)scsiqp);
4383 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004385 /*
4386 * Get the adv_req_t structure for the command that has been
4387 * completed. The adv_req_t structure actually contains the
4388 * completed ADV_SCSI_REQ_Q structure.
4389 */
4390 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
4391 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
4392 if (reqp == NULL) {
4393 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
4394 return;
4395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004397 /*
4398 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4399 * command that has been completed.
4400 *
4401 * Note: The adv_req_t request structure and adv_sgblk_t structure,
4402 * if any, are dropped, because a board structure pointer can not be
4403 * determined.
4404 */
4405 scp = reqp->cmndp;
4406 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
4407 if (scp == NULL) {
4408 ASC_PRINT
4409 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
4410 return;
4411 }
4412 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004414 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004415 ASC_STATS(shost, callback);
4416 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004418 boardp = ASC_BOARDP(shost);
4419 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004421 /*
4422 * 'done_status' contains the command's ending status.
4423 */
4424 switch (scsiqp->done_status) {
4425 case QD_NO_ERROR:
4426 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
4427 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004429 /*
4430 * Check for an underrun condition.
4431 *
4432 * If there was no error and an underrun condition, then
4433 * then return the number of underrun bytes.
4434 */
4435 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
4436 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
4437 resid_cnt <= scp->request_bufflen) {
4438 ASC_DBG1(1,
4439 "adv_isr_callback: underrun condition %lu bytes\n",
4440 (ulong)resid_cnt);
4441 scp->resid = resid_cnt;
4442 }
4443 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004445 case QD_WITH_ERROR:
4446 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
4447 switch (scsiqp->host_status) {
4448 case QHSTA_NO_ERROR:
4449 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
4450 ASC_DBG(2,
4451 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4452 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4453 sizeof(scp->sense_buffer));
4454 /*
4455 * Note: The 'status_byte()' macro used by target drivers
4456 * defined in scsi.h shifts the status byte returned by
4457 * host drivers right by 1 bit. This is why target drivers
4458 * also use right shifted status byte definitions. For
4459 * instance target drivers use CHECK_CONDITION, defined to
4460 * 0x1, instead of the SCSI defined check condition value
4461 * of 0x2. Host drivers are supposed to return the status
4462 * byte as it is defined by SCSI.
4463 */
4464 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4465 STATUS_BYTE(scsiqp->scsi_status);
4466 } else {
4467 scp->result = STATUS_BYTE(scsiqp->scsi_status);
4468 }
4469 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004471 default:
4472 /* Some other QHSTA error occurred. */
4473 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
4474 scsiqp->host_status);
4475 scp->result = HOST_BYTE(DID_BAD_TARGET);
4476 break;
4477 }
4478 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004480 case QD_ABORTED_BY_HOST:
4481 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
4482 scp->result =
4483 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
4484 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004486 default:
4487 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
4488 scsiqp->done_status);
4489 scp->result =
4490 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
4491 break;
4492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004494 /*
4495 * If the 'init_tidmask' bit isn't already set for the target and the
4496 * current request finished normally, then set the bit for the target
4497 * to indicate that a device is present.
4498 */
4499 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4500 scsiqp->done_status == QD_NO_ERROR &&
4501 scsiqp->host_status == QHSTA_NO_ERROR) {
4502 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004505 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004507 /*
4508 * Free all 'adv_sgblk_t' structures allocated for the request.
4509 */
4510 while ((sgblkp = reqp->sgblkp) != NULL) {
4511 /* Remove 'sgblkp' from the request list. */
4512 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004514 /* Add 'sgblkp' to the board free list. */
4515 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4516 boardp->adv_sgblkp = sgblkp;
4517 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004519 /*
4520 * Free the adv_req_t structure used with the command by adding
4521 * it back to the board free list.
4522 */
4523 reqp->next_reqp = boardp->adv_reqp;
4524 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004526 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004528 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529}
4530
4531/*
4532 * adv_async_callback() - Adv Library asynchronous event callback function.
4533 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004534static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004536 switch (code) {
4537 case ADV_ASYNC_SCSI_BUS_RESET_DET:
4538 /*
4539 * The firmware detected a SCSI Bus reset.
4540 */
4541 ASC_DBG(0,
4542 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
4543 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004545 case ADV_ASYNC_RDMA_FAILURE:
4546 /*
4547 * Handle RDMA failure by resetting the SCSI Bus and
4548 * possibly the chip if it is unresponsive. Log the error
4549 * with a unique code.
4550 */
4551 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
4552 AdvResetChipAndSB(adv_dvc_varp);
4553 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004555 case ADV_HOST_SCSI_BUS_RESET:
4556 /*
4557 * Host generated SCSI bus reset occurred.
4558 */
4559 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
4560 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004562 default:
4563 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
4564 break;
4565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566}
4567
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568#ifdef CONFIG_PROC_FS
4569/*
4570 * asc_prt_board_devices()
4571 *
4572 * Print driver information for devices attached to the board.
4573 *
4574 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4575 * cf. asc_prt_line().
4576 *
4577 * Return the number of characters copied into 'cp'. No more than
4578 * 'cplen' characters will be copied to 'cp'.
4579 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004580static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004582 asc_board_t *boardp;
4583 int leftlen;
4584 int totlen;
4585 int len;
4586 int chip_scsi_id;
4587 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004589 boardp = ASC_BOARDP(shost);
4590 leftlen = cplen;
4591 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004593 len = asc_prt_line(cp, leftlen,
4594 "\nDevice Information for AdvanSys SCSI Host %d:\n",
4595 shost->host_no);
4596 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004598 if (ASC_NARROW_BOARD(boardp)) {
4599 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
4600 } else {
4601 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
4602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004604 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
4605 ASC_PRT_NEXT();
4606 for (i = 0; i <= ADV_MAX_TID; i++) {
4607 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
4608 len = asc_prt_line(cp, leftlen, " %X,", i);
4609 ASC_PRT_NEXT();
4610 }
4611 }
4612 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
4613 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004615 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616}
4617
4618/*
4619 * Display Wide Board BIOS Information.
4620 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004621static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004623 asc_board_t *boardp;
4624 int leftlen;
4625 int totlen;
4626 int len;
4627 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004629 boardp = ASC_BOARDP(shost);
4630 leftlen = cplen;
4631 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004633 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
4634 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004636 /*
4637 * If the BIOS saved a valid signature, then fill in
4638 * the BIOS code segment base address.
4639 */
4640 if (boardp->bios_signature != 0x55AA) {
4641 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
4642 ASC_PRT_NEXT();
4643 len = asc_prt_line(cp, leftlen,
4644 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
4645 ASC_PRT_NEXT();
4646 len = asc_prt_line(cp, leftlen,
4647 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
4648 ASC_PRT_NEXT();
4649 } else {
4650 major = (boardp->bios_version >> 12) & 0xF;
4651 minor = (boardp->bios_version >> 8) & 0xF;
4652 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004654 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
4655 major, minor,
4656 letter >= 26 ? '?' : letter + 'A');
4657 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004659 /*
4660 * Current available ROM BIOS release is 3.1I for UW
4661 * and 3.2I for U2W. This code doesn't differentiate
4662 * UW and U2W boards.
4663 */
4664 if (major < 3 || (major <= 3 && minor < 1) ||
4665 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
4666 len = asc_prt_line(cp, leftlen,
4667 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
4668 ASC_PRT_NEXT();
4669 len = asc_prt_line(cp, leftlen,
4670 "ftp://ftp.connectcom.net/pub\n");
4671 ASC_PRT_NEXT();
4672 }
4673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004675 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676}
4677
4678/*
4679 * Add serial number to information bar if signature AAh
4680 * is found in at bit 15-9 (7 bits) of word 1.
4681 *
4682 * Serial Number consists fo 12 alpha-numeric digits.
4683 *
4684 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
4685 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
4686 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
4687 * 5 - Product revision (A-J) Word0: " "
4688 *
4689 * Signature Word1: 15-9 (7 bits)
4690 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
4691 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
4692 *
4693 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
4694 *
4695 * Note 1: Only production cards will have a serial number.
4696 *
4697 * Note 2: Signature is most significant 7 bits (0xFE).
4698 *
4699 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
4700 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004701static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004703 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004705 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
4706 return ASC_FALSE;
4707 } else {
4708 /*
4709 * First word - 6 digits.
4710 */
4711 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004713 /* Product type - 1st digit. */
4714 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
4715 /* Product type is P=Prototype */
4716 *cp += 0x8;
4717 }
4718 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004720 /* Manufacturing location - 2nd digit. */
4721 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004722
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004723 /* Product ID - 3rd, 4th digits. */
4724 num = w & 0x3FF;
4725 *cp++ = '0' + (num / 100);
4726 num %= 100;
4727 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004729 /* Product revision - 5th digit. */
4730 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004732 /*
4733 * Second word
4734 */
4735 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004737 /*
4738 * Year - 6th digit.
4739 *
4740 * If bit 15 of third word is set, then the
4741 * last digit of the year is greater than 7.
4742 */
4743 if (serialnum[2] & 0x8000) {
4744 *cp++ = '8' + ((w & 0x1C0) >> 6);
4745 } else {
4746 *cp++ = '0' + ((w & 0x1C0) >> 6);
4747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004749 /* Week of year - 7th, 8th digits. */
4750 num = w & 0x003F;
4751 *cp++ = '0' + num / 10;
4752 num %= 10;
4753 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004755 /*
4756 * Third word
4757 */
4758 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004760 /* Serial number - 9th digit. */
4761 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004763 /* 10th, 11th, 12th digits. */
4764 num = w % 1000;
4765 *cp++ = '0' + num / 100;
4766 num %= 100;
4767 *cp++ = '0' + num / 10;
4768 num %= 10;
4769 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004771 *cp = '\0'; /* Null Terminate the string. */
4772 return ASC_TRUE;
4773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774}
4775
4776/*
4777 * asc_prt_asc_board_eeprom()
4778 *
4779 * Print board EEPROM configuration.
4780 *
4781 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4782 * cf. asc_prt_line().
4783 *
4784 * Return the number of characters copied into 'cp'. No more than
4785 * 'cplen' characters will be copied to 'cp'.
4786 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004787static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004789 asc_board_t *boardp;
4790 ASC_DVC_VAR *asc_dvc_varp;
4791 int leftlen;
4792 int totlen;
4793 int len;
4794 ASCEEP_CONFIG *ep;
4795 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004797 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004799 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004800
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004801 boardp = ASC_BOARDP(shost);
4802 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4803 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004805 leftlen = cplen;
4806 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004808 len = asc_prt_line(cp, leftlen,
4809 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4810 shost->host_no);
4811 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004813 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
4814 == ASC_TRUE) {
4815 len =
4816 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4817 serialstr);
4818 ASC_PRT_NEXT();
4819 } else {
4820 if (ep->adapter_info[5] == 0xBB) {
4821 len = asc_prt_line(cp, leftlen,
4822 " Default Settings Used for EEPROM-less Adapter.\n");
4823 ASC_PRT_NEXT();
4824 } else {
4825 len = asc_prt_line(cp, leftlen,
4826 " Serial Number Signature Not Present.\n");
4827 ASC_PRT_NEXT();
4828 }
4829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004831 len = asc_prt_line(cp, leftlen,
4832 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4833 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
4834 ep->max_tag_qng);
4835 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004837 len = asc_prt_line(cp, leftlen,
4838 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
4839 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004841 len = asc_prt_line(cp, leftlen, " Target ID: ");
4842 ASC_PRT_NEXT();
4843 for (i = 0; i <= ASC_MAX_TID; i++) {
4844 len = asc_prt_line(cp, leftlen, " %d", i);
4845 ASC_PRT_NEXT();
4846 }
4847 len = asc_prt_line(cp, leftlen, "\n");
4848 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004850 len = asc_prt_line(cp, leftlen, " Disconnects: ");
4851 ASC_PRT_NEXT();
4852 for (i = 0; i <= ASC_MAX_TID; i++) {
4853 len = asc_prt_line(cp, leftlen, " %c",
4854 (ep->
4855 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4856 'N');
4857 ASC_PRT_NEXT();
4858 }
4859 len = asc_prt_line(cp, leftlen, "\n");
4860 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004862 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
4863 ASC_PRT_NEXT();
4864 for (i = 0; i <= ASC_MAX_TID; i++) {
4865 len = asc_prt_line(cp, leftlen, " %c",
4866 (ep->
4867 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4868 'N');
4869 ASC_PRT_NEXT();
4870 }
4871 len = asc_prt_line(cp, leftlen, "\n");
4872 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004874 len = asc_prt_line(cp, leftlen, " Start Motor: ");
4875 ASC_PRT_NEXT();
4876 for (i = 0; i <= ASC_MAX_TID; i++) {
4877 len = asc_prt_line(cp, leftlen, " %c",
4878 (ep->
4879 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4880 'N');
4881 ASC_PRT_NEXT();
4882 }
4883 len = asc_prt_line(cp, leftlen, "\n");
4884 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004885
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004886 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
4887 ASC_PRT_NEXT();
4888 for (i = 0; i <= ASC_MAX_TID; i++) {
4889 len = asc_prt_line(cp, leftlen, " %c",
4890 (ep->
4891 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4892 'N');
4893 ASC_PRT_NEXT();
4894 }
4895 len = asc_prt_line(cp, leftlen, "\n");
4896 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897
4898#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004899 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4900 len = asc_prt_line(cp, leftlen,
4901 " Host ISA DMA speed: %d MB/S\n",
4902 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
4903 ASC_PRT_NEXT();
4904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905#endif /* CONFIG_ISA */
4906
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004907 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908}
4909
4910/*
4911 * asc_prt_adv_board_eeprom()
4912 *
4913 * Print board EEPROM configuration.
4914 *
4915 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4916 * cf. asc_prt_line().
4917 *
4918 * Return the number of characters copied into 'cp'. No more than
4919 * 'cplen' characters will be copied to 'cp'.
4920 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004921static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004923 asc_board_t *boardp;
4924 ADV_DVC_VAR *adv_dvc_varp;
4925 int leftlen;
4926 int totlen;
4927 int len;
4928 int i;
4929 char *termstr;
4930 uchar serialstr[13];
4931 ADVEEP_3550_CONFIG *ep_3550 = NULL;
4932 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
4933 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
4934 ushort word;
4935 ushort *wordp;
4936 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004938 boardp = ASC_BOARDP(shost);
4939 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4940 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4941 ep_3550 = &boardp->eep_config.adv_3550_eep;
4942 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4943 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
4944 } else {
4945 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
4946 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004948 leftlen = cplen;
4949 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004950
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004951 len = asc_prt_line(cp, leftlen,
4952 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4953 shost->host_no);
4954 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004956 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4957 wordp = &ep_3550->serial_number_word1;
4958 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4959 wordp = &ep_38C0800->serial_number_word1;
4960 } else {
4961 wordp = &ep_38C1600->serial_number_word1;
4962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004964 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
4965 len =
4966 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4967 serialstr);
4968 ASC_PRT_NEXT();
4969 } else {
4970 len = asc_prt_line(cp, leftlen,
4971 " Serial Number Signature Not Present.\n");
4972 ASC_PRT_NEXT();
4973 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004974
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004975 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4976 len = asc_prt_line(cp, leftlen,
4977 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4978 ep_3550->adapter_scsi_id,
4979 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
4980 ASC_PRT_NEXT();
4981 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4982 len = asc_prt_line(cp, leftlen,
4983 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4984 ep_38C0800->adapter_scsi_id,
4985 ep_38C0800->max_host_qng,
4986 ep_38C0800->max_dvc_qng);
4987 ASC_PRT_NEXT();
4988 } else {
4989 len = asc_prt_line(cp, leftlen,
4990 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4991 ep_38C1600->adapter_scsi_id,
4992 ep_38C1600->max_host_qng,
4993 ep_38C1600->max_dvc_qng);
4994 ASC_PRT_NEXT();
4995 }
4996 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4997 word = ep_3550->termination;
4998 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4999 word = ep_38C0800->termination_lvd;
5000 } else {
5001 word = ep_38C1600->termination_lvd;
5002 }
5003 switch (word) {
5004 case 1:
5005 termstr = "Low Off/High Off";
5006 break;
5007 case 2:
5008 termstr = "Low Off/High On";
5009 break;
5010 case 3:
5011 termstr = "Low On/High On";
5012 break;
5013 default:
5014 case 0:
5015 termstr = "Automatic";
5016 break;
5017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005019 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5020 len = asc_prt_line(cp, leftlen,
5021 " termination: %u (%s), bios_ctrl: 0x%x\n",
5022 ep_3550->termination, termstr,
5023 ep_3550->bios_ctrl);
5024 ASC_PRT_NEXT();
5025 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5026 len = asc_prt_line(cp, leftlen,
5027 " termination: %u (%s), bios_ctrl: 0x%x\n",
5028 ep_38C0800->termination_lvd, termstr,
5029 ep_38C0800->bios_ctrl);
5030 ASC_PRT_NEXT();
5031 } else {
5032 len = asc_prt_line(cp, leftlen,
5033 " termination: %u (%s), bios_ctrl: 0x%x\n",
5034 ep_38C1600->termination_lvd, termstr,
5035 ep_38C1600->bios_ctrl);
5036 ASC_PRT_NEXT();
5037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005039 len = asc_prt_line(cp, leftlen, " Target ID: ");
5040 ASC_PRT_NEXT();
5041 for (i = 0; i <= ADV_MAX_TID; i++) {
5042 len = asc_prt_line(cp, leftlen, " %X", i);
5043 ASC_PRT_NEXT();
5044 }
5045 len = asc_prt_line(cp, leftlen, "\n");
5046 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005048 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5049 word = ep_3550->disc_enable;
5050 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5051 word = ep_38C0800->disc_enable;
5052 } else {
5053 word = ep_38C1600->disc_enable;
5054 }
5055 len = asc_prt_line(cp, leftlen, " Disconnects: ");
5056 ASC_PRT_NEXT();
5057 for (i = 0; i <= ADV_MAX_TID; i++) {
5058 len = asc_prt_line(cp, leftlen, " %c",
5059 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5060 ASC_PRT_NEXT();
5061 }
5062 len = asc_prt_line(cp, leftlen, "\n");
5063 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005065 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5066 word = ep_3550->tagqng_able;
5067 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5068 word = ep_38C0800->tagqng_able;
5069 } else {
5070 word = ep_38C1600->tagqng_able;
5071 }
5072 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
5073 ASC_PRT_NEXT();
5074 for (i = 0; i <= ADV_MAX_TID; i++) {
5075 len = asc_prt_line(cp, leftlen, " %c",
5076 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5077 ASC_PRT_NEXT();
5078 }
5079 len = asc_prt_line(cp, leftlen, "\n");
5080 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005082 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5083 word = ep_3550->start_motor;
5084 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5085 word = ep_38C0800->start_motor;
5086 } else {
5087 word = ep_38C1600->start_motor;
5088 }
5089 len = asc_prt_line(cp, leftlen, " Start Motor: ");
5090 ASC_PRT_NEXT();
5091 for (i = 0; i <= ADV_MAX_TID; i++) {
5092 len = asc_prt_line(cp, leftlen, " %c",
5093 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5094 ASC_PRT_NEXT();
5095 }
5096 len = asc_prt_line(cp, leftlen, "\n");
5097 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005099 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5100 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5101 ASC_PRT_NEXT();
5102 for (i = 0; i <= ADV_MAX_TID; i++) {
5103 len = asc_prt_line(cp, leftlen, " %c",
5104 (ep_3550->
5105 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
5106 'Y' : 'N');
5107 ASC_PRT_NEXT();
5108 }
5109 len = asc_prt_line(cp, leftlen, "\n");
5110 ASC_PRT_NEXT();
5111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005113 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5114 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
5115 ASC_PRT_NEXT();
5116 for (i = 0; i <= ADV_MAX_TID; i++) {
5117 len = asc_prt_line(cp, leftlen, " %c",
5118 (ep_3550->
5119 ultra_able & ADV_TID_TO_TIDMASK(i))
5120 ? 'Y' : 'N');
5121 ASC_PRT_NEXT();
5122 }
5123 len = asc_prt_line(cp, leftlen, "\n");
5124 ASC_PRT_NEXT();
5125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005127 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5128 word = ep_3550->wdtr_able;
5129 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5130 word = ep_38C0800->wdtr_able;
5131 } else {
5132 word = ep_38C1600->wdtr_able;
5133 }
5134 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
5135 ASC_PRT_NEXT();
5136 for (i = 0; i <= ADV_MAX_TID; i++) {
5137 len = asc_prt_line(cp, leftlen, " %c",
5138 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5139 ASC_PRT_NEXT();
5140 }
5141 len = asc_prt_line(cp, leftlen, "\n");
5142 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005144 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
5145 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
5146 len = asc_prt_line(cp, leftlen,
5147 " Synchronous Transfer Speed (Mhz):\n ");
5148 ASC_PRT_NEXT();
5149 for (i = 0; i <= ADV_MAX_TID; i++) {
5150 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005152 if (i == 0) {
5153 sdtr_speed = adv_dvc_varp->sdtr_speed1;
5154 } else if (i == 4) {
5155 sdtr_speed = adv_dvc_varp->sdtr_speed2;
5156 } else if (i == 8) {
5157 sdtr_speed = adv_dvc_varp->sdtr_speed3;
5158 } else if (i == 12) {
5159 sdtr_speed = adv_dvc_varp->sdtr_speed4;
5160 }
5161 switch (sdtr_speed & ADV_MAX_TID) {
5162 case 0:
5163 speed_str = "Off";
5164 break;
5165 case 1:
5166 speed_str = " 5";
5167 break;
5168 case 2:
5169 speed_str = " 10";
5170 break;
5171 case 3:
5172 speed_str = " 20";
5173 break;
5174 case 4:
5175 speed_str = " 40";
5176 break;
5177 case 5:
5178 speed_str = " 80";
5179 break;
5180 default:
5181 speed_str = "Unk";
5182 break;
5183 }
5184 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
5185 ASC_PRT_NEXT();
5186 if (i == 7) {
5187 len = asc_prt_line(cp, leftlen, "\n ");
5188 ASC_PRT_NEXT();
5189 }
5190 sdtr_speed >>= 4;
5191 }
5192 len = asc_prt_line(cp, leftlen, "\n");
5193 ASC_PRT_NEXT();
5194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005196 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197}
5198
5199/*
5200 * asc_prt_driver_conf()
5201 *
5202 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5203 * cf. asc_prt_line().
5204 *
5205 * Return the number of characters copied into 'cp'. No more than
5206 * 'cplen' characters will be copied to 'cp'.
5207 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005208static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005210 asc_board_t *boardp;
5211 int leftlen;
5212 int totlen;
5213 int len;
5214 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005216 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005218 leftlen = cplen;
5219 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005221 len = asc_prt_line(cp, leftlen,
5222 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
5223 shost->host_no);
5224 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005226 len = asc_prt_line(cp, leftlen,
5227 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
5228 shost->host_busy, shost->last_reset, shost->max_id,
5229 shost->max_lun, shost->max_channel);
5230 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005232 len = asc_prt_line(cp, leftlen,
5233 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
5234 shost->unique_id, shost->can_queue, shost->this_id,
5235 shost->sg_tablesize, shost->cmd_per_lun);
5236 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005238 len = asc_prt_line(cp, leftlen,
5239 " unchecked_isa_dma %d, use_clustering %d\n",
5240 shost->unchecked_isa_dma, shost->use_clustering);
5241 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005243 len = asc_prt_line(cp, leftlen,
5244 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
5245 boardp->flags, boardp->last_reset, jiffies,
5246 boardp->asc_n_io_port);
5247 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04005249 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005250 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005252 if (ASC_NARROW_BOARD(boardp)) {
5253 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
5254 } else {
5255 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
5256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005258 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259}
5260
5261/*
5262 * asc_prt_asc_board_info()
5263 *
5264 * Print dynamic board configuration information.
5265 *
5266 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5267 * cf. asc_prt_line().
5268 *
5269 * Return the number of characters copied into 'cp'. No more than
5270 * 'cplen' characters will be copied to 'cp'.
5271 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005272static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005274 asc_board_t *boardp;
5275 int chip_scsi_id;
5276 int leftlen;
5277 int totlen;
5278 int len;
5279 ASC_DVC_VAR *v;
5280 ASC_DVC_CFG *c;
5281 int i;
5282 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005284 boardp = ASC_BOARDP(shost);
5285 v = &boardp->dvc_var.asc_dvc_var;
5286 c = &boardp->dvc_cfg.asc_dvc_cfg;
5287 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005289 leftlen = cplen;
5290 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005292 len = asc_prt_line(cp, leftlen,
5293 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5294 shost->host_no);
5295 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005297 len = asc_prt_line(cp, leftlen,
5298 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
5299 c->chip_version, c->lib_version, c->lib_serial_no,
5300 c->mcode_date);
5301 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005303 len = asc_prt_line(cp, leftlen,
5304 " mcode_version 0x%x, err_code %u\n",
5305 c->mcode_version, v->err_code);
5306 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005307
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005308 /* Current number of commands waiting for the host. */
5309 len = asc_prt_line(cp, leftlen,
5310 " Total Command Pending: %d\n", v->cur_total_qng);
5311 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005313 len = asc_prt_line(cp, leftlen, " Command Queuing:");
5314 ASC_PRT_NEXT();
5315 for (i = 0; i <= ASC_MAX_TID; i++) {
5316 if ((chip_scsi_id == i) ||
5317 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5318 continue;
5319 }
5320 len = asc_prt_line(cp, leftlen, " %X:%c",
5321 i,
5322 (v->
5323 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
5324 'Y' : 'N');
5325 ASC_PRT_NEXT();
5326 }
5327 len = asc_prt_line(cp, leftlen, "\n");
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 a device. */
5331 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
5332 ASC_PRT_NEXT();
5333 for (i = 0; i <= ASC_MAX_TID; i++) {
5334 if ((chip_scsi_id == i) ||
5335 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5336 continue;
5337 }
5338 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
5339 ASC_PRT_NEXT();
5340 }
5341 len = asc_prt_line(cp, leftlen, "\n");
5342 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005344 /* Current limit on number of commands that can be sent to a device. */
5345 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
5346 ASC_PRT_NEXT();
5347 for (i = 0; i <= ASC_MAX_TID; i++) {
5348 if ((chip_scsi_id == i) ||
5349 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5350 continue;
5351 }
5352 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
5353 ASC_PRT_NEXT();
5354 }
5355 len = asc_prt_line(cp, leftlen, "\n");
5356 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005358 /* Indicate whether the device has returned queue full status. */
5359 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
5360 ASC_PRT_NEXT();
5361 for (i = 0; i <= ASC_MAX_TID; i++) {
5362 if ((chip_scsi_id == i) ||
5363 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5364 continue;
5365 }
5366 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
5367 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
5368 i, boardp->queue_full_cnt[i]);
5369 } else {
5370 len = asc_prt_line(cp, leftlen, " %X:N", i);
5371 }
5372 ASC_PRT_NEXT();
5373 }
5374 len = asc_prt_line(cp, leftlen, "\n");
5375 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005377 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5378 ASC_PRT_NEXT();
5379 for (i = 0; i <= ASC_MAX_TID; i++) {
5380 if ((chip_scsi_id == i) ||
5381 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5382 continue;
5383 }
5384 len = asc_prt_line(cp, leftlen, " %X:%c",
5385 i,
5386 (v->
5387 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5388 'N');
5389 ASC_PRT_NEXT();
5390 }
5391 len = asc_prt_line(cp, leftlen, "\n");
5392 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005394 for (i = 0; i <= ASC_MAX_TID; i++) {
5395 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005397 if ((chip_scsi_id == i) ||
5398 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5399 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
5400 continue;
5401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005403 len = asc_prt_line(cp, leftlen, " %X:", i);
5404 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005406 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
5407 len = asc_prt_line(cp, leftlen, " Asynchronous");
5408 ASC_PRT_NEXT();
5409 } else {
5410 syn_period_ix =
5411 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
5412 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005414 len = asc_prt_line(cp, leftlen,
5415 " Transfer Period Factor: %d (%d.%d Mhz),",
5416 v->sdtr_period_tbl[syn_period_ix],
5417 250 /
5418 v->sdtr_period_tbl[syn_period_ix],
5419 ASC_TENTHS(250,
5420 v->
5421 sdtr_period_tbl
5422 [syn_period_ix]));
5423 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005425 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5426 boardp->
5427 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
5428 ASC_PRT_NEXT();
5429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005431 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5432 len = asc_prt_line(cp, leftlen, "*\n");
5433 renegotiate = 1;
5434 } else {
5435 len = asc_prt_line(cp, leftlen, "\n");
5436 }
5437 ASC_PRT_NEXT();
5438 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005440 if (renegotiate) {
5441 len = asc_prt_line(cp, leftlen,
5442 " * = Re-negotiation pending before next command.\n");
5443 ASC_PRT_NEXT();
5444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005446 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447}
5448
5449/*
5450 * asc_prt_adv_board_info()
5451 *
5452 * Print dynamic board configuration information.
5453 *
5454 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5455 * cf. asc_prt_line().
5456 *
5457 * Return the number of characters copied into 'cp'. No more than
5458 * 'cplen' characters will be copied to 'cp'.
5459 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005460static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005462 asc_board_t *boardp;
5463 int leftlen;
5464 int totlen;
5465 int len;
5466 int i;
5467 ADV_DVC_VAR *v;
5468 ADV_DVC_CFG *c;
5469 AdvPortAddr iop_base;
5470 ushort chip_scsi_id;
5471 ushort lramword;
5472 uchar lrambyte;
5473 ushort tagqng_able;
5474 ushort sdtr_able, wdtr_able;
5475 ushort wdtr_done, sdtr_done;
5476 ushort period = 0;
5477 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005479 boardp = ASC_BOARDP(shost);
5480 v = &boardp->dvc_var.adv_dvc_var;
5481 c = &boardp->dvc_cfg.adv_dvc_cfg;
5482 iop_base = v->iop_base;
5483 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005485 leftlen = cplen;
5486 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005488 len = asc_prt_line(cp, leftlen,
5489 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5490 shost->host_no);
5491 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005493 len = asc_prt_line(cp, leftlen,
5494 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
5495 v->iop_base,
5496 AdvReadWordRegister(iop_base,
5497 IOPW_SCSI_CFG1) & CABLE_DETECT,
5498 v->err_code);
5499 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005501 len = asc_prt_line(cp, leftlen,
5502 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
5503 c->chip_version, c->lib_version, c->mcode_date,
5504 c->mcode_version);
5505 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005507 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
5508 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
5509 ASC_PRT_NEXT();
5510 for (i = 0; i <= ADV_MAX_TID; i++) {
5511 if ((chip_scsi_id == i) ||
5512 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5513 continue;
5514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005516 len = asc_prt_line(cp, leftlen, " %X:%c",
5517 i,
5518 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5519 'N');
5520 ASC_PRT_NEXT();
5521 }
5522 len = asc_prt_line(cp, leftlen, "\n");
5523 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005524
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005525 len = asc_prt_line(cp, leftlen, " Queue Limit:");
5526 ASC_PRT_NEXT();
5527 for (i = 0; i <= ADV_MAX_TID; i++) {
5528 if ((chip_scsi_id == i) ||
5529 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5530 continue;
5531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005533 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
5534 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005536 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5537 ASC_PRT_NEXT();
5538 }
5539 len = asc_prt_line(cp, leftlen, "\n");
5540 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005542 len = asc_prt_line(cp, leftlen, " Command Pending:");
5543 ASC_PRT_NEXT();
5544 for (i = 0; i <= ADV_MAX_TID; i++) {
5545 if ((chip_scsi_id == i) ||
5546 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5547 continue;
5548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005550 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
5551 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005553 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5554 ASC_PRT_NEXT();
5555 }
5556 len = asc_prt_line(cp, leftlen, "\n");
5557 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005558
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005559 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
5560 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
5561 ASC_PRT_NEXT();
5562 for (i = 0; i <= ADV_MAX_TID; i++) {
5563 if ((chip_scsi_id == i) ||
5564 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5565 continue;
5566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005568 len = asc_prt_line(cp, leftlen, " %X:%c",
5569 i,
5570 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5571 'N');
5572 ASC_PRT_NEXT();
5573 }
5574 len = asc_prt_line(cp, leftlen, "\n");
5575 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005577 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
5578 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
5579 ASC_PRT_NEXT();
5580 for (i = 0; i <= ADV_MAX_TID; i++) {
5581 if ((chip_scsi_id == i) ||
5582 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5583 continue;
5584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005586 AdvReadWordLram(iop_base,
5587 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5588 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005590 len = asc_prt_line(cp, leftlen, " %X:%d",
5591 i, (lramword & 0x8000) ? 16 : 8);
5592 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005593
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005594 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
5595 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5596 len = asc_prt_line(cp, leftlen, "*");
5597 ASC_PRT_NEXT();
5598 renegotiate = 1;
5599 }
5600 }
5601 len = asc_prt_line(cp, leftlen, "\n");
5602 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005604 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
5605 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
5606 ASC_PRT_NEXT();
5607 for (i = 0; i <= ADV_MAX_TID; i++) {
5608 if ((chip_scsi_id == i) ||
5609 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5610 continue;
5611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005612
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005613 len = asc_prt_line(cp, leftlen, " %X:%c",
5614 i,
5615 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5616 'N');
5617 ASC_PRT_NEXT();
5618 }
5619 len = asc_prt_line(cp, leftlen, "\n");
5620 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005622 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
5623 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005625 AdvReadWordLram(iop_base,
5626 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5627 lramword);
5628 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005630 if ((chip_scsi_id == i) ||
5631 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5632 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
5633 continue;
5634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005636 len = asc_prt_line(cp, leftlen, " %X:", i);
5637 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005639 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
5640 len = asc_prt_line(cp, leftlen, " Asynchronous");
5641 ASC_PRT_NEXT();
5642 } else {
5643 len =
5644 asc_prt_line(cp, leftlen,
5645 " Transfer Period Factor: ");
5646 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005648 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
5649 len =
5650 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
5651 ASC_PRT_NEXT();
5652 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
5653 len =
5654 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
5655 ASC_PRT_NEXT();
5656 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005658 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005660 if (period == 0) { /* Should never happen. */
5661 len =
5662 asc_prt_line(cp, leftlen,
5663 "%d (? Mhz), ");
5664 ASC_PRT_NEXT();
5665 } else {
5666 len = asc_prt_line(cp, leftlen,
5667 "%d (%d.%d Mhz),",
5668 period, 250 / period,
5669 ASC_TENTHS(250,
5670 period));
5671 ASC_PRT_NEXT();
5672 }
5673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005675 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5676 lramword & 0x1F);
5677 ASC_PRT_NEXT();
5678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005680 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5681 len = asc_prt_line(cp, leftlen, "*\n");
5682 renegotiate = 1;
5683 } else {
5684 len = asc_prt_line(cp, leftlen, "\n");
5685 }
5686 ASC_PRT_NEXT();
5687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005689 if (renegotiate) {
5690 len = asc_prt_line(cp, leftlen,
5691 " * = Re-negotiation pending before next command.\n");
5692 ASC_PRT_NEXT();
5693 }
5694
5695 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696}
5697
5698/*
5699 * asc_proc_copy()
5700 *
5701 * Copy proc information to a read buffer taking into account the current
5702 * read offset in the file and the remaining space in the read buffer.
5703 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005704static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005706 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005707{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005708 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005710 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
5711 (unsigned)offset, (unsigned)advoffset, cplen);
5712 if (offset <= advoffset) {
5713 /* Read offset below current offset, copy everything. */
5714 cnt = min(cplen, leftlen);
5715 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5716 (ulong)curbuf, (ulong)cp, cnt);
5717 memcpy(curbuf, cp, cnt);
5718 } else if (offset < advoffset + cplen) {
5719 /* Read offset within current range, partial copy. */
5720 cnt = (advoffset + cplen) - offset;
5721 cp = (cp + cplen) - cnt;
5722 cnt = min(cnt, leftlen);
5723 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5724 (ulong)curbuf, (ulong)cp, cnt);
5725 memcpy(curbuf, cp, cnt);
5726 }
5727 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005728}
5729
5730/*
5731 * asc_prt_line()
5732 *
5733 * If 'cp' is NULL print to the console, otherwise print to a buffer.
5734 *
5735 * Return 0 if printing to the console, otherwise return the number of
5736 * bytes written to the buffer.
5737 *
5738 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
5739 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
5740 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005741static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005743 va_list args;
5744 int ret;
5745 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005746
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005747 va_start(args, fmt);
5748 ret = vsprintf(s, fmt, args);
5749 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
5750 if (buf == NULL) {
5751 (void)printk(s);
5752 ret = 0;
5753 } else {
5754 ret = min(buflen, ret);
5755 memcpy(buf, s, ret);
5756 }
5757 va_end(args);
5758 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759}
5760#endif /* CONFIG_PROC_FS */
5761
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762/*
5763 * --- Functions Required by the Asc Library
5764 */
5765
5766/*
5767 * Delay for 'n' milliseconds. Don't use the 'jiffies'
5768 * global variable which is incremented once every 5 ms
5769 * from a timer interrupt, because this function may be
5770 * called when interrupts are disabled.
5771 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005772static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005773{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005774 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
5775 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005776}
5777
5778/*
5779 * Currently and inline noop but leave as a placeholder.
5780 * Leave DvcEnterCritical() as a noop placeholder.
5781 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005782static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005784 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785}
5786
5787/*
5788 * Critical sections are all protected by the board spinlock.
5789 * Leave DvcLeaveCritical() as a noop placeholder.
5790 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005791static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005793 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794}
5795
5796/*
5797 * void
5798 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5799 *
5800 * Calling/Exit State:
5801 * none
5802 *
5803 * Description:
5804 * Output an ASC_SCSI_Q structure to the chip
5805 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005806static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5808{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005809 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005811 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
5812 AscSetChipLramAddr(iop_base, s_addr);
5813 for (i = 0; i < 2 * words; i += 2) {
5814 if (i == 4 || i == 20) {
5815 continue;
5816 }
5817 outpw(iop_base + IOP_RAM_DATA,
5818 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
5819 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820}
5821
5822/*
5823 * void
5824 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5825 *
5826 * Calling/Exit State:
5827 * none
5828 *
5829 * Description:
5830 * Input an ASC_QDONE_INFO structure from the chip
5831 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005832static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005833DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5834{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005835 int i;
5836 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005838 AscSetChipLramAddr(iop_base, s_addr);
5839 for (i = 0; i < 2 * words; i += 2) {
5840 if (i == 10) {
5841 continue;
5842 }
5843 word = inpw(iop_base + IOP_RAM_DATA);
5844 inbuf[i] = word & 0xff;
5845 inbuf[i + 1] = (word >> 8) & 0xff;
5846 }
5847 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848}
5849
5850/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005851 * Return the BIOS address of the adapter at the specified
5852 * I/O port and with the specified bus type.
5853 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005854static unsigned short __devinit
5855AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005857 unsigned short cfg_lsw;
5858 unsigned short bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005860 /*
5861 * The PCI BIOS is re-located by the motherboard BIOS. Because
5862 * of this the driver can not determine where a PCI BIOS is
5863 * loaded and executes.
5864 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005865 if (bus_type & ASC_IS_PCI)
5866 return 0;
5867
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005869 if ((bus_type & ASC_IS_EISA) != 0) {
5870 cfg_lsw = AscGetEisaChipCfg(iop_base);
5871 cfg_lsw &= 0x000F;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005872 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
5873 return bios_addr;
5874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875#endif /* CONFIG_ISA */
5876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005877 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005879 /*
5880 * ISA PnP uses the top bit as the 32K BIOS flag
5881 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005882 if (bus_type == ASC_IS_ISAPNP)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005883 cfg_lsw &= 0x7FFF;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005884 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
5885 return bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005886}
5887
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888/*
5889 * --- Functions Required by the Adv Library
5890 */
5891
5892/*
5893 * DvcGetPhyAddr()
5894 *
5895 * Return the physical address of 'vaddr' and set '*lenp' to the
5896 * number of physically contiguous bytes that follow 'vaddr'.
5897 * 'flag' indicates the type of structure whose physical address
5898 * is being translated.
5899 *
5900 * Note: Because Linux currently doesn't page the kernel and all
5901 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
5902 */
5903ADV_PADDR
5904DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005905 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005907 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005909 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005911 ASC_DBG4(4,
5912 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
5913 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
5914 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005916 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005917}
5918
5919/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920 * --- Tracing and Debugging Functions
5921 */
5922
5923#ifdef ADVANSYS_STATS
5924#ifdef CONFIG_PROC_FS
5925/*
5926 * asc_prt_board_stats()
5927 *
5928 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5929 * cf. asc_prt_line().
5930 *
5931 * Return the number of characters copied into 'cp'. No more than
5932 * 'cplen' characters will be copied to 'cp'.
5933 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005934static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005936 int leftlen;
5937 int totlen;
5938 int len;
5939 struct asc_stats *s;
5940 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005942 leftlen = cplen;
5943 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005945 boardp = ASC_BOARDP(shost);
5946 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005948 len = asc_prt_line(cp, leftlen,
5949 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
5950 shost->host_no);
5951 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005953 len = asc_prt_line(cp, leftlen,
5954 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
5955 s->queuecommand, s->reset, s->biosparam,
5956 s->interrupt);
5957 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005959 len = asc_prt_line(cp, leftlen,
5960 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
5961 s->callback, s->done, s->build_error,
5962 s->adv_build_noreq, s->adv_build_nosg);
5963 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005965 len = asc_prt_line(cp, leftlen,
5966 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
5967 s->exe_noerror, s->exe_busy, s->exe_error,
5968 s->exe_unknown);
5969 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005971 /*
5972 * Display data transfer statistics.
5973 */
5974 if (s->cont_cnt > 0) {
5975 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
5976 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005978 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
5979 s->cont_xfer / 2,
5980 ASC_TENTHS(s->cont_xfer, 2));
5981 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005983 /* Contiguous transfer average size */
5984 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
5985 (s->cont_xfer / 2) / s->cont_cnt,
5986 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
5987 ASC_PRT_NEXT();
5988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005990 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005992 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
5993 s->sg_cnt, s->sg_elem);
5994 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005996 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
5997 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
5998 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006000 /* Scatter gather transfer statistics */
6001 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
6002 s->sg_elem / s->sg_cnt,
6003 ASC_TENTHS(s->sg_elem, s->sg_cnt));
6004 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006006 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
6007 (s->sg_xfer / 2) / s->sg_elem,
6008 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
6009 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006011 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
6012 (s->sg_xfer / 2) / s->sg_cnt,
6013 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
6014 ASC_PRT_NEXT();
6015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006017 /*
6018 * Display request queuing statistics.
6019 */
6020 len = asc_prt_line(cp, leftlen,
6021 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
6022 HZ);
6023 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006025 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027#endif /* CONFIG_PROC_FS */
6028#endif /* ADVANSYS_STATS */
6029
6030#ifdef ADVANSYS_DEBUG
6031/*
6032 * asc_prt_scsi_host()
6033 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006034static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006036 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006038 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006040 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
6041 printk(" host_busy %u, host_no %d, last_reset %d,\n",
6042 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04006044 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
6045 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006047 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
6048 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006050 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
6051 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006053 if (ASC_NARROW_BOARD(boardp)) {
6054 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
6055 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
6056 } else {
6057 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
6058 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
6059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060}
6061
6062/*
6063 * asc_prt_scsi_cmnd()
6064 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006065static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006067 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006069 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
6070 (ulong)s->device->host, (ulong)s->device, s->device->id,
6071 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006073 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006075 printk("sc_data_direction %u, resid %d\n",
6076 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006078 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006080 printk(" serial_number 0x%x, retries %d, allowed %d\n",
6081 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006083 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006085 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
6086 s->scsi_done, s->done, s->host_scribble, s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006088 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089}
6090
6091/*
6092 * asc_prt_asc_dvc_var()
6093 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006094static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006096 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006098 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
6099 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100
Matthew Wilcox895d6b42007-07-26 11:57:06 -04006101 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
6102 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006104 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
6105 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
6106 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
6107 (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006109 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
6110 "%u,\n", (unsigned)h->queue_full_or_busy,
6111 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006113 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
6114 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
6115 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
6116 (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006118 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
6119 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
6120 (unsigned)h->init_state, (unsigned)h->no_scam,
6121 (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006123 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124}
6125
6126/*
6127 * asc_prt_asc_dvc_cfg()
6128 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006129static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006131 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006133 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
6134 h->can_tagged_qng, h->cmd_qng_enabled);
6135 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
6136 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006138 printk
6139 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
6140 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
6141 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006143 printk
6144 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
6145 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
6146 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006148 printk(" mcode_version %d, overrun_buf 0x%lx\n",
6149 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150}
6151
6152/*
6153 * asc_prt_asc_scsi_q()
6154 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006155static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006156{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006157 ASC_SG_HEAD *sgp;
6158 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006160 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006162 printk
6163 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
6164 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
6165 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006167 printk
6168 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6169 (ulong)le32_to_cpu(q->q1.data_addr),
6170 (ulong)le32_to_cpu(q->q1.data_cnt),
6171 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006173 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
6174 (ulong)q->cdbptr, q->q2.cdb_len,
6175 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006177 if (q->sg_head) {
6178 sgp = q->sg_head;
6179 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
6180 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
6181 sgp->queue_cnt);
6182 for (i = 0; i < sgp->entry_cnt; i++) {
6183 printk(" [%u]: addr 0x%lx, bytes %lu\n",
6184 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
6185 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
6186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189}
6190
6191/*
6192 * asc_prt_asc_qdone_info()
6193 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006194static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006196 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
6197 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
6198 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
6199 q->d2.tag_code);
6200 printk
6201 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
6202 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203}
6204
6205/*
6206 * asc_prt_adv_dvc_var()
6207 *
6208 * Display an ADV_DVC_VAR structure.
6209 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006210static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006211{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006212 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006214 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
6215 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006217 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
6218 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
6219 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006221 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
6222 (unsigned)h->start_motor,
6223 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006225 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
6226 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
6227 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006228
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006229 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
6230 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006231
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006232 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
6233 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006235 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
6236 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237}
6238
6239/*
6240 * asc_prt_adv_dvc_cfg()
6241 *
6242 * Display an ADV_DVC_CFG structure.
6243 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006244static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006246 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006248 printk(" disc_enable 0x%x, termination 0x%x\n",
6249 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006251 printk(" chip_version 0x%x, mcode_date 0x%x\n",
6252 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006254 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
6255 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006256
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06006257 printk(" control_flag 0x%x\n", h->control_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258}
6259
6260/*
6261 * asc_prt_adv_scsi_req_q()
6262 *
6263 * Display an ADV_SCSI_REQ_Q structure.
6264 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006265static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006267 int sg_blk_cnt;
6268 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006270 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006272 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
6273 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006275 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
6276 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006278 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6279 (ulong)le32_to_cpu(q->data_cnt),
6280 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006282 printk
6283 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
6284 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006286 printk(" sg_working_ix 0x%x, target_cmd %u\n",
6287 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006289 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
6290 (ulong)le32_to_cpu(q->scsiq_rptr),
6291 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006293 /* Display the request's ADV_SG_BLOCK structures. */
6294 if (q->sg_list_ptr != NULL) {
6295 sg_blk_cnt = 0;
6296 while (1) {
6297 /*
6298 * 'sg_ptr' is a physical address. Convert it to a virtual
6299 * address by indexing 'sg_blk_cnt' into the virtual address
6300 * array 'sg_list_ptr'.
6301 *
6302 * XXX - Assumes all SG physical blocks are virtually contiguous.
6303 */
6304 sg_ptr =
6305 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
6306 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
6307 if (sg_ptr->sg_ptr == 0) {
6308 break;
6309 }
6310 sg_blk_cnt++;
6311 }
6312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313}
6314
6315/*
6316 * asc_prt_adv_sgblock()
6317 *
6318 * Display an ADV_SG_BLOCK structure.
6319 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006321{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006322 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006323
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006324 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
6325 (ulong)b, sgblockno);
6326 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
6327 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
6328 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
6329 if (b->sg_ptr != 0) {
6330 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
6331 }
6332 for (i = 0; i < b->sg_cnt; i++) {
6333 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
6334 i, (ulong)b->sg_list[i].sg_addr,
6335 (ulong)b->sg_list[i].sg_count);
6336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337}
6338
6339/*
6340 * asc_prt_hex()
6341 *
6342 * Print hexadecimal output in 4 byte groupings 32 bytes
6343 * or 8 double-words per line.
6344 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006345static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006347 int i;
6348 int j;
6349 int k;
6350 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006351
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006352 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006353
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006354 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006356 /* Display a maximum of 8 double-words per line. */
6357 if ((k = (l - i) / 4) >= 8) {
6358 k = 8;
6359 m = 0;
6360 } else {
6361 m = (l - i) % 4;
6362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006364 for (j = 0; j < k; j++) {
6365 printk(" %2.2X%2.2X%2.2X%2.2X",
6366 (unsigned)s[i + (j * 4)],
6367 (unsigned)s[i + (j * 4) + 1],
6368 (unsigned)s[i + (j * 4) + 2],
6369 (unsigned)s[i + (j * 4) + 3]);
6370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006371
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006372 switch (m) {
6373 case 0:
6374 default:
6375 break;
6376 case 1:
6377 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
6378 break;
6379 case 2:
6380 printk(" %2.2X%2.2X",
6381 (unsigned)s[i + (j * 4)],
6382 (unsigned)s[i + (j * 4) + 1]);
6383 break;
6384 case 3:
6385 printk(" %2.2X%2.2X%2.2X",
6386 (unsigned)s[i + (j * 4) + 1],
6387 (unsigned)s[i + (j * 4) + 2],
6388 (unsigned)s[i + (j * 4) + 3]);
6389 break;
6390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006392 printk("\n");
6393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006394}
6395#endif /* ADVANSYS_DEBUG */
6396
6397/*
6398 * --- Asc Library Functions
6399 */
6400
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006401static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006402{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006403 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006405 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6406 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
6407 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006408}
6409
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006410static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006411{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006412 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006414 if (AscGetChipScsiID(iop_base) == new_host_id) {
6415 return (new_host_id);
6416 }
6417 cfg_lsw = AscGetChipCfgLsw(iop_base);
6418 cfg_lsw &= 0xF8FF;
6419 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
6420 AscSetChipCfgLsw(iop_base, cfg_lsw);
6421 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006422}
6423
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006424static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006425{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006426 unsigned char sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006428 AscSetBank(iop_base, 1);
6429 sc = inp(iop_base + IOP_REG_SC);
6430 AscSetBank(iop_base, 0);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006431 return sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432}
6433
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006434static unsigned char __devinit
6435AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006437 if (bus_type & ASC_IS_EISA) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006438 PortAddr eisa_iop;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006439 unsigned char revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006440 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6441 (PortAddr) ASC_EISA_REV_IOP_MASK;
6442 revision = inp(eisa_iop);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006443 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006444 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006445 return AscGetChipVerNo(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006446}
6447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006448static ASC_DCNT
6449AscLoadMicroCode(PortAddr iop_base,
6450 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006452 ASC_DCNT chksum;
6453 ushort mcode_word_size;
6454 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006455
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006456 /* Write the microcode buffer starting at LRAM address 0. */
6457 mcode_word_size = (ushort)(mcode_size >> 1);
6458 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
6459 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006461 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
6462 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
6463 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
6464 (ushort)ASC_CODE_SEC_BEG,
6465 (ushort)((mcode_size -
6466 s_addr - (ushort)
6467 ASC_CODE_SEC_BEG) /
6468 2));
6469 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
6470 (ulong)mcode_chksum);
6471 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
6472 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
6473 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006474}
6475
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006476static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006478 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006479
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006480 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
6481 iop_base, AscGetChipSignatureByte(iop_base));
6482 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
6483 ASC_DBG2(1,
6484 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
6485 iop_base, AscGetChipSignatureWord(iop_base));
6486 sig_word = AscGetChipSignatureWord(iop_base);
6487 if ((sig_word == (ushort)ASC_1000_ID0W) ||
6488 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
6489 return (1);
6490 }
6491 }
6492 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006493}
6494
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006495static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006496{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006497 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
6498 AscSetChipStatus(iop_base, 0);
6499 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006500}
6501
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006502static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006503{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006504 ushort cfg_lsw;
6505 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006507 if ((bus_type & ASC_IS_EISA) != 0) {
6508 cfg_lsw = AscGetEisaChipCfg(iop_base);
6509 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
6510 if ((chip_irq == 13) || (chip_irq > 15)) {
6511 return (0);
6512 }
6513 return (chip_irq);
6514 }
6515 if ((bus_type & ASC_IS_VL) != 0) {
6516 cfg_lsw = AscGetChipCfgLsw(iop_base);
6517 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
6518 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
6519 return (0);
6520 }
6521 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
6522 }
6523 cfg_lsw = AscGetChipCfgLsw(iop_base);
6524 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
6525 if (chip_irq == 3)
6526 chip_irq += (uchar)2;
6527 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528}
6529
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006530static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006531AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006532{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006533 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006535 if ((bus_type & ASC_IS_VL) != 0) {
6536 if (irq_no != 0) {
6537 if ((irq_no < ASC_MIN_IRQ_NO)
6538 || (irq_no > ASC_MAX_IRQ_NO)) {
6539 irq_no = 0;
6540 } else {
6541 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
6542 }
6543 }
6544 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
6545 cfg_lsw |= (ushort)0x0010;
6546 AscSetChipCfgLsw(iop_base, cfg_lsw);
6547 AscToggleIRQAct(iop_base);
6548 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
6549 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
6550 AscSetChipCfgLsw(iop_base, cfg_lsw);
6551 AscToggleIRQAct(iop_base);
6552 return (AscGetChipIRQ(iop_base, bus_type));
6553 }
6554 if ((bus_type & (ASC_IS_ISA)) != 0) {
6555 if (irq_no == 15)
6556 irq_no -= (uchar)2;
6557 irq_no -= (uchar)ASC_MIN_IRQ_NO;
6558 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
6559 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
6560 AscSetChipCfgLsw(iop_base, cfg_lsw);
6561 return (AscGetChipIRQ(iop_base, bus_type));
6562 }
6563 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006564}
6565
6566#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006567static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006568{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006569 if (dma_channel < 4) {
6570 outp(0x000B, (ushort)(0xC0 | dma_channel));
6571 outp(0x000A, dma_channel);
6572 } else if (dma_channel < 8) {
6573 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
6574 outp(0x00D4, (ushort)(dma_channel - 4));
6575 }
6576 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577}
6578#endif /* CONFIG_ISA */
6579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006580static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006581{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006582 EXT_MSG ext_msg;
6583 EXT_MSG out_msg;
6584 ushort halt_q_addr;
6585 int sdtr_accept;
6586 ushort int_halt_code;
6587 ASC_SCSI_BIT_ID_TYPE scsi_busy;
6588 ASC_SCSI_BIT_ID_TYPE target_id;
6589 PortAddr iop_base;
6590 uchar tag_code;
6591 uchar q_status;
6592 uchar halt_qp;
6593 uchar sdtr_data;
6594 uchar target_ix;
6595 uchar q_cntl, tid_no;
6596 uchar cur_dvc_qng;
6597 uchar asyn_sdtr;
6598 uchar scsi_status;
6599 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006600
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006601 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
6602 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006603
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006604 iop_base = asc_dvc->iop_base;
6605 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006607 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
6608 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
6609 target_ix = AscReadLramByte(iop_base,
6610 (ushort)(halt_q_addr +
6611 (ushort)ASC_SCSIQ_B_TARGET_IX));
6612 q_cntl =
6613 AscReadLramByte(iop_base,
6614 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
6615 tid_no = ASC_TIX_TO_TID(target_ix);
6616 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
6617 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6618 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
6619 } else {
6620 asyn_sdtr = 0;
6621 }
6622 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
6623 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6624 AscSetChipSDTR(iop_base, 0, tid_no);
6625 boardp->sdtr_data[tid_no] = 0;
6626 }
6627 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6628 return (0);
6629 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
6630 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6631 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6632 boardp->sdtr_data[tid_no] = asyn_sdtr;
6633 }
6634 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6635 return (0);
6636 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006637
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006638 AscMemWordCopyPtrFromLram(iop_base,
6639 ASCV_MSGIN_BEG,
6640 (uchar *)&ext_msg,
6641 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006642
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006643 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6644 ext_msg.msg_req == EXTENDED_SDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006645 ext_msg.msg_len == MS_SDTR_LEN) {
6646 sdtr_accept = TRUE;
6647 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006648
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006649 sdtr_accept = FALSE;
6650 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
6651 }
6652 if ((ext_msg.xfer_period <
6653 asc_dvc->sdtr_period_tbl[asc_dvc->
6654 host_init_sdtr_index])
6655 || (ext_msg.xfer_period >
6656 asc_dvc->sdtr_period_tbl[asc_dvc->
6657 max_sdtr_index])) {
6658 sdtr_accept = FALSE;
6659 ext_msg.xfer_period =
6660 asc_dvc->sdtr_period_tbl[asc_dvc->
6661 host_init_sdtr_index];
6662 }
6663 if (sdtr_accept) {
6664 sdtr_data =
6665 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
6666 ext_msg.req_ack_offset);
6667 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006669 q_cntl |= QC_MSG_OUT;
6670 asc_dvc->init_sdtr &= ~target_id;
6671 asc_dvc->sdtr_done &= ~target_id;
6672 AscSetChipSDTR(iop_base, asyn_sdtr,
6673 tid_no);
6674 boardp->sdtr_data[tid_no] = asyn_sdtr;
6675 }
6676 }
6677 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006679 q_cntl &= ~QC_MSG_OUT;
6680 asc_dvc->init_sdtr &= ~target_id;
6681 asc_dvc->sdtr_done &= ~target_id;
6682 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6683 } else {
6684 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006686 q_cntl &= ~QC_MSG_OUT;
6687 asc_dvc->sdtr_done |= target_id;
6688 asc_dvc->init_sdtr |= target_id;
6689 asc_dvc->pci_fix_asyn_xfer &=
6690 ~target_id;
6691 sdtr_data =
6692 AscCalSDTRData(asc_dvc,
6693 ext_msg.xfer_period,
6694 ext_msg.
6695 req_ack_offset);
6696 AscSetChipSDTR(iop_base, sdtr_data,
6697 tid_no);
6698 boardp->sdtr_data[tid_no] = sdtr_data;
6699 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006700
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006701 q_cntl |= QC_MSG_OUT;
6702 AscMsgOutSDTR(asc_dvc,
6703 ext_msg.xfer_period,
6704 ext_msg.req_ack_offset);
6705 asc_dvc->pci_fix_asyn_xfer &=
6706 ~target_id;
6707 sdtr_data =
6708 AscCalSDTRData(asc_dvc,
6709 ext_msg.xfer_period,
6710 ext_msg.
6711 req_ack_offset);
6712 AscSetChipSDTR(iop_base, sdtr_data,
6713 tid_no);
6714 boardp->sdtr_data[tid_no] = sdtr_data;
6715 asc_dvc->sdtr_done |= target_id;
6716 asc_dvc->init_sdtr |= target_id;
6717 }
6718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006720 AscWriteLramByte(iop_base,
6721 (ushort)(halt_q_addr +
6722 (ushort)ASC_SCSIQ_B_CNTL),
6723 q_cntl);
6724 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6725 return (0);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006726 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6727 ext_msg.msg_req == EXTENDED_WDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006728 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006729
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006730 ext_msg.wdtr_width = 0;
6731 AscMemWordCopyPtrToLram(iop_base,
6732 ASCV_MSGOUT_BEG,
6733 (uchar *)&ext_msg,
6734 sizeof(EXT_MSG) >> 1);
6735 q_cntl |= QC_MSG_OUT;
6736 AscWriteLramByte(iop_base,
6737 (ushort)(halt_q_addr +
6738 (ushort)ASC_SCSIQ_B_CNTL),
6739 q_cntl);
6740 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6741 return (0);
6742 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006744 ext_msg.msg_type = MESSAGE_REJECT;
6745 AscMemWordCopyPtrToLram(iop_base,
6746 ASCV_MSGOUT_BEG,
6747 (uchar *)&ext_msg,
6748 sizeof(EXT_MSG) >> 1);
6749 q_cntl |= QC_MSG_OUT;
6750 AscWriteLramByte(iop_base,
6751 (ushort)(halt_q_addr +
6752 (ushort)ASC_SCSIQ_B_CNTL),
6753 q_cntl);
6754 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6755 return (0);
6756 }
6757 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006759 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006761 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006762
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006763 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006764
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006765 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
6766 q_cntl |= QC_MSG_OUT;
6767 AscMsgOutSDTR(asc_dvc,
6768 asc_dvc->
6769 sdtr_period_tbl[(sdtr_data >> 4) &
6770 (uchar)(asc_dvc->
6771 max_sdtr_index -
6772 1)],
6773 (uchar)(sdtr_data & (uchar)
6774 ASC_SYN_MAX_OFFSET));
6775 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006776
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006777 AscWriteLramByte(iop_base,
6778 (ushort)(halt_q_addr +
6779 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006781 tag_code = AscReadLramByte(iop_base,
6782 (ushort)(halt_q_addr + (ushort)
6783 ASC_SCSIQ_B_TAG_CODE));
6784 tag_code &= 0xDC;
6785 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
6786 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
6787 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006788
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006789 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
6790 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006792 }
6793 AscWriteLramByte(iop_base,
6794 (ushort)(halt_q_addr +
6795 (ushort)ASC_SCSIQ_B_TAG_CODE),
6796 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006797
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006798 q_status = AscReadLramByte(iop_base,
6799 (ushort)(halt_q_addr + (ushort)
6800 ASC_SCSIQ_B_STATUS));
6801 q_status |= (QS_READY | QS_BUSY);
6802 AscWriteLramByte(iop_base,
6803 (ushort)(halt_q_addr +
6804 (ushort)ASC_SCSIQ_B_STATUS),
6805 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006807 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
6808 scsi_busy &= ~target_id;
6809 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006810
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006811 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6812 return (0);
6813 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006815 AscMemWordCopyPtrFromLram(iop_base,
6816 ASCV_MSGOUT_BEG,
6817 (uchar *)&out_msg,
6818 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006820 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006821 (out_msg.msg_len == MS_SDTR_LEN) &&
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006822 (out_msg.msg_req == EXTENDED_SDTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006823
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006824 asc_dvc->init_sdtr &= ~target_id;
6825 asc_dvc->sdtr_done &= ~target_id;
6826 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6827 boardp->sdtr_data[tid_no] = asyn_sdtr;
6828 }
6829 q_cntl &= ~QC_MSG_OUT;
6830 AscWriteLramByte(iop_base,
6831 (ushort)(halt_q_addr +
6832 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
6833 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6834 return (0);
6835 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006837 scsi_status = AscReadLramByte(iop_base,
6838 (ushort)((ushort)halt_q_addr +
6839 (ushort)
6840 ASC_SCSIQ_SCSI_STATUS));
6841 cur_dvc_qng =
6842 AscReadLramByte(iop_base,
6843 (ushort)((ushort)ASC_QADR_BEG +
6844 (ushort)target_ix));
6845 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006846
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006847 scsi_busy = AscReadLramByte(iop_base,
6848 (ushort)ASCV_SCSIBUSY_B);
6849 scsi_busy |= target_id;
6850 AscWriteLramByte(iop_base,
6851 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
6852 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006853
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006854 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
6855 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
6856 cur_dvc_qng -= 1;
6857 asc_dvc->max_dvc_qng[tid_no] =
6858 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006860 AscWriteLramByte(iop_base,
6861 (ushort)((ushort)
6862 ASCV_MAX_DVC_QNG_BEG
6863 + (ushort)
6864 tid_no),
6865 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006866
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006867 /*
6868 * Set the device queue depth to the number of
6869 * active requests when the QUEUE FULL condition
6870 * was encountered.
6871 */
6872 boardp->queue_full |= target_id;
6873 boardp->queue_full_cnt[tid_no] =
6874 cur_dvc_qng;
6875 }
6876 }
6877 }
6878 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6879 return (0);
6880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006881#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006882 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
6883 uchar q_no;
6884 ushort q_addr;
6885 uchar sg_wk_q_no;
6886 uchar first_sg_wk_q_no;
6887 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
6888 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
6889 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
6890 ushort sg_list_dwords;
6891 ushort sg_entry_cnt;
6892 uchar next_qp;
6893 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006894
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006895 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
6896 if (q_no == ASC_QLINK_END) {
6897 return (0);
6898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006899
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006900 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006901
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006902 /*
6903 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
6904 * structure pointer using a macro provided by the driver.
6905 * The ASC_SCSI_REQ pointer provides a pointer to the
6906 * host ASC_SG_HEAD structure.
6907 */
6908 /* Read request's SRB pointer. */
6909 scsiq = (ASC_SCSI_Q *)
6910 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
6911 (ushort)
6912 (q_addr +
6913 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006915 /*
6916 * Get request's first and working SG queue.
6917 */
6918 sg_wk_q_no = AscReadLramByte(iop_base,
6919 (ushort)(q_addr +
6920 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006922 first_sg_wk_q_no = AscReadLramByte(iop_base,
6923 (ushort)(q_addr +
6924 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006926 /*
6927 * Reset request's working SG queue back to the
6928 * first SG queue.
6929 */
6930 AscWriteLramByte(iop_base,
6931 (ushort)(q_addr +
6932 (ushort)ASC_SCSIQ_B_SG_WK_QP),
6933 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006935 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006936
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006937 /*
6938 * Set sg_entry_cnt to the number of SG elements
6939 * that will be completed on this interrupt.
6940 *
6941 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
6942 * SG elements. The data_cnt and data_addr fields which
6943 * add 1 to the SG element capacity are not used when
6944 * restarting SG handling after a halt.
6945 */
6946 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
6947 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006949 /*
6950 * Keep track of remaining number of SG elements that will
6951 * need to be handled on the next interrupt.
6952 */
6953 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
6954 } else {
6955 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
6956 scsiq->remain_sg_entry_cnt = 0;
6957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006959 /*
6960 * Copy SG elements into the list of allocated SG queues.
6961 *
6962 * Last index completed is saved in scsiq->next_sg_index.
6963 */
6964 next_qp = first_sg_wk_q_no;
6965 q_addr = ASC_QNO_TO_QADDR(next_qp);
6966 scsi_sg_q.sg_head_qp = q_no;
6967 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
6968 for (i = 0; i < sg_head->queue_cnt; i++) {
6969 scsi_sg_q.seq_no = i + 1;
6970 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
6971 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
6972 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
6973 /*
6974 * After very first SG queue RISC FW uses next
6975 * SG queue first element then checks sg_list_cnt
6976 * against zero and then decrements, so set
6977 * sg_list_cnt 1 less than number of SG elements
6978 * in each SG queue.
6979 */
6980 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
6981 scsi_sg_q.sg_cur_list_cnt =
6982 ASC_SG_LIST_PER_Q - 1;
6983 } else {
6984 /*
6985 * This is the last SG queue in the list of
6986 * allocated SG queues. If there are more
6987 * SG elements than will fit in the allocated
6988 * queues, then set the QCSG_SG_XFER_MORE flag.
6989 */
6990 if (scsiq->remain_sg_entry_cnt != 0) {
6991 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
6992 } else {
6993 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
6994 }
6995 /* equals sg_entry_cnt * 2 */
6996 sg_list_dwords = sg_entry_cnt << 1;
6997 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
6998 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
6999 sg_entry_cnt = 0;
7000 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007002 scsi_sg_q.q_no = next_qp;
7003 AscMemWordCopyPtrToLram(iop_base,
7004 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
7005 (uchar *)&scsi_sg_q,
7006 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007008 AscMemDWordCopyPtrToLram(iop_base,
7009 q_addr + ASC_SGQ_LIST_BEG,
7010 (uchar *)&sg_head->
7011 sg_list[scsiq->next_sg_index],
7012 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007014 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007015
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007016 /*
7017 * If the just completed SG queue contained the
7018 * last SG element, then no more SG queues need
7019 * to be written.
7020 */
7021 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
7022 break;
7023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007024
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007025 next_qp = AscReadLramByte(iop_base,
7026 (ushort)(q_addr +
7027 ASC_SCSIQ_B_FWD));
7028 q_addr = ASC_QNO_TO_QADDR(next_qp);
7029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007031 /*
7032 * Clear the halt condition so the RISC will be restarted
7033 * after the return.
7034 */
7035 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7036 return (0);
7037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007038#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007039 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007040}
7041
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007042static uchar
7043_AscCopyLramScsiDoneQ(PortAddr iop_base,
7044 ushort q_addr,
7045 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007047 ushort _val;
7048 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007049
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007050 DvcGetQinfo(iop_base,
7051 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
7052 (uchar *)scsiq,
7053 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007054
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007055 _val = AscReadLramWord(iop_base,
7056 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
7057 scsiq->q_status = (uchar)_val;
7058 scsiq->q_no = (uchar)(_val >> 8);
7059 _val = AscReadLramWord(iop_base,
7060 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
7061 scsiq->cntl = (uchar)_val;
7062 sg_queue_cnt = (uchar)(_val >> 8);
7063 _val = AscReadLramWord(iop_base,
7064 (ushort)(q_addr +
7065 (ushort)ASC_SCSIQ_B_SENSE_LEN));
7066 scsiq->sense_len = (uchar)_val;
7067 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007069 /*
7070 * Read high word of remain bytes from alternate location.
7071 */
7072 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
7073 (ushort)(q_addr +
7074 (ushort)
7075 ASC_SCSIQ_W_ALT_DC1)))
7076 << 16);
7077 /*
7078 * Read low word of remain bytes from original location.
7079 */
7080 scsiq->remain_bytes += AscReadLramWord(iop_base,
7081 (ushort)(q_addr + (ushort)
7082 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007083
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007084 scsiq->remain_bytes &= max_dma_count;
7085 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007086}
7087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007088static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007089{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007090 uchar next_qp;
7091 uchar n_q_used;
7092 uchar sg_list_qp;
7093 uchar sg_queue_cnt;
7094 uchar q_cnt;
7095 uchar done_q_tail;
7096 uchar tid_no;
7097 ASC_SCSI_BIT_ID_TYPE scsi_busy;
7098 ASC_SCSI_BIT_ID_TYPE target_id;
7099 PortAddr iop_base;
7100 ushort q_addr;
7101 ushort sg_q_addr;
7102 uchar cur_target_qng;
7103 ASC_QDONE_INFO scsiq_buf;
7104 ASC_QDONE_INFO *scsiq;
7105 int false_overrun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007107 iop_base = asc_dvc->iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007108 n_q_used = 1;
7109 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
7110 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
7111 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
7112 next_qp = AscReadLramByte(iop_base,
7113 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
7114 if (next_qp != ASC_QLINK_END) {
7115 AscPutVarDoneQTail(iop_base, next_qp);
7116 q_addr = ASC_QNO_TO_QADDR(next_qp);
7117 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
7118 asc_dvc->max_dma_count);
7119 AscWriteLramByte(iop_base,
7120 (ushort)(q_addr +
7121 (ushort)ASC_SCSIQ_B_STATUS),
7122 (uchar)(scsiq->
7123 q_status & (uchar)~(QS_READY |
7124 QS_ABORTED)));
7125 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
7126 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
7127 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
7128 sg_q_addr = q_addr;
7129 sg_list_qp = next_qp;
7130 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
7131 sg_list_qp = AscReadLramByte(iop_base,
7132 (ushort)(sg_q_addr
7133 + (ushort)
7134 ASC_SCSIQ_B_FWD));
7135 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
7136 if (sg_list_qp == ASC_QLINK_END) {
7137 AscSetLibErrorCode(asc_dvc,
7138 ASCQ_ERR_SG_Q_LINKS);
7139 scsiq->d3.done_stat = QD_WITH_ERROR;
7140 scsiq->d3.host_stat =
7141 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
7142 goto FATAL_ERR_QDONE;
7143 }
7144 AscWriteLramByte(iop_base,
7145 (ushort)(sg_q_addr + (ushort)
7146 ASC_SCSIQ_B_STATUS),
7147 QS_FREE);
7148 }
7149 n_q_used = sg_queue_cnt + 1;
7150 AscPutVarDoneQTail(iop_base, sg_list_qp);
7151 }
7152 if (asc_dvc->queue_full_or_busy & target_id) {
7153 cur_target_qng = AscReadLramByte(iop_base,
7154 (ushort)((ushort)
7155 ASC_QADR_BEG
7156 + (ushort)
7157 scsiq->d2.
7158 target_ix));
7159 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
7160 scsi_busy = AscReadLramByte(iop_base, (ushort)
7161 ASCV_SCSIBUSY_B);
7162 scsi_busy &= ~target_id;
7163 AscWriteLramByte(iop_base,
7164 (ushort)ASCV_SCSIBUSY_B,
7165 scsi_busy);
7166 asc_dvc->queue_full_or_busy &= ~target_id;
7167 }
7168 }
7169 if (asc_dvc->cur_total_qng >= n_q_used) {
7170 asc_dvc->cur_total_qng -= n_q_used;
7171 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
7172 asc_dvc->cur_dvc_qng[tid_no]--;
7173 }
7174 } else {
7175 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
7176 scsiq->d3.done_stat = QD_WITH_ERROR;
7177 goto FATAL_ERR_QDONE;
7178 }
7179 if ((scsiq->d2.srb_ptr == 0UL) ||
7180 ((scsiq->q_status & QS_ABORTED) != 0)) {
7181 return (0x11);
7182 } else if (scsiq->q_status == QS_DONE) {
7183 false_overrun = FALSE;
7184 if (scsiq->extra_bytes != 0) {
7185 scsiq->remain_bytes +=
7186 (ADV_DCNT)scsiq->extra_bytes;
7187 }
7188 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
7189 if (scsiq->d3.host_stat ==
7190 QHSTA_M_DATA_OVER_RUN) {
7191 if ((scsiq->
7192 cntl & (QC_DATA_IN | QC_DATA_OUT))
7193 == 0) {
7194 scsiq->d3.done_stat =
7195 QD_NO_ERROR;
7196 scsiq->d3.host_stat =
7197 QHSTA_NO_ERROR;
7198 } else if (false_overrun) {
7199 scsiq->d3.done_stat =
7200 QD_NO_ERROR;
7201 scsiq->d3.host_stat =
7202 QHSTA_NO_ERROR;
7203 }
7204 } else if (scsiq->d3.host_stat ==
7205 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
7206 AscStopChip(iop_base);
7207 AscSetChipControl(iop_base,
7208 (uchar)(CC_SCSI_RESET
7209 | CC_HALT));
7210 DvcDelayNanoSecond(asc_dvc, 60000);
7211 AscSetChipControl(iop_base, CC_HALT);
7212 AscSetChipStatus(iop_base,
7213 CIW_CLR_SCSI_RESET_INT);
7214 AscSetChipStatus(iop_base, 0);
7215 AscSetChipControl(iop_base, 0);
7216 }
7217 }
7218 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007219 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007220 } else {
7221 if ((AscReadLramByte(iop_base,
7222 (ushort)(q_addr + (ushort)
7223 ASC_SCSIQ_CDB_BEG))
7224 == START_STOP)) {
7225 asc_dvc->unit_not_ready &= ~target_id;
7226 if (scsiq->d3.done_stat != QD_NO_ERROR) {
7227 asc_dvc->start_motor &=
7228 ~target_id;
7229 }
7230 }
7231 }
7232 return (1);
7233 } else {
7234 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
7235 FATAL_ERR_QDONE:
7236 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007237 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007238 }
7239 return (0x80);
7240 }
7241 }
7242 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007243}
7244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007245static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007246{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007247 ASC_CS_TYPE chipstat;
7248 PortAddr iop_base;
7249 ushort saved_ram_addr;
7250 uchar ctrl_reg;
7251 uchar saved_ctrl_reg;
7252 int int_pending;
7253 int status;
7254 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007256 iop_base = asc_dvc->iop_base;
7257 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007259 if (AscIsIntPending(iop_base) == 0) {
7260 return int_pending;
7261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007263 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007264 return (ERR);
7265 }
7266 if (asc_dvc->in_critical_cnt != 0) {
7267 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
7268 return (ERR);
7269 }
7270 if (asc_dvc->is_in_int) {
7271 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
7272 return (ERR);
7273 }
7274 asc_dvc->is_in_int = TRUE;
7275 ctrl_reg = AscGetChipControl(iop_base);
7276 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
7277 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
7278 chipstat = AscGetChipStatus(iop_base);
7279 if (chipstat & CSW_SCSI_RESET_LATCH) {
7280 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
7281 int i = 10;
7282 int_pending = TRUE;
7283 asc_dvc->sdtr_done = 0;
7284 saved_ctrl_reg &= (uchar)(~CC_HALT);
7285 while ((AscGetChipStatus(iop_base) &
7286 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
7287 DvcSleepMilliSecond(100);
7288 }
7289 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
7290 AscSetChipControl(iop_base, CC_HALT);
7291 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
7292 AscSetChipStatus(iop_base, 0);
7293 chipstat = AscGetChipStatus(iop_base);
7294 }
7295 }
7296 saved_ram_addr = AscGetChipLramAddr(iop_base);
7297 host_flag = AscReadLramByte(iop_base,
7298 ASCV_HOST_FLAG_B) &
7299 (uchar)(~ASC_HOST_FLAG_IN_ISR);
7300 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7301 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
7302 if ((chipstat & CSW_INT_PENDING)
7303 || (int_pending)
7304 ) {
7305 AscAckInterrupt(iop_base);
7306 int_pending = TRUE;
7307 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
7308 if (AscIsrChipHalted(asc_dvc) == ERR) {
7309 goto ISR_REPORT_QDONE_FATAL_ERROR;
7310 } else {
7311 saved_ctrl_reg &= (uchar)(~CC_HALT);
7312 }
7313 } else {
7314 ISR_REPORT_QDONE_FATAL_ERROR:
7315 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
7316 while (((status =
7317 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
7318 }
7319 } else {
7320 do {
7321 if ((status =
7322 AscIsrQDone(asc_dvc)) == 1) {
7323 break;
7324 }
7325 } while (status == 0x11);
7326 }
7327 if ((status & 0x80) != 0)
7328 int_pending = ERR;
7329 }
7330 }
7331 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7332 AscSetChipLramAddr(iop_base, saved_ram_addr);
7333 AscSetChipControl(iop_base, saved_ctrl_reg);
7334 asc_dvc->is_in_int = FALSE;
7335 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007336}
7337
7338/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007339static uchar _asc_mcode_buf[] = {
7340 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007341 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
7346 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7347 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007348 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007349 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
7350 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
7351 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007352 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007353 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
7354 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
7355 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007356 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007357 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
7358 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
7359 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007360 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007361 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
7362 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
7363 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007364 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007365 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
7366 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
7367 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007368 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007369 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
7370 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
7371 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007373 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
7374 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
7375 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007376 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007377 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
7378 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
7379 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007380 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007381 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
7382 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
7383 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007384 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007385 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
7386 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
7387 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007388 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007389 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
7390 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
7391 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007392 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007393 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
7394 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
7395 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007396 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007397 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
7398 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
7399 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007400 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007401 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
7402 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
7403 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007404 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007405 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
7406 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
7407 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007408 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007409 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
7410 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
7411 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007412 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007413 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
7414 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
7415 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007416 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007417 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
7418 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
7419 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007420 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007421 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
7422 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
7423 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007424 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007425 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
7426 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
7427 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007428 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007429 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
7430 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
7431 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007432 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007433 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
7434 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
7435 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007436 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007437 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
7438 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
7439 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007440 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007441 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
7442 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
7443 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007444 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007445 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
7446 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
7447 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007448 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007449 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
7450 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
7451 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007452 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007453 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
7454 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
7455 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007456 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007457 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
7458 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
7459 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007460 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007461 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
7462 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
7463 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007464 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007465 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
7466 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
7467 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007468 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007469 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
7470 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
7471 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007472 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007473 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
7474 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
7475 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007476 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007477 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
7478 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
7479 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007480 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007481 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
7482 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
7483 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007484 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007485 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
7486 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
7487 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007488 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007489 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
7490 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
7491 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007492 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007493 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
7494 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
7495 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007496 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007497 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
7498 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
7499 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007500 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007501 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
7502 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
7503 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007504 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007505 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
7506 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
7507 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007508 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007509 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
7510 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
7511 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007512 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007513 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
7514 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
7515 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007516 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007517 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
7518 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
7519 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007520 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007521 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
7522 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
7523 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007524 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007525 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
7526 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
7527 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007528 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007529 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
7530 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
7531 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007532};
7533
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007534static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
7535static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536
7537#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007538static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
7539 INQUIRY,
7540 REQUEST_SENSE,
7541 READ_CAPACITY,
7542 READ_TOC,
7543 MODE_SELECT,
7544 MODE_SENSE,
7545 MODE_SELECT_10,
7546 MODE_SENSE_10,
7547 0xFF,
7548 0xFF,
7549 0xFF,
7550 0xFF,
7551 0xFF,
7552 0xFF,
7553 0xFF,
7554 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07007555};
7556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007557static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007558{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007559 PortAddr iop_base;
7560 ulong last_int_level;
7561 int sta;
7562 int n_q_required;
7563 int disable_syn_offset_one_fix;
7564 int i;
7565 ASC_PADDR addr;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007566 ushort sg_entry_cnt = 0;
7567 ushort sg_entry_cnt_minus_one = 0;
7568 uchar target_ix;
7569 uchar tid_no;
7570 uchar sdtr_data;
7571 uchar extra_bytes;
7572 uchar scsi_cmd;
7573 uchar disable_cmd;
7574 ASC_SG_HEAD *sg_head;
7575 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007577 iop_base = asc_dvc->iop_base;
7578 sg_head = scsiq->sg_head;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007579 if (asc_dvc->err_code != 0)
7580 return (ERR);
7581 if (scsiq == (ASC_SCSI_Q *)0L) {
7582 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
7583 return (ERR);
7584 }
7585 scsiq->q1.q_no = 0;
7586 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
7587 scsiq->q1.extra_bytes = 0;
7588 }
7589 sta = 0;
7590 target_ix = scsiq->q2.target_ix;
7591 tid_no = ASC_TIX_TO_TID(target_ix);
7592 n_q_required = 1;
7593 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
7594 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
7595 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
7596 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7597 AscMsgOutSDTR(asc_dvc,
7598 asc_dvc->
7599 sdtr_period_tbl[(sdtr_data >> 4) &
7600 (uchar)(asc_dvc->
7601 max_sdtr_index -
7602 1)],
7603 (uchar)(sdtr_data & (uchar)
7604 ASC_SYN_MAX_OFFSET));
7605 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
7606 }
7607 }
7608 last_int_level = DvcEnterCritical();
7609 if (asc_dvc->in_critical_cnt != 0) {
7610 DvcLeaveCritical(last_int_level);
7611 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
7612 return (ERR);
7613 }
7614 asc_dvc->in_critical_cnt++;
7615 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7616 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
7617 asc_dvc->in_critical_cnt--;
7618 DvcLeaveCritical(last_int_level);
7619 return (ERR);
7620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007621#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007622 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7623 asc_dvc->in_critical_cnt--;
7624 DvcLeaveCritical(last_int_level);
7625 return (ERR);
7626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007627#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007628 if (sg_entry_cnt == 1) {
7629 scsiq->q1.data_addr =
7630 (ADV_PADDR)sg_head->sg_list[0].addr;
7631 scsiq->q1.data_cnt =
7632 (ADV_DCNT)sg_head->sg_list[0].bytes;
7633 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
7634 }
7635 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
7636 }
7637 scsi_cmd = scsiq->cdbptr[0];
7638 disable_syn_offset_one_fix = FALSE;
7639 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
7640 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
7641 if (scsiq->q1.cntl & QC_SG_HEAD) {
7642 data_cnt = 0;
7643 for (i = 0; i < sg_entry_cnt; i++) {
7644 data_cnt +=
7645 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
7646 bytes);
7647 }
7648 } else {
7649 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
7650 }
7651 if (data_cnt != 0UL) {
7652 if (data_cnt < 512UL) {
7653 disable_syn_offset_one_fix = TRUE;
7654 } else {
7655 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
7656 i++) {
7657 disable_cmd =
7658 _syn_offset_one_disable_cmd[i];
7659 if (disable_cmd == 0xFF) {
7660 break;
7661 }
7662 if (scsi_cmd == disable_cmd) {
7663 disable_syn_offset_one_fix =
7664 TRUE;
7665 break;
7666 }
7667 }
7668 }
7669 }
7670 }
7671 if (disable_syn_offset_one_fix) {
7672 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7673 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
7674 ASC_TAG_FLAG_DISABLE_DISCONNECT);
7675 } else {
7676 scsiq->q2.tag_code &= 0x27;
7677 }
7678 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7679 if (asc_dvc->bug_fix_cntl) {
7680 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7681 if ((scsi_cmd == READ_6) ||
7682 (scsi_cmd == READ_10)) {
7683 addr =
7684 (ADV_PADDR)le32_to_cpu(sg_head->
7685 sg_list
7686 [sg_entry_cnt_minus_one].
7687 addr) +
7688 (ADV_DCNT)le32_to_cpu(sg_head->
7689 sg_list
7690 [sg_entry_cnt_minus_one].
7691 bytes);
7692 extra_bytes =
7693 (uchar)((ushort)addr & 0x0003);
7694 if ((extra_bytes != 0)
7695 &&
7696 ((scsiq->q2.
7697 tag_code &
7698 ASC_TAG_FLAG_EXTRA_BYTES)
7699 == 0)) {
7700 scsiq->q2.tag_code |=
7701 ASC_TAG_FLAG_EXTRA_BYTES;
7702 scsiq->q1.extra_bytes =
7703 extra_bytes;
7704 data_cnt =
7705 le32_to_cpu(sg_head->
7706 sg_list
7707 [sg_entry_cnt_minus_one].
7708 bytes);
7709 data_cnt -=
7710 (ASC_DCNT) extra_bytes;
7711 sg_head->
7712 sg_list
7713 [sg_entry_cnt_minus_one].
7714 bytes =
7715 cpu_to_le32(data_cnt);
7716 }
7717 }
7718 }
7719 }
7720 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007721#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007722 /*
7723 * Set the sg_entry_cnt to the maximum possible. The rest of
7724 * the SG elements will be copied when the RISC completes the
7725 * SG elements that fit and halts.
7726 */
7727 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7728 sg_entry_cnt = ASC_MAX_SG_LIST;
7729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007730#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007731 n_q_required = AscSgListToQueue(sg_entry_cnt);
7732 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
7733 (uint) n_q_required)
7734 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7735 if ((sta =
7736 AscSendScsiQueue(asc_dvc, scsiq,
7737 n_q_required)) == 1) {
7738 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007739 DvcLeaveCritical(last_int_level);
7740 return (sta);
7741 }
7742 }
7743 } else {
7744 if (asc_dvc->bug_fix_cntl) {
7745 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7746 if ((scsi_cmd == READ_6) ||
7747 (scsi_cmd == READ_10)) {
7748 addr =
7749 le32_to_cpu(scsiq->q1.data_addr) +
7750 le32_to_cpu(scsiq->q1.data_cnt);
7751 extra_bytes =
7752 (uchar)((ushort)addr & 0x0003);
7753 if ((extra_bytes != 0)
7754 &&
7755 ((scsiq->q2.
7756 tag_code &
7757 ASC_TAG_FLAG_EXTRA_BYTES)
7758 == 0)) {
7759 data_cnt =
7760 le32_to_cpu(scsiq->q1.
7761 data_cnt);
7762 if (((ushort)data_cnt & 0x01FF)
7763 == 0) {
7764 scsiq->q2.tag_code |=
7765 ASC_TAG_FLAG_EXTRA_BYTES;
7766 data_cnt -= (ASC_DCNT)
7767 extra_bytes;
7768 scsiq->q1.data_cnt =
7769 cpu_to_le32
7770 (data_cnt);
7771 scsiq->q1.extra_bytes =
7772 extra_bytes;
7773 }
7774 }
7775 }
7776 }
7777 }
7778 n_q_required = 1;
7779 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
7780 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7781 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
7782 n_q_required)) == 1) {
7783 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007784 DvcLeaveCritical(last_int_level);
7785 return (sta);
7786 }
7787 }
7788 }
7789 asc_dvc->in_critical_cnt--;
7790 DvcLeaveCritical(last_int_level);
7791 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007792}
7793
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007794static int
7795AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007796{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007797 PortAddr iop_base;
7798 uchar free_q_head;
7799 uchar next_qp;
7800 uchar tid_no;
7801 uchar target_ix;
7802 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007803
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007804 iop_base = asc_dvc->iop_base;
7805 target_ix = scsiq->q2.target_ix;
7806 tid_no = ASC_TIX_TO_TID(target_ix);
7807 sta = 0;
7808 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
7809 if (n_q_required > 1) {
7810 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
7811 free_q_head, (uchar)
7812 (n_q_required)))
7813 != (uchar)ASC_QLINK_END) {
7814 asc_dvc->last_q_shortage = 0;
7815 scsiq->sg_head->queue_cnt = n_q_required - 1;
7816 scsiq->q1.q_no = free_q_head;
7817 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
7818 free_q_head)) == 1) {
7819 AscPutVarFreeQHead(iop_base, next_qp);
7820 asc_dvc->cur_total_qng += (uchar)(n_q_required);
7821 asc_dvc->cur_dvc_qng[tid_no]++;
7822 }
7823 return (sta);
7824 }
7825 } else if (n_q_required == 1) {
7826 if ((next_qp = AscAllocFreeQueue(iop_base,
7827 free_q_head)) !=
7828 ASC_QLINK_END) {
7829 scsiq->q1.q_no = free_q_head;
7830 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
7831 free_q_head)) == 1) {
7832 AscPutVarFreeQHead(iop_base, next_qp);
7833 asc_dvc->cur_total_qng++;
7834 asc_dvc->cur_dvc_qng[tid_no]++;
7835 }
7836 return (sta);
7837 }
7838 }
7839 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007840}
7841
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007842static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007843{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007844 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007845
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007846 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
7847 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
7848 n_sg_list_qs++;
7849 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007850}
7851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007852static uint
7853AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007854{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007855 uint cur_used_qs;
7856 uint cur_free_qs;
7857 ASC_SCSI_BIT_ID_TYPE target_id;
7858 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007860 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
7861 tid_no = ASC_TIX_TO_TID(target_ix);
7862 if ((asc_dvc->unit_not_ready & target_id) ||
7863 (asc_dvc->queue_full_or_busy & target_id)) {
7864 return (0);
7865 }
7866 if (n_qs == 1) {
7867 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7868 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
7869 } else {
7870 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7871 (uint) ASC_MIN_FREE_Q;
7872 }
7873 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
7874 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
7875 if (asc_dvc->cur_dvc_qng[tid_no] >=
7876 asc_dvc->max_dvc_qng[tid_no]) {
7877 return (0);
7878 }
7879 return (cur_free_qs);
7880 }
7881 if (n_qs > 1) {
7882 if ((n_qs > asc_dvc->last_q_shortage)
7883 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
7884 asc_dvc->last_q_shortage = n_qs;
7885 }
7886 }
7887 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007888}
7889
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007890static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007891{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007892 ushort q_addr;
7893 uchar tid_no;
7894 uchar sdtr_data;
7895 uchar syn_period_ix;
7896 uchar syn_offset;
7897 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007899 iop_base = asc_dvc->iop_base;
7900 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
7901 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
7902 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
7903 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7904 syn_period_ix =
7905 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
7906 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
7907 AscMsgOutSDTR(asc_dvc,
7908 asc_dvc->sdtr_period_tbl[syn_period_ix],
7909 syn_offset);
7910 scsiq->q1.cntl |= QC_MSG_OUT;
7911 }
7912 q_addr = ASC_QNO_TO_QADDR(q_no);
7913 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
7914 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7915 }
7916 scsiq->q1.status = QS_FREE;
7917 AscMemWordCopyPtrToLram(iop_base,
7918 q_addr + ASC_SCSIQ_CDB_BEG,
7919 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007920
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007921 DvcPutScsiQ(iop_base,
7922 q_addr + ASC_SCSIQ_CPY_BEG,
7923 (uchar *)&scsiq->q1.cntl,
7924 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
7925 AscWriteLramWord(iop_base,
7926 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
7927 (ushort)(((ushort)scsiq->q1.
7928 q_no << 8) | (ushort)QS_READY));
7929 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007930}
7931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007932static int
7933AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007934{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007935 int sta;
7936 int i;
7937 ASC_SG_HEAD *sg_head;
7938 ASC_SG_LIST_Q scsi_sg_q;
7939 ASC_DCNT saved_data_addr;
7940 ASC_DCNT saved_data_cnt;
7941 PortAddr iop_base;
7942 ushort sg_list_dwords;
7943 ushort sg_index;
7944 ushort sg_entry_cnt;
7945 ushort q_addr;
7946 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007948 iop_base = asc_dvc->iop_base;
7949 sg_head = scsiq->sg_head;
7950 saved_data_addr = scsiq->q1.data_addr;
7951 saved_data_cnt = scsiq->q1.data_cnt;
7952 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
7953 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007954#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007955 /*
7956 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
7957 * then not all SG elements will fit in the allocated queues.
7958 * The rest of the SG elements will be copied when the RISC
7959 * completes the SG elements that fit and halts.
7960 */
7961 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
7962 /*
7963 * Set sg_entry_cnt to be the number of SG elements that
7964 * will fit in the allocated SG queues. It is minus 1, because
7965 * the first SG element is handled above. ASC_MAX_SG_LIST is
7966 * already inflated by 1 to account for this. For example it
7967 * may be 50 which is 1 + 7 queues * 7 SG elements.
7968 */
7969 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007970
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007971 /*
7972 * Keep track of remaining number of SG elements that will
7973 * need to be handled from a_isr.c.
7974 */
7975 scsiq->remain_sg_entry_cnt =
7976 sg_head->entry_cnt - ASC_MAX_SG_LIST;
7977 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007978#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007979 /*
7980 * Set sg_entry_cnt to be the number of SG elements that
7981 * will fit in the allocated SG queues. It is minus 1, because
7982 * the first SG element is handled above.
7983 */
7984 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007985#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007987#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007988 if (sg_entry_cnt != 0) {
7989 scsiq->q1.cntl |= QC_SG_HEAD;
7990 q_addr = ASC_QNO_TO_QADDR(q_no);
7991 sg_index = 1;
7992 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
7993 scsi_sg_q.sg_head_qp = q_no;
7994 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
7995 for (i = 0; i < sg_head->queue_cnt; i++) {
7996 scsi_sg_q.seq_no = i + 1;
7997 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
7998 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
7999 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8000 if (i == 0) {
8001 scsi_sg_q.sg_list_cnt =
8002 ASC_SG_LIST_PER_Q;
8003 scsi_sg_q.sg_cur_list_cnt =
8004 ASC_SG_LIST_PER_Q;
8005 } else {
8006 scsi_sg_q.sg_list_cnt =
8007 ASC_SG_LIST_PER_Q - 1;
8008 scsi_sg_q.sg_cur_list_cnt =
8009 ASC_SG_LIST_PER_Q - 1;
8010 }
8011 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008012#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008013 /*
8014 * This is the last SG queue in the list of
8015 * allocated SG queues. If there are more
8016 * SG elements than will fit in the allocated
8017 * queues, then set the QCSG_SG_XFER_MORE flag.
8018 */
8019 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
8020 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8021 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008022#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008023 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008024#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008026#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008027 sg_list_dwords = sg_entry_cnt << 1;
8028 if (i == 0) {
8029 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
8030 scsi_sg_q.sg_cur_list_cnt =
8031 sg_entry_cnt;
8032 } else {
8033 scsi_sg_q.sg_list_cnt =
8034 sg_entry_cnt - 1;
8035 scsi_sg_q.sg_cur_list_cnt =
8036 sg_entry_cnt - 1;
8037 }
8038 sg_entry_cnt = 0;
8039 }
8040 next_qp = AscReadLramByte(iop_base,
8041 (ushort)(q_addr +
8042 ASC_SCSIQ_B_FWD));
8043 scsi_sg_q.q_no = next_qp;
8044 q_addr = ASC_QNO_TO_QADDR(next_qp);
8045 AscMemWordCopyPtrToLram(iop_base,
8046 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8047 (uchar *)&scsi_sg_q,
8048 sizeof(ASC_SG_LIST_Q) >> 1);
8049 AscMemDWordCopyPtrToLram(iop_base,
8050 q_addr + ASC_SGQ_LIST_BEG,
8051 (uchar *)&sg_head->
8052 sg_list[sg_index],
8053 sg_list_dwords);
8054 sg_index += ASC_SG_LIST_PER_Q;
8055 scsiq->next_sg_index = sg_index;
8056 }
8057 } else {
8058 scsiq->q1.cntl &= ~QC_SG_HEAD;
8059 }
8060 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
8061 scsiq->q1.data_addr = saved_data_addr;
8062 scsiq->q1.data_cnt = saved_data_cnt;
8063 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008064}
8065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008066static int
8067AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008068{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008069 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008071 if (AscHostReqRiscHalt(iop_base)) {
8072 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8073 AscStartChip(iop_base);
8074 return (sta);
8075 }
8076 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008077}
8078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008079static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008080{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008081 ASC_SCSI_BIT_ID_TYPE org_id;
8082 int i;
8083 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008085 AscSetBank(iop_base, 1);
8086 org_id = AscReadChipDvcID(iop_base);
8087 for (i = 0; i <= ASC_MAX_TID; i++) {
8088 if (org_id == (0x01 << i))
8089 break;
8090 }
8091 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8092 AscWriteChipDvcID(iop_base, id);
8093 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8094 AscSetBank(iop_base, 0);
8095 AscSetChipSyn(iop_base, sdtr_data);
8096 if (AscGetChipSyn(iop_base) != sdtr_data) {
8097 sta = FALSE;
8098 }
8099 } else {
8100 sta = FALSE;
8101 }
8102 AscSetBank(iop_base, 1);
8103 AscWriteChipDvcID(iop_base, org_id);
8104 AscSetBank(iop_base, 0);
8105 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008106}
8107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008108static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008109{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008110 uchar i;
8111 ushort s_addr;
8112 PortAddr iop_base;
8113 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008115 iop_base = asc_dvc->iop_base;
8116 warn_code = 0;
8117 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
8118 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
8119 64) >> 1)
8120 );
8121 i = ASC_MIN_ACTIVE_QNO;
8122 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
8123 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8124 (uchar)(i + 1));
8125 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8126 (uchar)(asc_dvc->max_total_qng));
8127 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8128 (uchar)i);
8129 i++;
8130 s_addr += ASC_QBLK_SIZE;
8131 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
8132 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8133 (uchar)(i + 1));
8134 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8135 (uchar)(i - 1));
8136 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8137 (uchar)i);
8138 }
8139 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8140 (uchar)ASC_QLINK_END);
8141 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8142 (uchar)(asc_dvc->max_total_qng - 1));
8143 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8144 (uchar)asc_dvc->max_total_qng);
8145 i++;
8146 s_addr += ASC_QBLK_SIZE;
8147 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
8148 i++, s_addr += ASC_QBLK_SIZE) {
8149 AscWriteLramByte(iop_base,
8150 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
8151 AscWriteLramByte(iop_base,
8152 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
8153 AscWriteLramByte(iop_base,
8154 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
8155 }
8156 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008157}
8158
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008159static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008160{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008161 PortAddr iop_base;
8162 int i;
8163 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008164
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008165 iop_base = asc_dvc->iop_base;
8166 AscPutRiscVarFreeQHead(iop_base, 1);
8167 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8168 AscPutVarFreeQHead(iop_base, 1);
8169 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8170 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
8171 (uchar)((int)asc_dvc->max_total_qng + 1));
8172 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
8173 (uchar)((int)asc_dvc->max_total_qng + 2));
8174 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
8175 asc_dvc->max_total_qng);
8176 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
8177 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8178 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
8179 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
8180 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
8181 AscPutQDoneInProgress(iop_base, 0);
8182 lram_addr = ASC_QADR_BEG;
8183 for (i = 0; i < 32; i++, lram_addr += 2) {
8184 AscWriteLramWord(iop_base, lram_addr, 0);
8185 }
8186 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008187}
8188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008189static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008190{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008191 if (asc_dvc->err_code == 0) {
8192 asc_dvc->err_code = err_code;
8193 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8194 err_code);
8195 }
8196 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008197}
8198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008199static uchar
8200AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008201{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008202 EXT_MSG sdtr_buf;
8203 uchar sdtr_period_index;
8204 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008205
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008206 iop_base = asc_dvc->iop_base;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008207 sdtr_buf.msg_type = EXTENDED_MESSAGE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008208 sdtr_buf.msg_len = MS_SDTR_LEN;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008209 sdtr_buf.msg_req = EXTENDED_SDTR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008210 sdtr_buf.xfer_period = sdtr_period;
8211 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8212 sdtr_buf.req_ack_offset = sdtr_offset;
8213 if ((sdtr_period_index =
8214 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
8215 asc_dvc->max_sdtr_index) {
8216 AscMemWordCopyPtrToLram(iop_base,
8217 ASCV_MSGOUT_BEG,
8218 (uchar *)&sdtr_buf,
8219 sizeof(EXT_MSG) >> 1);
8220 return ((sdtr_period_index << 4) | sdtr_offset);
8221 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008222
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008223 sdtr_buf.req_ack_offset = 0;
8224 AscMemWordCopyPtrToLram(iop_base,
8225 ASCV_MSGOUT_BEG,
8226 (uchar *)&sdtr_buf,
8227 sizeof(EXT_MSG) >> 1);
8228 return (0);
8229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008230}
8231
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008232static uchar
8233AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008234{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008235 uchar byte;
8236 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008238 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8239 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
8240 ) {
8241 return (0xFF);
8242 }
8243 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8244 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008245}
8246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008247static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008248{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008249 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8250 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8251 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008252}
8253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008254static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008255{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008256 uchar *period_table;
8257 int max_index;
8258 int min_index;
8259 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008260
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008261 period_table = asc_dvc->sdtr_period_tbl;
8262 max_index = (int)asc_dvc->max_sdtr_index;
8263 min_index = (int)asc_dvc->host_init_sdtr_index;
8264 if ((syn_time <= period_table[max_index])) {
8265 for (i = min_index; i < (max_index - 1); i++) {
8266 if (syn_time <= period_table[i]) {
8267 return ((uchar)i);
8268 }
8269 }
8270 return ((uchar)max_index);
8271 } else {
8272 return ((uchar)(max_index + 1));
8273 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008274}
8275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008276static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008277{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008278 ushort q_addr;
8279 uchar next_qp;
8280 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008282 q_addr = ASC_QNO_TO_QADDR(free_q_head);
8283 q_status = (uchar)AscReadLramByte(iop_base,
8284 (ushort)(q_addr +
8285 ASC_SCSIQ_B_STATUS));
8286 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
8287 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
8288 return (next_qp);
8289 }
8290 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008291}
8292
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008293static uchar
8294AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008295{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008296 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008298 for (i = 0; i < n_free_q; i++) {
8299 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
8300 == ASC_QLINK_END) {
8301 return (ASC_QLINK_END);
8302 }
8303 }
8304 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008305}
8306
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008307static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008308{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008309 int count = 0;
8310 int sta = 0;
8311 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008312
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008313 if (AscIsChipHalted(iop_base))
8314 return (1);
8315 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
8316 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8317 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
8318 do {
8319 if (AscIsChipHalted(iop_base)) {
8320 sta = 1;
8321 break;
8322 }
8323 DvcSleepMilliSecond(100);
8324 } while (count++ < 20);
8325 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
8326 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008327}
8328
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008329static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008330{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008331 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008332
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008333 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
8334 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8335 ASC_STOP_REQ_RISC_STOP);
8336 do {
8337 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
8338 ASC_STOP_ACK_RISC_STOP) {
8339 return (1);
8340 }
8341 DvcSleepMilliSecond(100);
8342 } while (count++ < 20);
8343 }
8344 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008345}
8346
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008347static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008348{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008349 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008350}
8351
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008352static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008353{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008354 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008355}
8356
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008357static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008358{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008359 AscSetChipControl(iop_base, 0);
8360 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8361 return (0);
8362 }
8363 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008364}
8365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008366static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008367{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008368 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008369
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008370 cc_val =
8371 AscGetChipControl(iop_base) &
8372 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
8373 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
8374 AscSetChipIH(iop_base, INS_HALT);
8375 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8376 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
8377 return (0);
8378 }
8379 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008380}
8381
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008382static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008383{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008384 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8385 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
8386 return (1);
8387 }
8388 }
8389 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008390}
8391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008392static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008393{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008394 AscSetBank(iop_base, 1);
8395 AscWriteChipIH(iop_base, ins_code);
8396 AscSetBank(iop_base, 0);
8397 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008398}
8399
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008400static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008401{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008402 uchar host_flag;
8403 uchar risc_flag;
8404 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008406 loop = 0;
8407 do {
8408 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8409 if (loop++ > 0x7FFF) {
8410 break;
8411 }
8412 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8413 host_flag =
8414 AscReadLramByte(iop_base,
8415 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8416 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8417 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8418 AscSetChipStatus(iop_base, CIW_INT_ACK);
8419 loop = 0;
8420 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8421 AscSetChipStatus(iop_base, CIW_INT_ACK);
8422 if (loop++ > 3) {
8423 break;
8424 }
8425 }
8426 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8427 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008428}
8429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008430static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008431{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008432 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008433
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008434 cfg = AscGetChipCfgLsw(iop_base);
8435 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
8436 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008437}
8438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008439static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008440{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008441 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008442
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008443 cfg = AscGetChipCfgLsw(iop_base);
8444 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
8445 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008446}
8447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008448static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008449{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008450 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008452 val = AscGetChipControl(iop_base) &
8453 (~
8454 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
8455 CC_CHIP_RESET));
8456 if (bank == 1) {
8457 val |= CC_BANK_ONE;
8458 } else if (bank == 2) {
8459 val |= CC_DIAG | CC_BANK_ONE;
8460 } else {
8461 val &= ~CC_BANK_ONE;
8462 }
8463 AscSetChipControl(iop_base, val);
8464 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008465}
8466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008467static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008468{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008469 PortAddr iop_base;
8470 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008471
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008472 iop_base = asc_dvc->iop_base;
8473 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
8474 && (i-- > 0)) {
8475 DvcSleepMilliSecond(100);
8476 }
8477 AscStopChip(iop_base);
8478 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
8479 DvcDelayNanoSecond(asc_dvc, 60000);
8480 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8481 AscSetChipIH(iop_base, INS_HALT);
8482 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
8483 AscSetChipControl(iop_base, CC_HALT);
8484 DvcSleepMilliSecond(200);
8485 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
8486 AscSetChipStatus(iop_base, 0);
8487 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008488}
8489
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008490static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008491{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008492 if (bus_type & ASC_IS_ISA)
8493 return (ASC_MAX_ISA_DMA_COUNT);
8494 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
8495 return (ASC_MAX_VL_DMA_COUNT);
8496 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008497}
8498
8499#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008500static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008501{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008502 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008503
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008504 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
8505 if (channel == 0x03)
8506 return (0);
8507 else if (channel == 0x00)
8508 return (7);
8509 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008510}
8511
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008512static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008513{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008514 ushort cfg_lsw;
8515 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008516
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008517 if ((dma_channel >= 5) && (dma_channel <= 7)) {
8518 if (dma_channel == 7)
8519 value = 0x00;
8520 else
8521 value = dma_channel - 4;
8522 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
8523 cfg_lsw |= value;
8524 AscSetChipCfgLsw(iop_base, cfg_lsw);
8525 return (AscGetIsaDmaChannel(iop_base));
8526 }
8527 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008528}
8529
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008530static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008531{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008532 speed_value &= 0x07;
8533 AscSetBank(iop_base, 1);
8534 AscWriteChipDmaSpeed(iop_base, speed_value);
8535 AscSetBank(iop_base, 0);
8536 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008537}
8538
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008539static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008540{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008541 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008542
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008543 AscSetBank(iop_base, 1);
8544 speed_value = AscReadChipDmaSpeed(iop_base);
8545 speed_value &= 0x07;
8546 AscSetBank(iop_base, 0);
8547 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008548}
8549#endif /* CONFIG_ISA */
8550
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008551static int __devinit AscInitGetConfig(asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008552{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008553 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008554 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008555
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008556 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008557 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008558 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008559
Matthew Wilcox9649af32007-07-26 21:51:47 -06008560 if (AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008561 warn_code |= AscInitAscDvcVar(asc_dvc);
8562 warn_code |= AscInitFromEEP(asc_dvc);
8563 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06008564 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008565 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008566 } else {
8567 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8568 }
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008569
8570 switch (warn_code) {
8571 case 0: /* No error */
8572 break;
8573 case ASC_WARN_IO_PORT_ROTATE:
8574 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
8575 "modified\n", boardp->id);
8576 break;
8577 case ASC_WARN_AUTO_CONFIG:
8578 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
8579 "switch enabled\n", boardp->id);
8580 break;
8581 case ASC_WARN_EEPROM_CHKSUM:
8582 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
8583 "error\n", boardp->id);
8584 break;
8585 case ASC_WARN_IRQ_MODIFIED:
8586 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
8587 boardp->id);
8588 break;
8589 case ASC_WARN_CMD_QNG_CONFLICT:
8590 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
8591 "w/o disconnects\n", boardp->id);
8592 break;
8593 default:
8594 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
8595 "0x%x\n", boardp->id, warn_code);
8596 break;
8597 }
8598
8599 if (asc_dvc->err_code != 0) {
8600 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
8601 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8602 asc_dvc->err_code);
8603 }
8604
8605 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008606}
8607
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008608static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008609{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008610 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008611 PortAddr iop_base = asc_dvc->iop_base;
8612 unsigned short cfg_msw;
8613 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008614
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008615 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
8616 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008617 return asc_dvc->err_code;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008618 if (!AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008619 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008620 return asc_dvc->err_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008621 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008622
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008623 cfg_msw = AscGetChipCfgMsw(iop_base);
8624 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008625 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008626 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8627 AscSetChipCfgMsw(iop_base, cfg_msw);
8628 }
8629 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
8630 asc_dvc->cfg->cmd_qng_enabled) {
8631 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
8632 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
8633 }
8634 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8635 warn_code |= ASC_WARN_AUTO_CONFIG;
8636 }
8637 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
8638 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
8639 != asc_dvc->irq_no) {
8640 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
8641 }
8642 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008643#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008644 if (asc_dvc->bus_type & ASC_IS_PCI) {
8645 cfg_msw &= 0xFFC0;
8646 AscSetChipCfgMsw(iop_base, cfg_msw);
8647 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
8648 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -06008649 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
8650 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008651 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
8652 asc_dvc->bug_fix_cntl |=
8653 ASC_BUG_FIX_ASYN_USE_SYN;
8654 }
8655 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008656 } else
8657#endif /* CONFIG_PCI */
8658 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008659 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
8660 == ASC_CHIP_VER_ASYN_BUG) {
8661 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
8662 }
8663 }
8664 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
8665 asc_dvc->cfg->chip_scsi_id) {
8666 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
8667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008668#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008669 if (asc_dvc->bus_type & ASC_IS_ISA) {
8670 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
8671 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
8672 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008673#endif /* CONFIG_ISA */
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008674
8675 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008676
8677 switch (warn_code) {
8678 case 0: /* No error. */
8679 break;
8680 case ASC_WARN_IO_PORT_ROTATE:
8681 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
8682 "modified\n", boardp->id);
8683 break;
8684 case ASC_WARN_AUTO_CONFIG:
8685 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
8686 "switch enabled\n", boardp->id);
8687 break;
8688 case ASC_WARN_EEPROM_CHKSUM:
8689 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
8690 "error\n", boardp->id);
8691 break;
8692 case ASC_WARN_IRQ_MODIFIED:
8693 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
8694 boardp->id);
8695 break;
8696 case ASC_WARN_CMD_QNG_CONFLICT:
8697 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
8698 "disconnects\n",
8699 boardp->id);
8700 break;
8701 default:
8702 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
8703 "0x%x\n", boardp->id, warn_code);
8704 break;
8705 }
8706
8707 if (asc_dvc->err_code != 0) {
8708 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
8709 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8710 asc_dvc->err_code);
8711 }
8712
8713 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008714}
8715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008716static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008717{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008718 ushort warn_code;
8719 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008721 iop_base = asc_dvc->iop_base;
8722 warn_code = 0;
8723 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
8724 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
8725 AscResetChipAndScsiBus(asc_dvc);
8726 DvcSleepMilliSecond((ASC_DCNT)
8727 ((ushort)asc_dvc->scsi_reset_wait * 1000));
8728 }
8729 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
8730 if (asc_dvc->err_code != 0)
8731 return (UW_ERR);
8732 if (!AscFindSignature(asc_dvc->iop_base)) {
8733 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8734 return (warn_code);
8735 }
8736 AscDisableInterrupt(iop_base);
8737 warn_code |= AscInitLram(asc_dvc);
8738 if (asc_dvc->err_code != 0)
8739 return (UW_ERR);
8740 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
8741 (ulong)_asc_mcode_chksum);
8742 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
8743 _asc_mcode_size) != _asc_mcode_chksum) {
8744 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
8745 return (warn_code);
8746 }
8747 warn_code |= AscInitMicroCodeVar(asc_dvc);
8748 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
8749 AscEnableInterrupt(iop_base);
8750 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008751}
8752
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008753static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008754{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008755 int i;
8756 PortAddr iop_base;
8757 ushort warn_code;
8758 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008759
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008760 iop_base = asc_dvc->iop_base;
8761 warn_code = 0;
8762 asc_dvc->err_code = 0;
8763 if ((asc_dvc->bus_type &
8764 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
8765 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
8766 }
8767 AscSetChipControl(iop_base, CC_HALT);
8768 AscSetChipStatus(iop_base, 0);
8769 asc_dvc->bug_fix_cntl = 0;
8770 asc_dvc->pci_fix_asyn_xfer = 0;
8771 asc_dvc->pci_fix_asyn_xfer_always = 0;
8772 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
8773 asc_dvc->sdtr_done = 0;
8774 asc_dvc->cur_total_qng = 0;
8775 asc_dvc->is_in_int = 0;
8776 asc_dvc->in_critical_cnt = 0;
8777 asc_dvc->last_q_shortage = 0;
8778 asc_dvc->use_tagged_qng = 0;
8779 asc_dvc->no_scam = 0;
8780 asc_dvc->unit_not_ready = 0;
8781 asc_dvc->queue_full_or_busy = 0;
8782 asc_dvc->redo_scam = 0;
8783 asc_dvc->res2 = 0;
8784 asc_dvc->host_init_sdtr_index = 0;
8785 asc_dvc->cfg->can_tagged_qng = 0;
8786 asc_dvc->cfg->cmd_qng_enabled = 0;
8787 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
8788 asc_dvc->init_sdtr = 0;
8789 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
8790 asc_dvc->scsi_reset_wait = 3;
8791 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
8792 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
8793 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
8794 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
8795 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
8796 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
8797 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
8798 ASC_LIB_VERSION_MINOR;
8799 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
8800 asc_dvc->cfg->chip_version = chip_version;
8801 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
8802 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
8803 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
8804 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
8805 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
8806 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
8807 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
8808 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
8809 asc_dvc->max_sdtr_index = 7;
8810 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
8811 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
8812 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
8813 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
8814 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
8815 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
8816 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
8817 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
8818 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
8819 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
8820 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
8821 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
8822 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
8823 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
8824 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
8825 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
8826 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
8827 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
8828 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
8829 asc_dvc->max_sdtr_index = 15;
8830 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
8831 AscSetExtraControl(iop_base,
8832 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8833 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
8834 AscSetExtraControl(iop_base,
8835 (SEC_ACTIVE_NEGATE |
8836 SEC_ENABLE_FILTER));
8837 }
8838 }
8839 if (asc_dvc->bus_type == ASC_IS_PCI) {
8840 AscSetExtraControl(iop_base,
8841 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8842 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008844 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008845#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008846 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
Matthew Wilcox59fcf842007-07-26 11:54:15 -04008847 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
8848 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
8849 asc_dvc->bus_type = ASC_IS_ISAPNP;
8850 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008851 asc_dvc->cfg->isa_dma_channel =
8852 (uchar)AscGetIsaDmaChannel(iop_base);
8853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008854#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008855 for (i = 0; i <= ASC_MAX_TID; i++) {
8856 asc_dvc->cur_dvc_qng[i] = 0;
8857 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
8858 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
8859 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
8860 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
8861 }
8862 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008863}
8864
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008865static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008866{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008867 ASCEEP_CONFIG eep_config_buf;
8868 ASCEEP_CONFIG *eep_config;
8869 PortAddr iop_base;
8870 ushort chksum;
8871 ushort warn_code;
8872 ushort cfg_msw, cfg_lsw;
8873 int i;
8874 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008875
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008876 iop_base = asc_dvc->iop_base;
8877 warn_code = 0;
8878 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
8879 AscStopQueueExe(iop_base);
8880 if ((AscStopChip(iop_base) == FALSE) ||
8881 (AscGetChipScsiCtrl(iop_base) != 0)) {
8882 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
8883 AscResetChipAndScsiBus(asc_dvc);
8884 DvcSleepMilliSecond((ASC_DCNT)
8885 ((ushort)asc_dvc->scsi_reset_wait * 1000));
8886 }
8887 if (AscIsChipHalted(iop_base) == FALSE) {
8888 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8889 return (warn_code);
8890 }
8891 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8892 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8893 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8894 return (warn_code);
8895 }
8896 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
8897 cfg_msw = AscGetChipCfgMsw(iop_base);
8898 cfg_lsw = AscGetChipCfgLsw(iop_base);
8899 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008900 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008901 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8902 AscSetChipCfgMsw(iop_base, cfg_msw);
8903 }
8904 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
8905 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
8906 if (chksum == 0) {
8907 chksum = 0xaa55;
8908 }
8909 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8910 warn_code |= ASC_WARN_AUTO_CONFIG;
8911 if (asc_dvc->cfg->chip_version == 3) {
8912 if (eep_config->cfg_lsw != cfg_lsw) {
8913 warn_code |= ASC_WARN_EEPROM_RECOVER;
8914 eep_config->cfg_lsw =
8915 AscGetChipCfgLsw(iop_base);
8916 }
8917 if (eep_config->cfg_msw != cfg_msw) {
8918 warn_code |= ASC_WARN_EEPROM_RECOVER;
8919 eep_config->cfg_msw =
8920 AscGetChipCfgMsw(iop_base);
8921 }
8922 }
8923 }
8924 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
8925 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
8926 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
8927 eep_config->chksum);
8928 if (chksum != eep_config->chksum) {
8929 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
8930 ASC_CHIP_VER_PCI_ULTRA_3050) {
8931 ASC_DBG(1,
8932 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
8933 eep_config->init_sdtr = 0xFF;
8934 eep_config->disc_enable = 0xFF;
8935 eep_config->start_motor = 0xFF;
8936 eep_config->use_cmd_qng = 0;
8937 eep_config->max_total_qng = 0xF0;
8938 eep_config->max_tag_qng = 0x20;
8939 eep_config->cntl = 0xBFFF;
8940 ASC_EEP_SET_CHIP_ID(eep_config, 7);
8941 eep_config->no_scam = 0;
8942 eep_config->adapter_info[0] = 0;
8943 eep_config->adapter_info[1] = 0;
8944 eep_config->adapter_info[2] = 0;
8945 eep_config->adapter_info[3] = 0;
8946 eep_config->adapter_info[4] = 0;
8947 /* Indicate EEPROM-less board. */
8948 eep_config->adapter_info[5] = 0xBB;
8949 } else {
8950 ASC_PRINT
8951 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
8952 write_eep = 1;
8953 warn_code |= ASC_WARN_EEPROM_CHKSUM;
8954 }
8955 }
8956 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
8957 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
8958 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
8959 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
8960 asc_dvc->start_motor = eep_config->start_motor;
8961 asc_dvc->dvc_cntl = eep_config->cntl;
8962 asc_dvc->no_scam = eep_config->no_scam;
8963 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
8964 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
8965 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
8966 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
8967 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
8968 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
8969 if (!AscTestExternalLram(asc_dvc)) {
8970 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
8971 ASC_IS_PCI_ULTRA)) {
8972 eep_config->max_total_qng =
8973 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
8974 eep_config->max_tag_qng =
8975 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
8976 } else {
8977 eep_config->cfg_msw |= 0x0800;
8978 cfg_msw |= 0x0800;
8979 AscSetChipCfgMsw(iop_base, cfg_msw);
8980 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
8981 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
8982 }
8983 } else {
8984 }
8985 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
8986 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
8987 }
8988 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
8989 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
8990 }
8991 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
8992 eep_config->max_tag_qng = eep_config->max_total_qng;
8993 }
8994 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
8995 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
8996 }
8997 asc_dvc->max_total_qng = eep_config->max_total_qng;
8998 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
8999 eep_config->use_cmd_qng) {
9000 eep_config->disc_enable = eep_config->use_cmd_qng;
9001 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
9002 }
9003 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
9004 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
9005 }
9006 ASC_EEP_SET_CHIP_ID(eep_config,
9007 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
9008 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
9009 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
9010 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
9011 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
9012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009014 for (i = 0; i <= ASC_MAX_TID; i++) {
9015 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
9016 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
9017 asc_dvc->cfg->sdtr_period_offset[i] =
9018 (uchar)(ASC_DEF_SDTR_OFFSET |
9019 (asc_dvc->host_init_sdtr_index << 4));
9020 }
9021 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
9022 if (write_eep) {
9023 if ((i =
9024 AscSetEEPConfig(iop_base, eep_config,
9025 asc_dvc->bus_type)) != 0) {
9026 ASC_PRINT1
9027 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
9028 i);
9029 } else {
9030 ASC_PRINT
9031 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
9032 }
9033 }
9034 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009035}
9036
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009037static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009038{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009039 int i;
9040 ushort warn_code;
9041 PortAddr iop_base;
9042 ASC_PADDR phy_addr;
9043 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009044
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009045 iop_base = asc_dvc->iop_base;
9046 warn_code = 0;
9047 for (i = 0; i <= ASC_MAX_TID; i++) {
9048 AscPutMCodeInitSDTRAtID(iop_base, i,
9049 asc_dvc->cfg->sdtr_period_offset[i]
9050 );
9051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009053 AscInitQLinkVar(asc_dvc);
9054 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
9055 asc_dvc->cfg->disc_enable);
9056 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
9057 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009058
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009059 /* Align overrun buffer on an 8 byte boundary. */
9060 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
9061 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
9062 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
9063 (uchar *)&phy_addr, 1);
9064 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
9065 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
9066 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009068 asc_dvc->cfg->mcode_date =
9069 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
9070 asc_dvc->cfg->mcode_version =
9071 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009073 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
9074 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
9075 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
9076 return (warn_code);
9077 }
9078 if (AscStartChip(iop_base) != 1) {
9079 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
9080 return (warn_code);
9081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009083 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009084}
9085
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009086static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009087{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009088 PortAddr iop_base;
9089 ushort q_addr;
9090 ushort saved_word;
9091 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009092
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009093 iop_base = asc_dvc->iop_base;
9094 sta = 0;
9095 q_addr = ASC_QNO_TO_QADDR(241);
9096 saved_word = AscReadLramWord(iop_base, q_addr);
9097 AscSetChipLramAddr(iop_base, q_addr);
9098 AscSetChipLramData(iop_base, 0x55AA);
9099 DvcSleepMilliSecond(10);
9100 AscSetChipLramAddr(iop_base, q_addr);
9101 if (AscGetChipLramData(iop_base) == 0x55AA) {
9102 sta = 1;
9103 AscWriteLramWord(iop_base, q_addr, saved_word);
9104 }
9105 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009106}
9107
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009108static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009109{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009110 uchar read_back;
9111 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009112
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009113 retry = 0;
9114 while (TRUE) {
9115 AscSetChipEEPCmd(iop_base, cmd_reg);
9116 DvcSleepMilliSecond(1);
9117 read_back = AscGetChipEEPCmd(iop_base);
9118 if (read_back == cmd_reg) {
9119 return (1);
9120 }
9121 if (retry++ > ASC_EEP_MAX_RETRY) {
9122 return (0);
9123 }
9124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009125}
9126
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009127static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009128{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009129 ushort read_back;
9130 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009131
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009132 retry = 0;
9133 while (TRUE) {
9134 AscSetChipEEPData(iop_base, data_reg);
9135 DvcSleepMilliSecond(1);
9136 read_back = AscGetChipEEPData(iop_base);
9137 if (read_back == data_reg) {
9138 return (1);
9139 }
9140 if (retry++ > ASC_EEP_MAX_RETRY) {
9141 return (0);
9142 }
9143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009144}
9145
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009146static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009147{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009148 DvcSleepMilliSecond(1);
9149 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009150}
9151
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009152static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009153{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009154 DvcSleepMilliSecond(20);
9155 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009156}
9157
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009158static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009159{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009160 ushort read_wval;
9161 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009162
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009163 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9164 AscWaitEEPRead();
9165 cmd_reg = addr | ASC_EEP_CMD_READ;
9166 AscWriteEEPCmdReg(iop_base, cmd_reg);
9167 AscWaitEEPRead();
9168 read_wval = AscGetChipEEPData(iop_base);
9169 AscWaitEEPRead();
9170 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009171}
9172
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009173static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009174AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009175{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009176 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009177
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009178 read_wval = AscReadEEPWord(iop_base, addr);
9179 if (read_wval != word_val) {
9180 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
9181 AscWaitEEPRead();
9182 AscWriteEEPDataReg(iop_base, word_val);
9183 AscWaitEEPRead();
9184 AscWriteEEPCmdReg(iop_base,
9185 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
9186 AscWaitEEPWrite();
9187 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9188 AscWaitEEPRead();
9189 return (AscReadEEPWord(iop_base, addr));
9190 }
9191 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009192}
9193
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009194static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009195AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009196{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009197 ushort wval;
9198 ushort sum;
9199 ushort *wbuf;
9200 int cfg_beg;
9201 int cfg_end;
9202 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
9203 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009204
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009205 wbuf = (ushort *)cfg_buf;
9206 sum = 0;
9207 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
9208 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9209 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9210 sum += *wbuf;
9211 }
9212 if (bus_type & ASC_IS_VL) {
9213 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9214 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9215 } else {
9216 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9217 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9218 }
9219 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9220 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
9221 if (s_addr <= uchar_end_in_config) {
9222 /*
9223 * Swap all char fields - must unswap bytes already swapped
9224 * by AscReadEEPWord().
9225 */
9226 *wbuf = le16_to_cpu(wval);
9227 } else {
9228 /* Don't swap word field at the end - cntl field. */
9229 *wbuf = wval;
9230 }
9231 sum += wval; /* Checksum treats all EEPROM data as words. */
9232 }
9233 /*
9234 * Read the checksum word which will be compared against 'sum'
9235 * by the caller. Word field already swapped.
9236 */
9237 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9238 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009239}
9240
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009241static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009242AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009243{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009244 int n_error;
9245 ushort *wbuf;
9246 ushort word;
9247 ushort sum;
9248 int s_addr;
9249 int cfg_beg;
9250 int cfg_end;
9251 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009252
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009253 wbuf = (ushort *)cfg_buf;
9254 n_error = 0;
9255 sum = 0;
9256 /* Write two config words; AscWriteEEPWord() will swap bytes. */
9257 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9258 sum += *wbuf;
9259 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9260 n_error++;
9261 }
9262 }
9263 if (bus_type & ASC_IS_VL) {
9264 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9265 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9266 } else {
9267 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9268 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9269 }
9270 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9271 if (s_addr <= uchar_end_in_config) {
9272 /*
9273 * This is a char field. Swap char fields before they are
9274 * swapped again by AscWriteEEPWord().
9275 */
9276 word = cpu_to_le16(*wbuf);
9277 if (word !=
9278 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
9279 n_error++;
9280 }
9281 } else {
9282 /* Don't swap word field at the end - cntl field. */
9283 if (*wbuf !=
9284 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9285 n_error++;
9286 }
9287 }
9288 sum += *wbuf; /* Checksum calculated from word values. */
9289 }
9290 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
9291 *wbuf = sum;
9292 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
9293 n_error++;
9294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009295
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009296 /* Read EEPROM back again. */
9297 wbuf = (ushort *)cfg_buf;
9298 /*
9299 * Read two config words; Byte-swapping done by AscReadEEPWord().
9300 */
9301 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9302 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
9303 n_error++;
9304 }
9305 }
9306 if (bus_type & ASC_IS_VL) {
9307 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9308 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9309 } else {
9310 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9311 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9312 }
9313 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9314 if (s_addr <= uchar_end_in_config) {
9315 /*
9316 * Swap all char fields. Must unswap bytes already swapped
9317 * by AscReadEEPWord().
9318 */
9319 word =
9320 le16_to_cpu(AscReadEEPWord
9321 (iop_base, (uchar)s_addr));
9322 } else {
9323 /* Don't swap word field at the end - cntl field. */
9324 word = AscReadEEPWord(iop_base, (uchar)s_addr);
9325 }
9326 if (*wbuf != word) {
9327 n_error++;
9328 }
9329 }
9330 /* Read checksum; Byte swapping not needed. */
9331 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
9332 n_error++;
9333 }
9334 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009335}
9336
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009337static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009338AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009339{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009340 int retry;
9341 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009342
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009343 retry = 0;
9344 while (TRUE) {
9345 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
9346 bus_type)) == 0) {
9347 break;
9348 }
9349 if (++retry > ASC_EEP_MAX_RETRY) {
9350 break;
9351 }
9352 }
9353 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009354}
9355
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009356static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009357{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009358 char type = sdev->type;
9359 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009361 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
9362 if (!(asc_dvc->init_sdtr & tid_bits)) {
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009363 if ((type == TYPE_ROM) &&
9364 (strncmp(sdev->vendor, "HP ", 3) == 0)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009365 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9366 }
9367 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009368 if ((type == TYPE_PROCESSOR) ||
9369 (type == TYPE_SCANNER) || (type == TYPE_ROM) ||
9370 (type == TYPE_TAPE)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009371 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009374 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
9375 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009376 sdev->id,
9377 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009378 }
9379 }
9380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009381}
9382
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009383static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009384{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009385 uchar byte_data;
9386 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009387
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009388 if (isodd_word(addr)) {
9389 AscSetChipLramAddr(iop_base, addr - 1);
9390 word_data = AscGetChipLramData(iop_base);
9391 byte_data = (uchar)((word_data >> 8) & 0xFF);
9392 } else {
9393 AscSetChipLramAddr(iop_base, addr);
9394 word_data = AscGetChipLramData(iop_base);
9395 byte_data = (uchar)(word_data & 0xFF);
9396 }
9397 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009398}
Linus Torvalds1da177e2005-04-16 15:20:36 -07009399
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009400static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
9401{
9402 ushort word_data;
9403
9404 AscSetChipLramAddr(iop_base, addr);
9405 word_data = AscGetChipLramData(iop_base);
9406 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009407}
9408
9409#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009410static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009411{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009412 ushort val_low, val_high;
9413 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009414
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009415 AscSetChipLramAddr(iop_base, addr);
9416 val_low = AscGetChipLramData(iop_base);
9417 val_high = AscGetChipLramData(iop_base);
9418 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
9419 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420}
9421#endif /* CC_VERY_LONG_SG_LIST */
9422
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009423static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009424{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009425 AscSetChipLramAddr(iop_base, addr);
9426 AscSetChipLramData(iop_base, word_val);
9427 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009428}
9429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009430static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009431{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009432 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009433
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009434 if (isodd_word(addr)) {
9435 addr--;
9436 word_data = AscReadLramWord(iop_base, addr);
9437 word_data &= 0x00FF;
9438 word_data |= (((ushort)byte_val << 8) & 0xFF00);
9439 } else {
9440 word_data = AscReadLramWord(iop_base, addr);
9441 word_data &= 0xFF00;
9442 word_data |= ((ushort)byte_val & 0x00FF);
9443 }
9444 AscWriteLramWord(iop_base, addr, word_data);
9445 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009446}
9447
9448/*
9449 * Copy 2 bytes to LRAM.
9450 *
9451 * The source data is assumed to be in little-endian order in memory
9452 * and is maintained in little-endian order when written to LRAM.
9453 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009454static void
9455AscMemWordCopyPtrToLram(PortAddr iop_base,
9456 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009457{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009458 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009460 AscSetChipLramAddr(iop_base, s_addr);
9461 for (i = 0; i < 2 * words; i += 2) {
9462 /*
9463 * On a little-endian system the second argument below
9464 * produces a little-endian ushort which is written to
9465 * LRAM in little-endian order. On a big-endian system
9466 * the second argument produces a big-endian ushort which
9467 * is "transparently" byte-swapped by outpw() and written
9468 * in little-endian order to LRAM.
9469 */
9470 outpw(iop_base + IOP_RAM_DATA,
9471 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
9472 }
9473 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009474}
9475
9476/*
9477 * Copy 4 bytes to LRAM.
9478 *
9479 * The source data is assumed to be in little-endian order in memory
9480 * and is maintained in little-endian order when writen to LRAM.
9481 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009482static void
9483AscMemDWordCopyPtrToLram(PortAddr iop_base,
9484 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009485{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009486 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009487
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009488 AscSetChipLramAddr(iop_base, s_addr);
9489 for (i = 0; i < 4 * dwords; i += 4) {
9490 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
9491 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
9492 }
9493 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009494}
9495
9496/*
9497 * Copy 2 bytes from LRAM.
9498 *
9499 * The source data is assumed to be in little-endian order in LRAM
9500 * and is maintained in little-endian order when written to memory.
9501 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009502static void
9503AscMemWordCopyPtrFromLram(PortAddr iop_base,
9504 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009505{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009506 int i;
9507 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009508
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009509 AscSetChipLramAddr(iop_base, s_addr);
9510 for (i = 0; i < 2 * words; i += 2) {
9511 word = inpw(iop_base + IOP_RAM_DATA);
9512 d_buffer[i] = word & 0xff;
9513 d_buffer[i + 1] = (word >> 8) & 0xff;
9514 }
9515 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009516}
9517
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009518static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009519{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009520 ASC_DCNT sum;
9521 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009523 sum = 0L;
9524 for (i = 0; i < words; i++, s_addr += 2) {
9525 sum += AscReadLramWord(iop_base, s_addr);
9526 }
9527 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009528}
9529
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009530static void
9531AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009532{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009533 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009535 AscSetChipLramAddr(iop_base, s_addr);
9536 for (i = 0; i < words; i++) {
9537 AscSetChipLramData(iop_base, set_wval);
9538 }
9539 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009540}
9541
Linus Torvalds1da177e2005-04-16 15:20:36 -07009542/*
9543 * --- Adv Library Functions
9544 */
9545
9546/* a_mcode.h */
9547
9548/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009549static unsigned char _adv_asc3550_buf[] = {
9550 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009551 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
9552 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
9553 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009554 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009555 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
9556 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
9557 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009558 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009559 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
9560 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
9561 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009562 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009563 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
9564 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
9565 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009566 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009567 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
9568 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
9569 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009570 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009571 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
9572 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
9573 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009574 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009575 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
9576 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
9577 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009578 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009579 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
9580 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
9581 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009582 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009583 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
9584 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
9585 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009586 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009587 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
9588 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
9589 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009590 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009591 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
9592 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
9593 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009594 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009595 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
9596 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
9597 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009598 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009599 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
9600 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
9601 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009602 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009603 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
9604 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
9605 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009606 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009607 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
9608 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
9609 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009610 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009611 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
9612 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
9613 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009614 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009615 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
9616 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
9617 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009618 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009619 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
9620 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
9621 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009622 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009623 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
9624 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
9625 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009626 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009627 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
9628 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
9629 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009630 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009631 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
9632 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
9633 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009634 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009635 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
9636 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
9637 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009638 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009639 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
9640 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
9641 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009642 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009643 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
9644 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
9645 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009646 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009647 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
9648 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
9649 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009650 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009651 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
9652 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
9653 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009654 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009655 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
9656 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
9657 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009658 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009659 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
9660 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
9661 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009662 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009663 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
9664 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
9665 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009666 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009667 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
9668 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
9669 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009670 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009671 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
9672 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
9673 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009674 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009675 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
9676 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
9677 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009678 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009679 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
9680 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
9681 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009682 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009683 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
9684 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
9685 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009686 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009687 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
9688 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
9689 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009690 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009691 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
9692 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
9693 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009694 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009695 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
9696 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
9697 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009698 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009699 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
9700 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
9701 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009702 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009703 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
9704 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
9705 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009706 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009707 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
9708 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
9709 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009710 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009711 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
9712 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
9713 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009714 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009715 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
9716 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
9717 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009718 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009719 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
9720 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
9721 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009722 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009723 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
9724 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
9725 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009726 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009727 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
9728 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
9729 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009730 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009731 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
9732 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
9733 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009734 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009735 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
9736 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
9737 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009738 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009739 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
9740 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
9741 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009742 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009743 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
9744 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
9745 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009746 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009747 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
9748 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
9749 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009750 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009751 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
9752 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
9753 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009754 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009755 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
9756 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
9757 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009758 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009759 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
9760 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
9761 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009762 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009763 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
9764 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
9765 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009766 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009767 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
9768 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
9769 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009770 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009771 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
9772 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
9773 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009774 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009775 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
9776 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
9777 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009778 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009779 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
9780 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
9781 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009782 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009783 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
9784 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
9785 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009786 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009787 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
9788 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
9789 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009790 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009791 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
9792 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
9793 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009794 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009795 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
9796 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
9797 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009798 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009799 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
9800 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
9801 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009802 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009803 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
9804 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
9805 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009806 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009807 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
9808 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
9809 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009810 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009811 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
9812 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
9813 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009814 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009815 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
9816 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
9817 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009818 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009819 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
9820 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
9821 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009822 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009823 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
9824 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
9825 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009826 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009827 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
9828 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
9829 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009830 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009831 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
9832 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
9833 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009834 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009835 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
9836 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
9837 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009838 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009839 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
9840 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
9841 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009842 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009843 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
9844 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
9845 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009846 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009847 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
9848 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
9849 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009850 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009851 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
9852 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
9853 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009854 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009855 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
9856 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
9857 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009858 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009859 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
9860 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
9861 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009862 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009863 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
9864 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
9865 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009866 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009867 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
9868 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
9869 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009870 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009871 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
9872 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
9873 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009874 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009875 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
9876 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
9877 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009878 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009879 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
9880 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
9881 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009882 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009883 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
9884 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
9885 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009886 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009887 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
9888 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
9889 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009890 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009891 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
9892 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
9893 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009894 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009895 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
9896 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
9897 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009898 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009899 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
9900 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
9901 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009902 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009903 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
9904 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
9905 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009906 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009907 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
9908 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
9909 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009910 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009911 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
9912 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
9913 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009914 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009915 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
9916 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
9917 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009918 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009919 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
9920 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
9921 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009922 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009923 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
9924 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
9925 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009926 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009927 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
9928 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
9929 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009930 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009931 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
9932 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
9933 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009934 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009935 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
9936 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
9937 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009938 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009939 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
9940 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
9941 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009942 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009943 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
9944 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
9945 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009946 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009947 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
9948 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
9949 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009950 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009951 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
9952 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
9953 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009954 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009955 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
9956 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
9957 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009958 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009959 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
9960 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
9961 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009962 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009963 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
9964 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
9965 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009966 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009967 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
9968 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009969};
9970
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009971static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
9972static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009973
9974/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009975static unsigned char _adv_asc38C0800_buf[] = {
9976 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009977 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
9978 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
9979 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009980 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009981 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
9982 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
9983 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009984 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009985 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
9986 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
9987 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009988 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009989 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
9990 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
9991 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009992 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009993 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
9994 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
9995 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009996 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009997 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
9998 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
9999 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010000 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010001 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
10002 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
10003 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010004 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010005 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
10006 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
10007 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010008 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010009 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
10010 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
10011 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010012 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010013 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
10014 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
10015 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010016 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010017 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
10018 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
10019 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010020 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010021 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
10022 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10023 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010024 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010025 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
10026 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
10027 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010028 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010029 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
10030 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
10031 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010032 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010033 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
10034 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
10035 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010036 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010037 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
10038 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
10039 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010040 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010041 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
10042 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
10043 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010044 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010045 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
10046 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
10047 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010048 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010049 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
10050 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
10051 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010052 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010053 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
10054 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
10055 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010056 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010057 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
10058 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
10059 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010060 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010061 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
10062 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
10063 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010064 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010065 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
10066 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
10067 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010068 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010069 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
10070 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
10071 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010072 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010073 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
10074 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
10075 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010076 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010077 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
10078 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
10079 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010080 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010081 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
10082 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
10083 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010084 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010085 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
10086 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
10087 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010088 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010089 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
10090 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
10091 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010092 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010093 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
10094 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
10095 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010096 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010097 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
10098 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
10099 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010100 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010101 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
10102 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
10103 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010104 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010105 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
10106 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
10107 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010108 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010109 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
10110 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
10111 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010112 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010113 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
10114 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
10115 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010116 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010117 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
10118 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
10119 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010120 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010121 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
10122 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
10123 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010124 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010125 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
10126 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
10127 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010128 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010129 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
10130 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
10131 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010132 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010133 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
10134 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
10135 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010136 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010137 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
10138 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
10139 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010140 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010141 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
10142 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
10143 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010144 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010145 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
10146 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
10147 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010148 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010149 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
10150 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
10151 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010152 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010153 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
10154 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
10155 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010156 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010157 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
10158 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
10159 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010160 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010161 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
10162 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
10163 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010164 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010165 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
10166 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
10167 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010168 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010169 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
10170 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
10171 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010172 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010173 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
10174 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
10175 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010176 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010177 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
10178 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
10179 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010180 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010181 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
10182 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
10183 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010184 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010185 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
10186 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
10187 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010188 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010189 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
10190 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
10191 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010192 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010193 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
10194 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
10195 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010196 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010197 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
10198 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
10199 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010200 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010201 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
10202 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
10203 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010204 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010205 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
10206 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
10207 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010208 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010209 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
10210 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
10211 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010212 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010213 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
10214 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
10215 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010216 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010217 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
10218 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
10219 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010220 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010221 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
10222 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
10223 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010224 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010225 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
10226 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
10227 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010228 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010229 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
10230 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
10231 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010232 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010233 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
10234 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
10235 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010236 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010237 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
10238 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
10239 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010240 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010241 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
10242 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
10243 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010244 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010245 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
10246 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
10247 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010248 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010249 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
10250 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
10251 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010252 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010253 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
10254 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
10255 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010256 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010257 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
10258 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
10259 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010260 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010261 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
10262 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
10263 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010264 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010265 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
10266 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
10267 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010268 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010269 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
10270 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
10271 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010272 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010273 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
10274 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
10275 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010276 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010277 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
10278 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
10279 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010280 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010281 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
10282 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
10283 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010284 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010285 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
10286 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
10287 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010288 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010289 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
10290 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
10291 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010292 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010293 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
10294 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
10295 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010296 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010297 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
10298 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
10299 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010300 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010301 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
10302 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
10303 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010304 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010305 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
10306 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
10307 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010308 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010309 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
10310 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
10311 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010312 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010313 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
10314 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
10315 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010316 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010317 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
10318 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
10319 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010320 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010321 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
10322 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10323 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010324 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010325 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10326 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
10327 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010328 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010329 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
10330 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
10331 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010332 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010333 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
10334 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
10335 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010336 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010337 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
10338 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
10339 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010340 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010341 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
10342 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
10343 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010344 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010345 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
10346 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
10347 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010348 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010349 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
10350 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
10351 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010352 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010353 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
10354 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
10355 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010356 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010357 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
10358 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
10359 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010360 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010361 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
10362 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
10363 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010364 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010365 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
10366 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
10367 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010368 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010369 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
10370 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
10371 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010372 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010373 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
10374 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
10375 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010376 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010377 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
10378 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
10379 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010380 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010381 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
10382 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
10383 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010384 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010385 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
10386 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
10387 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010388 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010389 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
10390 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
10391 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010392 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010393 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
10394 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
10395 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010396 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010397 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
10398 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
10399 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010400 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010401 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
10402 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
10403 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010404 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010405 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
10406 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
10407 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010408 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010409 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
10410 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
10411 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010412 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010413 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
10414 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
10415 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010416 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010417 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
10418 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
10419 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010420 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010421};
10422
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010423static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
10424static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010425
10426/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010427static unsigned char _adv_asc38C1600_buf[] = {
10428 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010429 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
10430 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
10431 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010432 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010433 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
10434 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
10435 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010436 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010437 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
10438 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
10439 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010440 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010441 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
10442 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
10443 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010444 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010445 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
10446 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
10447 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010448 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010449 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
10450 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
10451 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010452 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010453 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
10454 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
10455 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010456 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010457 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
10458 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
10459 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010460 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010461 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
10462 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
10463 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010464 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010465 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
10466 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
10467 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010468 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010469 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
10470 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
10471 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010472 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010473 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
10474 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10475 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010476 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010477 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
10478 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
10479 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010480 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010481 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
10482 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
10483 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010484 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010485 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
10486 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
10487 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010488 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010489 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
10490 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
10491 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010492 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010493 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
10494 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
10495 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010496 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010497 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
10498 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
10499 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010500 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010501 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
10502 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
10503 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010504 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010505 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
10506 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
10507 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010508 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010509 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
10510 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
10511 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010512 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010513 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
10514 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
10515 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010516 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010517 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
10518 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
10519 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010520 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010521 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
10522 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
10523 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010524 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010525 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
10526 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
10527 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010528 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010529 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
10530 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
10531 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010532 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010533 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
10534 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
10535 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010536 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010537 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
10538 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
10539 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010540 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010541 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
10542 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
10543 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010544 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010545 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
10546 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
10547 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010548 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010549 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
10550 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
10551 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010552 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010553 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
10554 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
10555 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010556 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010557 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
10558 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
10559 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010560 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010561 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
10562 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
10563 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010564 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010565 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
10566 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
10567 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010568 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010569 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
10570 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
10571 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010572 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010573 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
10574 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
10575 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010576 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010577 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
10578 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
10579 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010580 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010581 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
10582 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
10583 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010584 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010585 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
10586 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
10587 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010588 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010589 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
10590 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
10591 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010592 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010593 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
10594 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
10595 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010596 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010597 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
10598 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
10599 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010600 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010601 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
10602 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
10603 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010604 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010605 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
10606 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
10607 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010608 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010609 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
10610 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
10611 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010612 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010613 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
10614 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
10615 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010616 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010617 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
10618 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
10619 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010620 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010621 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
10622 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
10623 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010624 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010625 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
10626 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
10627 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010628 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010629 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
10630 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
10631 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010632 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010633 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
10634 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
10635 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010636 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010637 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
10638 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
10639 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010640 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010641 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
10642 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
10643 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010644 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010645 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
10646 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
10647 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010648 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010649 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
10650 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
10651 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010652 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010653 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
10654 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
10655 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010656 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010657 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
10658 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
10659 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010660 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010661 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
10662 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
10663 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010664 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010665 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
10666 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
10667 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010668 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010669 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
10670 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
10671 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010672 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010673 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
10674 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
10675 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010676 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010677 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
10678 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
10679 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010680 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010681 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
10682 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
10683 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010684 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010685 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
10686 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
10687 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010688 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010689 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
10690 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
10691 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010692 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010693 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
10694 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
10695 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010696 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010697 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
10698 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
10699 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010700 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010701 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
10702 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
10703 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010704 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010705 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
10706 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
10707 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010708 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010709 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
10710 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
10711 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010712 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010713 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
10714 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
10715 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010716 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010717 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
10718 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
10719 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010720 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010721 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
10722 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
10723 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010724 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010725 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
10726 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
10727 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010728 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010729 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
10730 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
10731 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010732 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010733 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
10734 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
10735 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010736 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010737 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
10738 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
10739 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010740 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010741 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
10742 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
10743 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010744 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010745 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
10746 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
10747 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010748 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010749 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
10750 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
10751 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010752 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010753 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
10754 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
10755 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010756 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010757 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
10758 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
10759 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010760 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010761 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
10762 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
10763 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010764 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010765 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
10766 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
10767 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010768 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010769 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
10770 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
10771 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010772 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010773 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
10774 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
10775 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010776 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010777 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
10778 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
10779 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010780 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010781 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
10782 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
10783 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010784 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010785 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
10786 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
10787 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010788 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010789 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
10790 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
10791 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010792 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010793 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
10794 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
10795 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010796 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010797 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
10798 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
10799 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010800 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010801 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
10802 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
10803 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010804 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010805 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
10806 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
10807 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010808 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010809 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
10810 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
10811 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010812 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010813 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
10814 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
10815 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010816 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010817 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
10818 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
10819 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010820 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010821 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
10822 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
10823 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010824 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010825 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
10826 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
10827 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010828 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010829 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
10830 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
10831 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010832 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010833 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
10834 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
10835 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010836 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010837 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
10838 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
10839 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010840 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010841 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
10842 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
10843 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010844 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010845 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
10846 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
10847 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010848 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010849 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
10850 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
10851 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010852 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010853 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
10854 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
10855 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010856 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010857 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
10858 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
10859 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010860 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010861 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
10862 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
10863 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010864 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010865 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
10866 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
10867 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010868 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010869 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
10870 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
10871 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010872 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010873 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
10874 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
10875 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010876 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010877 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
10878 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
10879 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010880 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010881 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
10882 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
10883 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010884 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010885 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
10886 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
10887 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010888 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010889 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
10890 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
10891 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010892 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010893 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
10894 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
10895 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010896 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010897 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
10898 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
10899 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010900 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010901 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
10902 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
10903 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010904 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010905 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
10906 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
10907 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010908 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010909 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
10910 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
10911 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010912 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010913 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
10914 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
10915 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010916 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010917 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
10918 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
10919 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010920 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010921 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
10922 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
10923 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010924 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010925 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
10926 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
10927 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010928 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010929 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
10930 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
10931 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010932 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010933 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
10934 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
10935 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010936 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010937 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
10938 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
10939 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010940 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010941 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
10942 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
10943 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010944 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010945 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
10946 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
10947 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010948 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010949 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
10950 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
10951 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010952 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010953 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
10954 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
10955 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010956};
10957
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010958static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
10959static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010960
Linus Torvalds1da177e2005-04-16 15:20:36 -070010961/*
10962 * EEPROM Configuration.
10963 *
10964 * All drivers should use this structure to set the default EEPROM
10965 * configuration. The BIOS now uses this structure when it is built.
10966 * Additional structure information can be found in a_condor.h where
10967 * the structure is defined.
10968 *
10969 * The *_Field_IsChar structs are needed to correct for endianness.
10970 * These values are read from the board 16 bits at a time directly
10971 * into the structs. Because some fields are char, the values will be
10972 * in the wrong order. The *_Field_IsChar tells when to flip the
10973 * bytes. Data read and written to PCI memory is automatically swapped
10974 * on big-endian platforms so char fields read as words are actually being
10975 * unswapped on big-endian platforms.
10976 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010977static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010978 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
10979 0x0000, /* cfg_msw */
10980 0xFFFF, /* disc_enable */
10981 0xFFFF, /* wdtr_able */
10982 0xFFFF, /* sdtr_able */
10983 0xFFFF, /* start_motor */
10984 0xFFFF, /* tagqng_able */
10985 0xFFFF, /* bios_scan */
10986 0, /* scam_tolerant */
10987 7, /* adapter_scsi_id */
10988 0, /* bios_boot_delay */
10989 3, /* scsi_reset_delay */
10990 0, /* bios_id_lun */
10991 0, /* termination */
10992 0, /* reserved1 */
10993 0xFFE7, /* bios_ctrl */
10994 0xFFFF, /* ultra_able */
10995 0, /* reserved2 */
10996 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
10997 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
10998 0, /* dvc_cntl */
10999 0, /* bug_fix */
11000 0, /* serial_number_word1 */
11001 0, /* serial_number_word2 */
11002 0, /* serial_number_word3 */
11003 0, /* check_sum */
11004 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11005 , /* oem_name[16] */
11006 0, /* dvc_err_code */
11007 0, /* adv_err_code */
11008 0, /* adv_err_addr */
11009 0, /* saved_dvc_err_code */
11010 0, /* saved_adv_err_code */
11011 0, /* saved_adv_err_addr */
11012 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011013};
11014
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011015static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011016 0, /* cfg_lsw */
11017 0, /* cfg_msw */
11018 0, /* -disc_enable */
11019 0, /* wdtr_able */
11020 0, /* sdtr_able */
11021 0, /* start_motor */
11022 0, /* tagqng_able */
11023 0, /* bios_scan */
11024 0, /* scam_tolerant */
11025 1, /* adapter_scsi_id */
11026 1, /* bios_boot_delay */
11027 1, /* scsi_reset_delay */
11028 1, /* bios_id_lun */
11029 1, /* termination */
11030 1, /* reserved1 */
11031 0, /* bios_ctrl */
11032 0, /* ultra_able */
11033 0, /* reserved2 */
11034 1, /* max_host_qng */
11035 1, /* max_dvc_qng */
11036 0, /* dvc_cntl */
11037 0, /* bug_fix */
11038 0, /* serial_number_word1 */
11039 0, /* serial_number_word2 */
11040 0, /* serial_number_word3 */
11041 0, /* check_sum */
11042 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11043 , /* oem_name[16] */
11044 0, /* dvc_err_code */
11045 0, /* adv_err_code */
11046 0, /* adv_err_addr */
11047 0, /* saved_dvc_err_code */
11048 0, /* saved_adv_err_code */
11049 0, /* saved_adv_err_addr */
11050 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011051};
11052
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011053static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011054 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11055 0x0000, /* 01 cfg_msw */
11056 0xFFFF, /* 02 disc_enable */
11057 0xFFFF, /* 03 wdtr_able */
11058 0x4444, /* 04 sdtr_speed1 */
11059 0xFFFF, /* 05 start_motor */
11060 0xFFFF, /* 06 tagqng_able */
11061 0xFFFF, /* 07 bios_scan */
11062 0, /* 08 scam_tolerant */
11063 7, /* 09 adapter_scsi_id */
11064 0, /* bios_boot_delay */
11065 3, /* 10 scsi_reset_delay */
11066 0, /* bios_id_lun */
11067 0, /* 11 termination_se */
11068 0, /* termination_lvd */
11069 0xFFE7, /* 12 bios_ctrl */
11070 0x4444, /* 13 sdtr_speed2 */
11071 0x4444, /* 14 sdtr_speed3 */
11072 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11073 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11074 0, /* 16 dvc_cntl */
11075 0x4444, /* 17 sdtr_speed4 */
11076 0, /* 18 serial_number_word1 */
11077 0, /* 19 serial_number_word2 */
11078 0, /* 20 serial_number_word3 */
11079 0, /* 21 check_sum */
11080 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11081 , /* 22-29 oem_name[16] */
11082 0, /* 30 dvc_err_code */
11083 0, /* 31 adv_err_code */
11084 0, /* 32 adv_err_addr */
11085 0, /* 33 saved_dvc_err_code */
11086 0, /* 34 saved_adv_err_code */
11087 0, /* 35 saved_adv_err_addr */
11088 0, /* 36 reserved */
11089 0, /* 37 reserved */
11090 0, /* 38 reserved */
11091 0, /* 39 reserved */
11092 0, /* 40 reserved */
11093 0, /* 41 reserved */
11094 0, /* 42 reserved */
11095 0, /* 43 reserved */
11096 0, /* 44 reserved */
11097 0, /* 45 reserved */
11098 0, /* 46 reserved */
11099 0, /* 47 reserved */
11100 0, /* 48 reserved */
11101 0, /* 49 reserved */
11102 0, /* 50 reserved */
11103 0, /* 51 reserved */
11104 0, /* 52 reserved */
11105 0, /* 53 reserved */
11106 0, /* 54 reserved */
11107 0, /* 55 reserved */
11108 0, /* 56 cisptr_lsw */
11109 0, /* 57 cisprt_msw */
11110 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11111 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
11112 0, /* 60 reserved */
11113 0, /* 61 reserved */
11114 0, /* 62 reserved */
11115 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011116};
11117
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011118static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011119 0, /* 00 cfg_lsw */
11120 0, /* 01 cfg_msw */
11121 0, /* 02 disc_enable */
11122 0, /* 03 wdtr_able */
11123 0, /* 04 sdtr_speed1 */
11124 0, /* 05 start_motor */
11125 0, /* 06 tagqng_able */
11126 0, /* 07 bios_scan */
11127 0, /* 08 scam_tolerant */
11128 1, /* 09 adapter_scsi_id */
11129 1, /* bios_boot_delay */
11130 1, /* 10 scsi_reset_delay */
11131 1, /* bios_id_lun */
11132 1, /* 11 termination_se */
11133 1, /* termination_lvd */
11134 0, /* 12 bios_ctrl */
11135 0, /* 13 sdtr_speed2 */
11136 0, /* 14 sdtr_speed3 */
11137 1, /* 15 max_host_qng */
11138 1, /* max_dvc_qng */
11139 0, /* 16 dvc_cntl */
11140 0, /* 17 sdtr_speed4 */
11141 0, /* 18 serial_number_word1 */
11142 0, /* 19 serial_number_word2 */
11143 0, /* 20 serial_number_word3 */
11144 0, /* 21 check_sum */
11145 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11146 , /* 22-29 oem_name[16] */
11147 0, /* 30 dvc_err_code */
11148 0, /* 31 adv_err_code */
11149 0, /* 32 adv_err_addr */
11150 0, /* 33 saved_dvc_err_code */
11151 0, /* 34 saved_adv_err_code */
11152 0, /* 35 saved_adv_err_addr */
11153 0, /* 36 reserved */
11154 0, /* 37 reserved */
11155 0, /* 38 reserved */
11156 0, /* 39 reserved */
11157 0, /* 40 reserved */
11158 0, /* 41 reserved */
11159 0, /* 42 reserved */
11160 0, /* 43 reserved */
11161 0, /* 44 reserved */
11162 0, /* 45 reserved */
11163 0, /* 46 reserved */
11164 0, /* 47 reserved */
11165 0, /* 48 reserved */
11166 0, /* 49 reserved */
11167 0, /* 50 reserved */
11168 0, /* 51 reserved */
11169 0, /* 52 reserved */
11170 0, /* 53 reserved */
11171 0, /* 54 reserved */
11172 0, /* 55 reserved */
11173 0, /* 56 cisptr_lsw */
11174 0, /* 57 cisprt_msw */
11175 0, /* 58 subsysvid */
11176 0, /* 59 subsysid */
11177 0, /* 60 reserved */
11178 0, /* 61 reserved */
11179 0, /* 62 reserved */
11180 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011181};
11182
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011183static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011184 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11185 0x0000, /* 01 cfg_msw */
11186 0xFFFF, /* 02 disc_enable */
11187 0xFFFF, /* 03 wdtr_able */
11188 0x5555, /* 04 sdtr_speed1 */
11189 0xFFFF, /* 05 start_motor */
11190 0xFFFF, /* 06 tagqng_able */
11191 0xFFFF, /* 07 bios_scan */
11192 0, /* 08 scam_tolerant */
11193 7, /* 09 adapter_scsi_id */
11194 0, /* bios_boot_delay */
11195 3, /* 10 scsi_reset_delay */
11196 0, /* bios_id_lun */
11197 0, /* 11 termination_se */
11198 0, /* termination_lvd */
11199 0xFFE7, /* 12 bios_ctrl */
11200 0x5555, /* 13 sdtr_speed2 */
11201 0x5555, /* 14 sdtr_speed3 */
11202 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11203 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11204 0, /* 16 dvc_cntl */
11205 0x5555, /* 17 sdtr_speed4 */
11206 0, /* 18 serial_number_word1 */
11207 0, /* 19 serial_number_word2 */
11208 0, /* 20 serial_number_word3 */
11209 0, /* 21 check_sum */
11210 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11211 , /* 22-29 oem_name[16] */
11212 0, /* 30 dvc_err_code */
11213 0, /* 31 adv_err_code */
11214 0, /* 32 adv_err_addr */
11215 0, /* 33 saved_dvc_err_code */
11216 0, /* 34 saved_adv_err_code */
11217 0, /* 35 saved_adv_err_addr */
11218 0, /* 36 reserved */
11219 0, /* 37 reserved */
11220 0, /* 38 reserved */
11221 0, /* 39 reserved */
11222 0, /* 40 reserved */
11223 0, /* 41 reserved */
11224 0, /* 42 reserved */
11225 0, /* 43 reserved */
11226 0, /* 44 reserved */
11227 0, /* 45 reserved */
11228 0, /* 46 reserved */
11229 0, /* 47 reserved */
11230 0, /* 48 reserved */
11231 0, /* 49 reserved */
11232 0, /* 50 reserved */
11233 0, /* 51 reserved */
11234 0, /* 52 reserved */
11235 0, /* 53 reserved */
11236 0, /* 54 reserved */
11237 0, /* 55 reserved */
11238 0, /* 56 cisptr_lsw */
11239 0, /* 57 cisprt_msw */
11240 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11241 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
11242 0, /* 60 reserved */
11243 0, /* 61 reserved */
11244 0, /* 62 reserved */
11245 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011246};
11247
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011248static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011249 0, /* 00 cfg_lsw */
11250 0, /* 01 cfg_msw */
11251 0, /* 02 disc_enable */
11252 0, /* 03 wdtr_able */
11253 0, /* 04 sdtr_speed1 */
11254 0, /* 05 start_motor */
11255 0, /* 06 tagqng_able */
11256 0, /* 07 bios_scan */
11257 0, /* 08 scam_tolerant */
11258 1, /* 09 adapter_scsi_id */
11259 1, /* bios_boot_delay */
11260 1, /* 10 scsi_reset_delay */
11261 1, /* bios_id_lun */
11262 1, /* 11 termination_se */
11263 1, /* termination_lvd */
11264 0, /* 12 bios_ctrl */
11265 0, /* 13 sdtr_speed2 */
11266 0, /* 14 sdtr_speed3 */
11267 1, /* 15 max_host_qng */
11268 1, /* max_dvc_qng */
11269 0, /* 16 dvc_cntl */
11270 0, /* 17 sdtr_speed4 */
11271 0, /* 18 serial_number_word1 */
11272 0, /* 19 serial_number_word2 */
11273 0, /* 20 serial_number_word3 */
11274 0, /* 21 check_sum */
11275 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11276 , /* 22-29 oem_name[16] */
11277 0, /* 30 dvc_err_code */
11278 0, /* 31 adv_err_code */
11279 0, /* 32 adv_err_addr */
11280 0, /* 33 saved_dvc_err_code */
11281 0, /* 34 saved_adv_err_code */
11282 0, /* 35 saved_adv_err_addr */
11283 0, /* 36 reserved */
11284 0, /* 37 reserved */
11285 0, /* 38 reserved */
11286 0, /* 39 reserved */
11287 0, /* 40 reserved */
11288 0, /* 41 reserved */
11289 0, /* 42 reserved */
11290 0, /* 43 reserved */
11291 0, /* 44 reserved */
11292 0, /* 45 reserved */
11293 0, /* 46 reserved */
11294 0, /* 47 reserved */
11295 0, /* 48 reserved */
11296 0, /* 49 reserved */
11297 0, /* 50 reserved */
11298 0, /* 51 reserved */
11299 0, /* 52 reserved */
11300 0, /* 53 reserved */
11301 0, /* 54 reserved */
11302 0, /* 55 reserved */
11303 0, /* 56 cisptr_lsw */
11304 0, /* 57 cisprt_msw */
11305 0, /* 58 subsysvid */
11306 0, /* 59 subsysid */
11307 0, /* 60 reserved */
11308 0, /* 61 reserved */
11309 0, /* 62 reserved */
11310 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011311};
11312
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011313#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -070011314/*
11315 * Initialize the ADV_DVC_VAR structure.
11316 *
11317 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11318 *
11319 * For a non-fatal error return a warning code. If there are no warnings
11320 * then 0 is returned.
11321 */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040011322static int __devinit
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011323AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011324{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011325 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011326 unsigned short warn_code = 0;
11327 AdvPortAddr iop_base = asc_dvc->iop_base;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011328 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011329 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011330
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011331 asc_dvc->err_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011332
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011333 /*
11334 * Save the state of the PCI Configuration Command Register
11335 * "Parity Error Response Control" Bit. If the bit is clear (0),
11336 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
11337 * DMA parity errors.
11338 */
11339 asc_dvc->cfg->control_flag = 0;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011340 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
11341 if ((cmd & PCI_COMMAND_PARITY) == 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011342 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011343
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011344 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
11345 ADV_LIB_VERSION_MINOR;
11346 asc_dvc->cfg->chip_version =
11347 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011348
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011349 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
11350 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
11351 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011352
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011353 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
11354 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
11355 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011356
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011357 /*
11358 * Reset the chip to start and allow register writes.
11359 */
11360 if (AdvFindSignature(iop_base) == 0) {
11361 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11362 return ADV_ERROR;
11363 } else {
11364 /*
11365 * The caller must set 'chip_type' to a valid setting.
11366 */
11367 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
11368 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
11369 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
11370 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
11371 return ADV_ERROR;
11372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011374 /*
11375 * Reset Chip.
11376 */
11377 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11378 ADV_CTRL_REG_CMD_RESET);
11379 DvcSleepMilliSecond(100);
11380 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11381 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011382
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011383 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011384 status = AdvInitFrom38C1600EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011385 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011386 status = AdvInitFrom38C0800EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011387 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011388 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011389 }
11390 warn_code |= status;
11391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011392
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011393 if (warn_code != 0) {
11394 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
11395 boardp->id, warn_code);
11396 }
11397
11398 if (asc_dvc->err_code) {
11399 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
11400 boardp->id, asc_dvc->err_code);
11401 }
11402
11403 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011404}
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011405#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070011406
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011407static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
11408{
11409 ADV_CARR_T *carrp;
11410 ADV_SDCNT buf_size;
11411 ADV_PADDR carr_paddr;
11412
11413 BUG_ON(!asc_dvc->carrier_buf);
11414
11415 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
11416 asc_dvc->carr_freelist = NULL;
11417 if (carrp == asc_dvc->carrier_buf) {
11418 buf_size = ADV_CARRIER_BUFSIZE;
11419 } else {
11420 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
11421 }
11422
11423 do {
11424 /* Get physical address of the carrier 'carrp'. */
11425 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
11426 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
11427 (uchar *)carrp,
11428 (ADV_SDCNT *)&contig_len,
11429 ADV_IS_CARRIER_FLAG));
11430
11431 buf_size -= sizeof(ADV_CARR_T);
11432
11433 /*
11434 * If the current carrier is not physically contiguous, then
11435 * maybe there was a page crossing. Try the next carrier
11436 * aligned start address.
11437 */
11438 if (contig_len < sizeof(ADV_CARR_T)) {
11439 carrp++;
11440 continue;
11441 }
11442
11443 carrp->carr_pa = carr_paddr;
11444 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
11445
11446 /*
11447 * Insert the carrier at the beginning of the freelist.
11448 */
11449 carrp->next_vpa =
11450 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
11451 asc_dvc->carr_freelist = carrp;
11452
11453 carrp++;
11454 } while (buf_size > 0);
11455}
11456
Linus Torvalds1da177e2005-04-16 15:20:36 -070011457/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011458 * Load the Microcode
11459 *
11460 * Write the microcode image to RISC memory starting at address 0.
11461 *
11462 * The microcode is stored compressed in the following format:
11463 *
11464 * 254 word (508 byte) table indexed by byte code followed
11465 * by the following byte codes:
11466 *
11467 * 1-Byte Code:
11468 * 00: Emit word 0 in table.
11469 * 01: Emit word 1 in table.
11470 * .
11471 * FD: Emit word 253 in table.
11472 *
11473 * Multi-Byte Code:
11474 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
11475 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
11476 *
11477 * Returns 0 or an error if the checksum doesn't match
11478 */
11479static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
11480 int memsize, int chksum)
11481{
11482 int i, j, end, len = 0;
11483 ADV_DCNT sum;
11484
11485 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11486
11487 for (i = 253 * 2; i < size; i++) {
11488 if (buf[i] == 0xff) {
11489 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
11490 for (j = 0; j < buf[i + 1]; j++) {
11491 AdvWriteWordAutoIncLram(iop_base, word);
11492 len += 2;
11493 }
11494 i += 3;
11495 } else if (buf[i] == 0xfe) {
11496 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
11497 AdvWriteWordAutoIncLram(iop_base, word);
11498 i += 2;
11499 len += 2;
11500 } else {
11501 unsigned char off = buf[i] * 2;
11502 unsigned short word = (buf[off + 1] << 8) | buf[off];
11503 AdvWriteWordAutoIncLram(iop_base, word);
11504 len += 2;
11505 }
11506 }
11507
11508 end = len;
11509
11510 while (len < memsize) {
11511 AdvWriteWordAutoIncLram(iop_base, 0);
11512 len += 2;
11513 }
11514
11515 /* Verify the microcode checksum. */
11516 sum = 0;
11517 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11518
11519 for (len = 0; len < end; len += 2) {
11520 sum += AdvReadWordAutoIncLram(iop_base);
11521 }
11522
11523 if (sum != chksum)
11524 return ASC_IERR_MCODE_CHKSUM;
11525
11526 return 0;
11527}
11528
11529/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070011530 * Initialize the ASC-3550.
11531 *
11532 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11533 *
11534 * For a non-fatal error return a warning code. If there are no warnings
11535 * then 0 is returned.
11536 *
11537 * Needed after initialization for error recovery.
11538 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011539static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011540{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011541 AdvPortAddr iop_base;
11542 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011543 int begin_addr;
11544 int end_addr;
11545 ushort code_sum;
11546 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011547 int i;
11548 ushort scsi_cfg1;
11549 uchar tid;
11550 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
11551 ushort wdtr_able = 0, sdtr_able, tagqng_able;
11552 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070011553
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011554 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011555 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011556 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011557
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011558 /*
11559 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
11560 */
11561 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011562 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011563 return ADV_ERROR;
11564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011565
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011566 warn_code = 0;
11567 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011568
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011569 /*
11570 * Save the RISC memory BIOS region before writing the microcode.
11571 * The BIOS may already be loaded and using its RISC LRAM region
11572 * so its region must be saved and restored.
11573 *
11574 * Note: This code makes the assumption, which is currently true,
11575 * that a chip reset does not clear RISC LRAM.
11576 */
11577 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11578 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11579 bios_mem[i]);
11580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011581
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011582 /*
11583 * Save current per TID negotiated values.
11584 */
11585 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
11586 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011588 bios_version =
11589 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
11590 major = (bios_version >> 12) & 0xF;
11591 minor = (bios_version >> 8) & 0xF;
11592 if (major < 3 || (major == 3 && minor == 1)) {
11593 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
11594 AdvReadWordLram(iop_base, 0x120, wdtr_able);
11595 } else {
11596 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11597 }
11598 }
11599 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11600 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
11601 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11602 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
11603 max_cmd[tid]);
11604 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011605
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011606 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
11607 _adv_asc3550_size, ADV_3550_MEMSIZE,
11608 _adv_asc3550_chksum);
11609 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011610 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011611
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011612 /*
11613 * Restore the RISC memory BIOS region.
11614 */
11615 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11616 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11617 bios_mem[i]);
11618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011619
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011620 /*
11621 * Calculate and write the microcode code checksum to the microcode
11622 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
11623 */
11624 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
11625 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
11626 code_sum = 0;
11627 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
11628 for (word = begin_addr; word < end_addr; word += 2) {
11629 code_sum += AdvReadWordAutoIncLram(iop_base);
11630 }
11631 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011632
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011633 /*
11634 * Read and save microcode version and date.
11635 */
11636 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
11637 asc_dvc->cfg->mcode_date);
11638 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
11639 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011641 /*
11642 * Set the chip type to indicate the ASC3550.
11643 */
11644 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011645
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011646 /*
11647 * If the PCI Configuration Command Register "Parity Error Response
11648 * Control" Bit was clear (0), then set the microcode variable
11649 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
11650 * to ignore DMA parity errors.
11651 */
11652 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
11653 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11654 word |= CONTROL_FLAG_IGNORE_PERR;
11655 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011657
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011658 /*
11659 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
11660 * threshold of 128 bytes. This register is only accessible to the host.
11661 */
11662 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
11663 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011664
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011665 /*
11666 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040011667 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011668 * device reports it is capable of in Inquiry byte 7.
11669 *
11670 * If SCSI Bus Resets have been disabled, then directly set
11671 * SDTR and WDTR from the EEPROM configuration. This will allow
11672 * the BIOS and warm boot to work without a SCSI bus hang on
11673 * the Inquiry caused by host and target mismatched DTR values.
11674 * Without the SCSI Bus Reset, before an Inquiry a device can't
11675 * be assumed to be in Asynchronous, Narrow mode.
11676 */
11677 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
11678 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
11679 asc_dvc->wdtr_able);
11680 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
11681 asc_dvc->sdtr_able);
11682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011683
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011684 /*
11685 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
11686 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
11687 * bitmask. These values determine the maximum SDTR speed negotiated
11688 * with a device.
11689 *
11690 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
11691 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
11692 * without determining here whether the device supports SDTR.
11693 *
11694 * 4-bit speed SDTR speed name
11695 * =========== ===============
11696 * 0000b (0x0) SDTR disabled
11697 * 0001b (0x1) 5 Mhz
11698 * 0010b (0x2) 10 Mhz
11699 * 0011b (0x3) 20 Mhz (Ultra)
11700 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
11701 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
11702 * 0110b (0x6) Undefined
11703 * .
11704 * 1111b (0xF) Undefined
11705 */
11706 word = 0;
11707 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11708 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
11709 /* Set Ultra speed for TID 'tid'. */
11710 word |= (0x3 << (4 * (tid % 4)));
11711 } else {
11712 /* Set Fast speed for TID 'tid'. */
11713 word |= (0x2 << (4 * (tid % 4)));
11714 }
11715 if (tid == 3) { /* Check if done with sdtr_speed1. */
11716 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
11717 word = 0;
11718 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
11719 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
11720 word = 0;
11721 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
11722 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
11723 word = 0;
11724 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
11725 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
11726 /* End of loop. */
11727 }
11728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011729
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011730 /*
11731 * Set microcode operating variable for the disconnect per TID bitmask.
11732 */
11733 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
11734 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011735
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011736 /*
11737 * Set SCSI_CFG0 Microcode Default Value.
11738 *
11739 * The microcode will set the SCSI_CFG0 register using this value
11740 * after it is started below.
11741 */
11742 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
11743 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
11744 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011745
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011746 /*
11747 * Determine SCSI_CFG1 Microcode Default Value.
11748 *
11749 * The microcode will set the SCSI_CFG1 register using this value
11750 * after it is started below.
11751 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011752
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011753 /* Read current SCSI_CFG1 Register value. */
11754 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011755
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011756 /*
11757 * If all three connectors are in use, return an error.
11758 */
11759 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
11760 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
11761 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
11762 return ADV_ERROR;
11763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011764
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011765 /*
11766 * If the internal narrow cable is reversed all of the SCSI_CTRL
11767 * register signals will be set. Check for and return an error if
11768 * this condition is found.
11769 */
11770 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
11771 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
11772 return ADV_ERROR;
11773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011774
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011775 /*
11776 * If this is a differential board and a single-ended device
11777 * is attached to one of the connectors, return an error.
11778 */
11779 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
11780 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
11781 return ADV_ERROR;
11782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011783
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011784 /*
11785 * If automatic termination control is enabled, then set the
11786 * termination value based on a table listed in a_condor.h.
11787 *
11788 * If manual termination was specified with an EEPROM setting
11789 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
11790 * is ready to be 'ored' into SCSI_CFG1.
11791 */
11792 if (asc_dvc->cfg->termination == 0) {
11793 /*
11794 * The software always controls termination by setting TERM_CTL_SEL.
11795 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
11796 */
11797 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011798
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011799 switch (scsi_cfg1 & CABLE_DETECT) {
11800 /* TERM_CTL_H: on, TERM_CTL_L: on */
11801 case 0x3:
11802 case 0x7:
11803 case 0xB:
11804 case 0xD:
11805 case 0xE:
11806 case 0xF:
11807 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
11808 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011809
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011810 /* TERM_CTL_H: on, TERM_CTL_L: off */
11811 case 0x1:
11812 case 0x5:
11813 case 0x9:
11814 case 0xA:
11815 case 0xC:
11816 asc_dvc->cfg->termination |= TERM_CTL_H;
11817 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011818
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011819 /* TERM_CTL_H: off, TERM_CTL_L: off */
11820 case 0x2:
11821 case 0x6:
11822 break;
11823 }
11824 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011825
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011826 /*
11827 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
11828 */
11829 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011831 /*
11832 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
11833 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
11834 * referenced, because the hardware internally inverts
11835 * the Termination High and Low bits if TERM_POL is set.
11836 */
11837 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011838
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011839 /*
11840 * Set SCSI_CFG1 Microcode Default Value
11841 *
11842 * Set filter value and possibly modified termination control
11843 * bits in the Microcode SCSI_CFG1 Register Value.
11844 *
11845 * The microcode will set the SCSI_CFG1 register using this value
11846 * after it is started below.
11847 */
11848 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
11849 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011850
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011851 /*
11852 * Set MEM_CFG Microcode Default Value
11853 *
11854 * The microcode will set the MEM_CFG register using this value
11855 * after it is started below.
11856 *
11857 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
11858 * are defined.
11859 *
11860 * ASC-3550 has 8KB internal memory.
11861 */
11862 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
11863 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011864
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011865 /*
11866 * Set SEL_MASK Microcode Default Value
11867 *
11868 * The microcode will set the SEL_MASK register using this value
11869 * after it is started below.
11870 */
11871 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
11872 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011873
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011874 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011875
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011876 /*
11877 * Set-up the Host->RISC Initiator Command Queue (ICQ).
11878 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011879
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011880 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
11881 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11882 return ADV_ERROR;
11883 }
11884 asc_dvc->carr_freelist = (ADV_CARR_T *)
11885 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011887 /*
11888 * The first command issued will be placed in the stopper carrier.
11889 */
11890 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011891
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011892 /*
11893 * Set RISC ICQ physical address start value.
11894 */
11895 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011897 /*
11898 * Set-up the RISC->Host Initiator Response Queue (IRQ).
11899 */
11900 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
11901 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11902 return ADV_ERROR;
11903 }
11904 asc_dvc->carr_freelist = (ADV_CARR_T *)
11905 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011906
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011907 /*
11908 * The first command completed by the RISC will be placed in
11909 * the stopper.
11910 *
11911 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
11912 * completed the RISC will set the ASC_RQ_STOPPER bit.
11913 */
11914 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011915
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011916 /*
11917 * Set RISC IRQ physical address start value.
11918 */
11919 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
11920 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011921
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011922 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
11923 (ADV_INTR_ENABLE_HOST_INTR |
11924 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011925
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011926 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
11927 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011928
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011929 /* finally, finally, gentlemen, start your engine */
11930 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011931
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011932 /*
11933 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
11934 * Resets should be performed. The RISC has to be running
11935 * to issue a SCSI Bus Reset.
11936 */
11937 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
11938 /*
11939 * If the BIOS Signature is present in memory, restore the
11940 * BIOS Handshake Configuration Table and do not perform
11941 * a SCSI Bus Reset.
11942 */
11943 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
11944 0x55AA) {
11945 /*
11946 * Restore per TID negotiated values.
11947 */
11948 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11949 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11950 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
11951 tagqng_able);
11952 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11953 AdvWriteByteLram(iop_base,
11954 ASC_MC_NUMBER_OF_MAX_CMD + tid,
11955 max_cmd[tid]);
11956 }
11957 } else {
11958 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
11959 warn_code = ASC_WARN_BUSRESET_ERROR;
11960 }
11961 }
11962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011963
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011964 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011965}
11966
11967/*
11968 * Initialize the ASC-38C0800.
11969 *
11970 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11971 *
11972 * For a non-fatal error return a warning code. If there are no warnings
11973 * then 0 is returned.
11974 *
11975 * Needed after initialization for error recovery.
11976 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011977static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011978{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011979 AdvPortAddr iop_base;
11980 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011981 int begin_addr;
11982 int end_addr;
11983 ushort code_sum;
11984 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011985 int i;
11986 ushort scsi_cfg1;
11987 uchar byte;
11988 uchar tid;
11989 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
11990 ushort wdtr_able, sdtr_able, tagqng_able;
11991 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070011992
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011993 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011994 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011995 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011996
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011997 /*
11998 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
11999 */
12000 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
12001 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12002 return ADV_ERROR;
12003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012004
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012005 warn_code = 0;
12006 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012007
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012008 /*
12009 * Save the RISC memory BIOS region before writing the microcode.
12010 * The BIOS may already be loaded and using its RISC LRAM region
12011 * so its region must be saved and restored.
12012 *
12013 * Note: This code makes the assumption, which is currently true,
12014 * that a chip reset does not clear RISC LRAM.
12015 */
12016 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12017 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12018 bios_mem[i]);
12019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012020
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012021 /*
12022 * Save current per TID negotiated values.
12023 */
12024 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12025 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12026 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12027 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12028 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12029 max_cmd[tid]);
12030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012031
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012032 /*
12033 * RAM BIST (RAM Built-In Self Test)
12034 *
12035 * Address : I/O base + offset 0x38h register (byte).
12036 * Function: Bit 7-6(RW) : RAM mode
12037 * Normal Mode : 0x00
12038 * Pre-test Mode : 0x40
12039 * RAM Test Mode : 0x80
12040 * Bit 5 : unused
12041 * Bit 4(RO) : Done bit
12042 * Bit 3-0(RO) : Status
12043 * Host Error : 0x08
12044 * Int_RAM Error : 0x04
12045 * RISC Error : 0x02
12046 * SCSI Error : 0x01
12047 * No Error : 0x00
12048 *
12049 * Note: RAM BIST code should be put right here, before loading the
12050 * microcode and after saving the RISC memory BIOS region.
12051 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012052
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012053 /*
12054 * LRAM Pre-test
12055 *
12056 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12057 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12058 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12059 * to NORMAL_MODE, return an error too.
12060 */
12061 for (i = 0; i < 2; i++) {
12062 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12063 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12064 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12065 if ((byte & RAM_TEST_DONE) == 0
12066 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012067 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012068 return ADV_ERROR;
12069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012071 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12072 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12073 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12074 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012075 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012076 return ADV_ERROR;
12077 }
12078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012080 /*
12081 * LRAM Test - It takes about 1.5 ms to run through the test.
12082 *
12083 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12084 * If Done bit not set or Status not 0, save register byte, set the
12085 * err_code, and return an error.
12086 */
12087 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12088 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012089
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012090 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12091 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12092 /* Get here if Done bit not set or Status not 0. */
12093 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012094 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012095 return ADV_ERROR;
12096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012097
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012098 /* We need to reset back to normal mode after LRAM test passes. */
12099 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012100
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012101 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
12102 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
12103 _adv_asc38C0800_chksum);
12104 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012105 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012106
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012107 /*
12108 * Restore the RISC memory BIOS region.
12109 */
12110 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12111 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12112 bios_mem[i]);
12113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012114
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012115 /*
12116 * Calculate and write the microcode code checksum to the microcode
12117 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12118 */
12119 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12120 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12121 code_sum = 0;
12122 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12123 for (word = begin_addr; word < end_addr; word += 2) {
12124 code_sum += AdvReadWordAutoIncLram(iop_base);
12125 }
12126 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012127
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012128 /*
12129 * Read microcode version and date.
12130 */
12131 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12132 asc_dvc->cfg->mcode_date);
12133 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12134 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012135
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012136 /*
12137 * Set the chip type to indicate the ASC38C0800.
12138 */
12139 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012140
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012141 /*
12142 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12143 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12144 * cable detection and then we are able to read C_DET[3:0].
12145 *
12146 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12147 * Microcode Default Value' section below.
12148 */
12149 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12150 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12151 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012152
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012153 /*
12154 * If the PCI Configuration Command Register "Parity Error Response
12155 * Control" Bit was clear (0), then set the microcode variable
12156 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12157 * to ignore DMA parity errors.
12158 */
12159 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12160 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12161 word |= CONTROL_FLAG_IGNORE_PERR;
12162 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012164
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012165 /*
12166 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
12167 * bits for the default FIFO threshold.
12168 *
12169 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
12170 *
12171 * For DMA Errata #4 set the BC_THRESH_ENB bit.
12172 */
12173 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12174 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
12175 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012176
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012177 /*
12178 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012179 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012180 * device reports it is capable of in Inquiry byte 7.
12181 *
12182 * If SCSI Bus Resets have been disabled, then directly set
12183 * SDTR and WDTR from the EEPROM configuration. This will allow
12184 * the BIOS and warm boot to work without a SCSI bus hang on
12185 * the Inquiry caused by host and target mismatched DTR values.
12186 * Without the SCSI Bus Reset, before an Inquiry a device can't
12187 * be assumed to be in Asynchronous, Narrow mode.
12188 */
12189 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12190 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12191 asc_dvc->wdtr_able);
12192 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12193 asc_dvc->sdtr_able);
12194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012195
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012196 /*
12197 * Set microcode operating variables for DISC and SDTR_SPEED1,
12198 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12199 * configuration values.
12200 *
12201 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12202 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12203 * without determining here whether the device supports SDTR.
12204 */
12205 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12206 asc_dvc->cfg->disc_enable);
12207 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12208 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12209 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12210 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012211
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012212 /*
12213 * Set SCSI_CFG0 Microcode Default Value.
12214 *
12215 * The microcode will set the SCSI_CFG0 register using this value
12216 * after it is started below.
12217 */
12218 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12219 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12220 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012221
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012222 /*
12223 * Determine SCSI_CFG1 Microcode Default Value.
12224 *
12225 * The microcode will set the SCSI_CFG1 register using this value
12226 * after it is started below.
12227 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012228
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012229 /* Read current SCSI_CFG1 Register value. */
12230 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012231
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012232 /*
12233 * If the internal narrow cable is reversed all of the SCSI_CTRL
12234 * register signals will be set. Check for and return an error if
12235 * this condition is found.
12236 */
12237 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12238 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12239 return ADV_ERROR;
12240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012241
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012242 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012243 * All kind of combinations of devices attached to one of four
12244 * connectors are acceptable except HVD device attached. For example,
12245 * LVD device can be attached to SE connector while SE device attached
12246 * to LVD connector. If LVD device attached to SE connector, it only
12247 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012248 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012249 * If an HVD device is attached to one of LVD connectors, return an
12250 * error. However, there is no way to detect HVD device attached to
12251 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012252 */
12253 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012254 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012255 return ADV_ERROR;
12256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012257
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012258 /*
12259 * If either SE or LVD automatic termination control is enabled, then
12260 * set the termination value based on a table listed in a_condor.h.
12261 *
12262 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012263 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
12264 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012265 */
12266 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
12267 /* SE automatic termination control is enabled. */
12268 switch (scsi_cfg1 & C_DET_SE) {
12269 /* TERM_SE_HI: on, TERM_SE_LO: on */
12270 case 0x1:
12271 case 0x2:
12272 case 0x3:
12273 asc_dvc->cfg->termination |= TERM_SE;
12274 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012275
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012276 /* TERM_SE_HI: on, TERM_SE_LO: off */
12277 case 0x0:
12278 asc_dvc->cfg->termination |= TERM_SE_HI;
12279 break;
12280 }
12281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012282
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012283 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
12284 /* LVD automatic termination control is enabled. */
12285 switch (scsi_cfg1 & C_DET_LVD) {
12286 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
12287 case 0x4:
12288 case 0x8:
12289 case 0xC:
12290 asc_dvc->cfg->termination |= TERM_LVD;
12291 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012292
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012293 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
12294 case 0x0:
12295 break;
12296 }
12297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012298
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012299 /*
12300 * Clear any set TERM_SE and TERM_LVD bits.
12301 */
12302 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012303
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012304 /*
12305 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
12306 */
12307 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012308
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012309 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012310 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
12311 * bits and set possibly modified termination control bits in the
12312 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012313 */
12314 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012315
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012316 /*
12317 * Set SCSI_CFG1 Microcode Default Value
12318 *
12319 * Set possibly modified termination control and reset DIS_TERM_DRV
12320 * bits in the Microcode SCSI_CFG1 Register Value.
12321 *
12322 * The microcode will set the SCSI_CFG1 register using this value
12323 * after it is started below.
12324 */
12325 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012326
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012327 /*
12328 * Set MEM_CFG Microcode Default Value
12329 *
12330 * The microcode will set the MEM_CFG register using this value
12331 * after it is started below.
12332 *
12333 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12334 * are defined.
12335 *
12336 * ASC-38C0800 has 16KB internal memory.
12337 */
12338 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12339 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012340
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012341 /*
12342 * Set SEL_MASK Microcode Default Value
12343 *
12344 * The microcode will set the SEL_MASK register using this value
12345 * after it is started below.
12346 */
12347 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12348 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012349
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012350 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012351
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012352 /*
12353 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12354 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012355
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012356 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12357 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12358 return ADV_ERROR;
12359 }
12360 asc_dvc->carr_freelist = (ADV_CARR_T *)
12361 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012362
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012363 /*
12364 * The first command issued will be placed in the stopper carrier.
12365 */
12366 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012367
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012368 /*
12369 * Set RISC ICQ physical address start value.
12370 * carr_pa is LE, must be native before write
12371 */
12372 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012374 /*
12375 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12376 */
12377 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12378 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12379 return ADV_ERROR;
12380 }
12381 asc_dvc->carr_freelist = (ADV_CARR_T *)
12382 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012383
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012384 /*
12385 * The first command completed by the RISC will be placed in
12386 * the stopper.
12387 *
12388 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12389 * completed the RISC will set the ASC_RQ_STOPPER bit.
12390 */
12391 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012392
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012393 /*
12394 * Set RISC IRQ physical address start value.
12395 *
12396 * carr_pa is LE, must be native before write *
12397 */
12398 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12399 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012400
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012401 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12402 (ADV_INTR_ENABLE_HOST_INTR |
12403 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012404
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012405 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12406 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012407
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012408 /* finally, finally, gentlemen, start your engine */
12409 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012410
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012411 /*
12412 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12413 * Resets should be performed. The RISC has to be running
12414 * to issue a SCSI Bus Reset.
12415 */
12416 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12417 /*
12418 * If the BIOS Signature is present in memory, restore the
12419 * BIOS Handshake Configuration Table and do not perform
12420 * a SCSI Bus Reset.
12421 */
12422 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12423 0x55AA) {
12424 /*
12425 * Restore per TID negotiated values.
12426 */
12427 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12428 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12429 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12430 tagqng_able);
12431 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12432 AdvWriteByteLram(iop_base,
12433 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12434 max_cmd[tid]);
12435 }
12436 } else {
12437 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12438 warn_code = ASC_WARN_BUSRESET_ERROR;
12439 }
12440 }
12441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012442
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012443 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012444}
12445
12446/*
12447 * Initialize the ASC-38C1600.
12448 *
12449 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
12450 *
12451 * For a non-fatal error return a warning code. If there are no warnings
12452 * then 0 is returned.
12453 *
12454 * Needed after initialization for error recovery.
12455 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012456static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012457{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012458 AdvPortAddr iop_base;
12459 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012460 int begin_addr;
12461 int end_addr;
12462 ushort code_sum;
12463 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012464 int i;
12465 ushort scsi_cfg1;
12466 uchar byte;
12467 uchar tid;
12468 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12469 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
12470 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012471
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012472 /* If there is already an error, don't continue. */
12473 if (asc_dvc->err_code != 0) {
12474 return ADV_ERROR;
12475 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012476
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012477 /*
12478 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
12479 */
12480 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
12481 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12482 return ADV_ERROR;
12483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012484
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012485 warn_code = 0;
12486 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012487
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012488 /*
12489 * Save the RISC memory BIOS region before writing the microcode.
12490 * The BIOS may already be loaded and using its RISC LRAM region
12491 * so its region must be saved and restored.
12492 *
12493 * Note: This code makes the assumption, which is currently true,
12494 * that a chip reset does not clear RISC LRAM.
12495 */
12496 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12497 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12498 bios_mem[i]);
12499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012500
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012501 /*
12502 * Save current per TID negotiated values.
12503 */
12504 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12505 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12506 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12507 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12508 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12509 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12510 max_cmd[tid]);
12511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012512
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012513 /*
12514 * RAM BIST (Built-In Self Test)
12515 *
12516 * Address : I/O base + offset 0x38h register (byte).
12517 * Function: Bit 7-6(RW) : RAM mode
12518 * Normal Mode : 0x00
12519 * Pre-test Mode : 0x40
12520 * RAM Test Mode : 0x80
12521 * Bit 5 : unused
12522 * Bit 4(RO) : Done bit
12523 * Bit 3-0(RO) : Status
12524 * Host Error : 0x08
12525 * Int_RAM Error : 0x04
12526 * RISC Error : 0x02
12527 * SCSI Error : 0x01
12528 * No Error : 0x00
12529 *
12530 * Note: RAM BIST code should be put right here, before loading the
12531 * microcode and after saving the RISC memory BIOS region.
12532 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012533
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012534 /*
12535 * LRAM Pre-test
12536 *
12537 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12538 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12539 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12540 * to NORMAL_MODE, return an error too.
12541 */
12542 for (i = 0; i < 2; i++) {
12543 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12544 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12545 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12546 if ((byte & RAM_TEST_DONE) == 0
12547 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012548 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012549 return ADV_ERROR;
12550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012551
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012552 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12553 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12554 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12555 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012556 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012557 return ADV_ERROR;
12558 }
12559 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012560
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012561 /*
12562 * LRAM Test - It takes about 1.5 ms to run through the test.
12563 *
12564 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12565 * If Done bit not set or Status not 0, save register byte, set the
12566 * err_code, and return an error.
12567 */
12568 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12569 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012570
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012571 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12572 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12573 /* Get here if Done bit not set or Status not 0. */
12574 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012575 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012576 return ADV_ERROR;
12577 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012578
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012579 /* We need to reset back to normal mode after LRAM test passes. */
12580 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012581
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012582 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
12583 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
12584 _adv_asc38C1600_chksum);
12585 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012586 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012588 /*
12589 * Restore the RISC memory BIOS region.
12590 */
12591 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12592 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12593 bios_mem[i]);
12594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012595
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012596 /*
12597 * Calculate and write the microcode code checksum to the microcode
12598 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12599 */
12600 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12601 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12602 code_sum = 0;
12603 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12604 for (word = begin_addr; word < end_addr; word += 2) {
12605 code_sum += AdvReadWordAutoIncLram(iop_base);
12606 }
12607 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012608
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012609 /*
12610 * Read microcode version and date.
12611 */
12612 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12613 asc_dvc->cfg->mcode_date);
12614 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12615 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012616
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012617 /*
12618 * Set the chip type to indicate the ASC38C1600.
12619 */
12620 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012621
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012622 /*
12623 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12624 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12625 * cable detection and then we are able to read C_DET[3:0].
12626 *
12627 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12628 * Microcode Default Value' section below.
12629 */
12630 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12631 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12632 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012633
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012634 /*
12635 * If the PCI Configuration Command Register "Parity Error Response
12636 * Control" Bit was clear (0), then set the microcode variable
12637 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12638 * to ignore DMA parity errors.
12639 */
12640 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12641 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12642 word |= CONTROL_FLAG_IGNORE_PERR;
12643 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012645
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012646 /*
12647 * If the BIOS control flag AIPP (Asynchronous Information
12648 * Phase Protection) disable bit is not set, then set the firmware
12649 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
12650 * AIPP checking and encoding.
12651 */
12652 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
12653 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12654 word |= CONTROL_FLAG_ENABLE_AIPP;
12655 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012657
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012658 /*
12659 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
12660 * and START_CTL_TH [3:2].
12661 */
12662 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12663 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012664
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012665 /*
12666 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012667 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012668 * device reports it is capable of in Inquiry byte 7.
12669 *
12670 * If SCSI Bus Resets have been disabled, then directly set
12671 * SDTR and WDTR from the EEPROM configuration. This will allow
12672 * the BIOS and warm boot to work without a SCSI bus hang on
12673 * the Inquiry caused by host and target mismatched DTR values.
12674 * Without the SCSI Bus Reset, before an Inquiry a device can't
12675 * be assumed to be in Asynchronous, Narrow mode.
12676 */
12677 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12678 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12679 asc_dvc->wdtr_able);
12680 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12681 asc_dvc->sdtr_able);
12682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012683
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012684 /*
12685 * Set microcode operating variables for DISC and SDTR_SPEED1,
12686 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12687 * configuration values.
12688 *
12689 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12690 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12691 * without determining here whether the device supports SDTR.
12692 */
12693 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12694 asc_dvc->cfg->disc_enable);
12695 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12696 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12697 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12698 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012699
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012700 /*
12701 * Set SCSI_CFG0 Microcode Default Value.
12702 *
12703 * The microcode will set the SCSI_CFG0 register using this value
12704 * after it is started below.
12705 */
12706 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12707 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12708 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012709
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012710 /*
12711 * Calculate SCSI_CFG1 Microcode Default Value.
12712 *
12713 * The microcode will set the SCSI_CFG1 register using this value
12714 * after it is started below.
12715 *
12716 * Each ASC-38C1600 function has only two cable detect bits.
12717 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
12718 */
12719 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012720
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012721 /*
12722 * If the cable is reversed all of the SCSI_CTRL register signals
12723 * will be set. Check for and return an error if this condition is
12724 * found.
12725 */
12726 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12727 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12728 return ADV_ERROR;
12729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012730
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012731 /*
12732 * Each ASC-38C1600 function has two connectors. Only an HVD device
12733 * can not be connected to either connector. An LVD device or SE device
12734 * may be connected to either connecor. If an SE device is connected,
12735 * then at most Ultra speed (20 Mhz) can be used on both connectors.
12736 *
12737 * If an HVD device is attached, return an error.
12738 */
12739 if (scsi_cfg1 & HVD) {
12740 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
12741 return ADV_ERROR;
12742 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012743
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012744 /*
12745 * Each function in the ASC-38C1600 uses only the SE cable detect and
12746 * termination because there are two connectors for each function. Each
12747 * function may use either LVD or SE mode. Corresponding the SE automatic
12748 * termination control EEPROM bits are used for each function. Each
12749 * function has its own EEPROM. If SE automatic control is enabled for
12750 * the function, then set the termination value based on a table listed
12751 * in a_condor.h.
12752 *
12753 * If manual termination is specified in the EEPROM for the function,
12754 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
12755 * ready to be 'ored' into SCSI_CFG1.
12756 */
12757 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012758 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012759 /* SE automatic termination control is enabled. */
12760 switch (scsi_cfg1 & C_DET_SE) {
12761 /* TERM_SE_HI: on, TERM_SE_LO: on */
12762 case 0x1:
12763 case 0x2:
12764 case 0x3:
12765 asc_dvc->cfg->termination |= TERM_SE;
12766 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012767
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012768 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012769 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012770 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
12771 } else {
12772 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
12773 asc_dvc->cfg->termination |= TERM_SE_HI;
12774 }
12775 break;
12776 }
12777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012778
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012779 /*
12780 * Clear any set TERM_SE bits.
12781 */
12782 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012783
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012784 /*
12785 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
12786 */
12787 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012788
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012789 /*
12790 * Clear Big Endian and Terminator Polarity bits and set possibly
12791 * modified termination control bits in the Microcode SCSI_CFG1
12792 * Register Value.
12793 *
12794 * Big Endian bit is not used even on big endian machines.
12795 */
12796 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012797
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012798 /*
12799 * Set SCSI_CFG1 Microcode Default Value
12800 *
12801 * Set possibly modified termination control bits in the Microcode
12802 * SCSI_CFG1 Register Value.
12803 *
12804 * The microcode will set the SCSI_CFG1 register using this value
12805 * after it is started below.
12806 */
12807 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012808
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012809 /*
12810 * Set MEM_CFG Microcode Default Value
12811 *
12812 * The microcode will set the MEM_CFG register using this value
12813 * after it is started below.
12814 *
12815 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12816 * are defined.
12817 *
12818 * ASC-38C1600 has 32KB internal memory.
12819 *
12820 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
12821 * out a special 16K Adv Library and Microcode version. After the issue
12822 * resolved, we should turn back to the 32K support. Both a_condor.h and
12823 * mcode.sas files also need to be updated.
12824 *
12825 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12826 * BIOS_EN | RAM_SZ_32KB);
12827 */
12828 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12829 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012831 /*
12832 * Set SEL_MASK Microcode Default Value
12833 *
12834 * The microcode will set the SEL_MASK register using this value
12835 * after it is started below.
12836 */
12837 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12838 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012839
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012840 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012841
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012842 /*
12843 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12844 */
12845 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12846 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12847 return ADV_ERROR;
12848 }
12849 asc_dvc->carr_freelist = (ADV_CARR_T *)
12850 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012851
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012852 /*
12853 * The first command issued will be placed in the stopper carrier.
12854 */
12855 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012857 /*
12858 * Set RISC ICQ physical address start value. Initialize the
12859 * COMMA register to the same value otherwise the RISC will
12860 * prematurely detect a command is available.
12861 */
12862 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
12863 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
12864 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012865
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012866 /*
12867 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12868 */
12869 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12870 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12871 return ADV_ERROR;
12872 }
12873 asc_dvc->carr_freelist = (ADV_CARR_T *)
12874 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012875
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012876 /*
12877 * The first command completed by the RISC will be placed in
12878 * the stopper.
12879 *
12880 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12881 * completed the RISC will set the ASC_RQ_STOPPER bit.
12882 */
12883 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012884
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012885 /*
12886 * Set RISC IRQ physical address start value.
12887 */
12888 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12889 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012890
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012891 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12892 (ADV_INTR_ENABLE_HOST_INTR |
12893 ADV_INTR_ENABLE_GLOBAL_INTR));
12894 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12895 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012897 /* finally, finally, gentlemen, start your engine */
12898 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012899
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012900 /*
12901 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12902 * Resets should be performed. The RISC has to be running
12903 * to issue a SCSI Bus Reset.
12904 */
12905 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12906 /*
12907 * If the BIOS Signature is present in memory, restore the
12908 * per TID microcode operating variables.
12909 */
12910 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12911 0x55AA) {
12912 /*
12913 * Restore per TID negotiated values.
12914 */
12915 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12916 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12917 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12918 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12919 tagqng_able);
12920 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12921 AdvWriteByteLram(iop_base,
12922 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12923 max_cmd[tid]);
12924 }
12925 } else {
12926 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12927 warn_code = ASC_WARN_BUSRESET_ERROR;
12928 }
12929 }
12930 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012931
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012932 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012933}
12934
12935/*
12936 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12937 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12938 * all of this is done.
12939 *
12940 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12941 *
12942 * For a non-fatal error return a warning code. If there are no warnings
12943 * then 0 is returned.
12944 *
12945 * Note: Chip is stopped on entry.
12946 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012947static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012948{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012949 AdvPortAddr iop_base;
12950 ushort warn_code;
12951 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012952
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012953 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012954
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012955 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012956
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012957 /*
12958 * Read the board's EEPROM configuration.
12959 *
12960 * Set default values if a bad checksum is found.
12961 */
12962 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12963 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012964
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012965 /*
12966 * Set EEPROM default values.
12967 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012968 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12969 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012970
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012971 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012972 * Assume the 6 byte board serial number that was read from
12973 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012974 */
12975 eep_config.serial_number_word3 =
12976 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012977
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012978 eep_config.serial_number_word2 =
12979 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012980
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012981 eep_config.serial_number_word1 =
12982 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012983
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012984 AdvSet3550EEPConfig(iop_base, &eep_config);
12985 }
12986 /*
12987 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
12988 * EEPROM configuration that was read.
12989 *
12990 * This is the mapping of EEPROM fields to Adv Library fields.
12991 */
12992 asc_dvc->wdtr_able = eep_config.wdtr_able;
12993 asc_dvc->sdtr_able = eep_config.sdtr_able;
12994 asc_dvc->ultra_able = eep_config.ultra_able;
12995 asc_dvc->tagqng_able = eep_config.tagqng_able;
12996 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
12997 asc_dvc->max_host_qng = eep_config.max_host_qng;
12998 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
12999 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13000 asc_dvc->start_motor = eep_config.start_motor;
13001 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13002 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13003 asc_dvc->no_scam = eep_config.scam_tolerant;
13004 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13005 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13006 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013007
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013008 /*
13009 * Set the host maximum queuing (max. 253, min. 16) and the per device
13010 * maximum queuing (max. 63, min. 4).
13011 */
13012 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13013 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13014 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13015 /* If the value is zero, assume it is uninitialized. */
13016 if (eep_config.max_host_qng == 0) {
13017 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13018 } else {
13019 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13020 }
13021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013022
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013023 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13024 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13025 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13026 /* If the value is zero, assume it is uninitialized. */
13027 if (eep_config.max_dvc_qng == 0) {
13028 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13029 } else {
13030 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13031 }
13032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013033
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013034 /*
13035 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13036 * set 'max_dvc_qng' to 'max_host_qng'.
13037 */
13038 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13039 eep_config.max_dvc_qng = eep_config.max_host_qng;
13040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013041
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013042 /*
13043 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13044 * values based on possibly adjusted EEPROM values.
13045 */
13046 asc_dvc->max_host_qng = eep_config.max_host_qng;
13047 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013049 /*
13050 * If the EEPROM 'termination' field is set to automatic (0), then set
13051 * the ADV_DVC_CFG 'termination' field to automatic also.
13052 *
13053 * If the termination is specified with a non-zero 'termination'
13054 * value check that a legal value is set and set the ADV_DVC_CFG
13055 * 'termination' field appropriately.
13056 */
13057 if (eep_config.termination == 0) {
13058 asc_dvc->cfg->termination = 0; /* auto termination */
13059 } else {
13060 /* Enable manual control with low off / high off. */
13061 if (eep_config.termination == 1) {
13062 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013063
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013064 /* Enable manual control with low off / high on. */
13065 } else if (eep_config.termination == 2) {
13066 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013067
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013068 /* Enable manual control with low on / high on. */
13069 } else if (eep_config.termination == 3) {
13070 asc_dvc->cfg->termination =
13071 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
13072 } else {
13073 /*
13074 * The EEPROM 'termination' field contains a bad value. Use
13075 * automatic termination instead.
13076 */
13077 asc_dvc->cfg->termination = 0;
13078 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13079 }
13080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013081
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013082 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013083}
13084
13085/*
13086 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13087 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13088 * all of this is done.
13089 *
13090 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13091 *
13092 * For a non-fatal error return a warning code. If there are no warnings
13093 * then 0 is returned.
13094 *
13095 * Note: Chip is stopped on entry.
13096 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013097static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013098{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013099 AdvPortAddr iop_base;
13100 ushort warn_code;
13101 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013102 uchar tid, termination;
13103 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013104
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013105 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013106
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013107 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013108
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013109 /*
13110 * Read the board's EEPROM configuration.
13111 *
13112 * Set default values if a bad checksum is found.
13113 */
13114 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13115 eep_config.check_sum) {
13116 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013117
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013118 /*
13119 * Set EEPROM default values.
13120 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013121 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13122 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013123
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013124 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013125 * Assume the 6 byte board serial number that was read from
13126 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013127 */
13128 eep_config.serial_number_word3 =
13129 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013130
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013131 eep_config.serial_number_word2 =
13132 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013133
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013134 eep_config.serial_number_word1 =
13135 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013136
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013137 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13138 }
13139 /*
13140 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13141 * EEPROM configuration that was read.
13142 *
13143 * This is the mapping of EEPROM fields to Adv Library fields.
13144 */
13145 asc_dvc->wdtr_able = eep_config.wdtr_able;
13146 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13147 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13148 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13149 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13150 asc_dvc->tagqng_able = eep_config.tagqng_able;
13151 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13152 asc_dvc->max_host_qng = eep_config.max_host_qng;
13153 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13154 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13155 asc_dvc->start_motor = eep_config.start_motor;
13156 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13157 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13158 asc_dvc->no_scam = eep_config.scam_tolerant;
13159 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13160 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13161 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013162
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013163 /*
13164 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13165 * are set, then set an 'sdtr_able' bit for it.
13166 */
13167 asc_dvc->sdtr_able = 0;
13168 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13169 if (tid == 0) {
13170 sdtr_speed = asc_dvc->sdtr_speed1;
13171 } else if (tid == 4) {
13172 sdtr_speed = asc_dvc->sdtr_speed2;
13173 } else if (tid == 8) {
13174 sdtr_speed = asc_dvc->sdtr_speed3;
13175 } else if (tid == 12) {
13176 sdtr_speed = asc_dvc->sdtr_speed4;
13177 }
13178 if (sdtr_speed & ADV_MAX_TID) {
13179 asc_dvc->sdtr_able |= (1 << tid);
13180 }
13181 sdtr_speed >>= 4;
13182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013183
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013184 /*
13185 * Set the host maximum queuing (max. 253, min. 16) and the per device
13186 * maximum queuing (max. 63, min. 4).
13187 */
13188 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13189 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13190 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13191 /* If the value is zero, assume it is uninitialized. */
13192 if (eep_config.max_host_qng == 0) {
13193 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13194 } else {
13195 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13196 }
13197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013198
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013199 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13200 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13201 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13202 /* If the value is zero, assume it is uninitialized. */
13203 if (eep_config.max_dvc_qng == 0) {
13204 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13205 } else {
13206 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13207 }
13208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013209
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013210 /*
13211 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13212 * set 'max_dvc_qng' to 'max_host_qng'.
13213 */
13214 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13215 eep_config.max_dvc_qng = eep_config.max_host_qng;
13216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013217
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013218 /*
13219 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13220 * values based on possibly adjusted EEPROM values.
13221 */
13222 asc_dvc->max_host_qng = eep_config.max_host_qng;
13223 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013224
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013225 /*
13226 * If the EEPROM 'termination' field is set to automatic (0), then set
13227 * the ADV_DVC_CFG 'termination' field to automatic also.
13228 *
13229 * If the termination is specified with a non-zero 'termination'
13230 * value check that a legal value is set and set the ADV_DVC_CFG
13231 * 'termination' field appropriately.
13232 */
13233 if (eep_config.termination_se == 0) {
13234 termination = 0; /* auto termination for SE */
13235 } else {
13236 /* Enable manual control with low off / high off. */
13237 if (eep_config.termination_se == 1) {
13238 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013239
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013240 /* Enable manual control with low off / high on. */
13241 } else if (eep_config.termination_se == 2) {
13242 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013243
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013244 /* Enable manual control with low on / high on. */
13245 } else if (eep_config.termination_se == 3) {
13246 termination = TERM_SE;
13247 } else {
13248 /*
13249 * The EEPROM 'termination_se' field contains a bad value.
13250 * Use automatic termination instead.
13251 */
13252 termination = 0;
13253 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13254 }
13255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013256
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013257 if (eep_config.termination_lvd == 0) {
13258 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13259 } else {
13260 /* Enable manual control with low off / high off. */
13261 if (eep_config.termination_lvd == 1) {
13262 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013263
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013264 /* Enable manual control with low off / high on. */
13265 } else if (eep_config.termination_lvd == 2) {
13266 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013267
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013268 /* Enable manual control with low on / high on. */
13269 } else if (eep_config.termination_lvd == 3) {
13270 asc_dvc->cfg->termination = termination | TERM_LVD;
13271 } else {
13272 /*
13273 * The EEPROM 'termination_lvd' field contains a bad value.
13274 * Use automatic termination instead.
13275 */
13276 asc_dvc->cfg->termination = termination;
13277 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13278 }
13279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013280
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013281 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013282}
13283
13284/*
13285 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13286 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13287 * all of this is done.
13288 *
13289 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13290 *
13291 * For a non-fatal error return a warning code. If there are no warnings
13292 * then 0 is returned.
13293 *
13294 * Note: Chip is stopped on entry.
13295 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013296static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013297{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013298 AdvPortAddr iop_base;
13299 ushort warn_code;
13300 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013301 uchar tid, termination;
13302 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013303
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013304 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013305
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013306 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013307
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013308 /*
13309 * Read the board's EEPROM configuration.
13310 *
13311 * Set default values if a bad checksum is found.
13312 */
13313 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13314 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013315 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013316 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013317
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013318 /*
13319 * Set EEPROM default values.
13320 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013321 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13322 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013323
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013324 if (PCI_FUNC(pdev->devfn) != 0) {
13325 u8 ints;
13326 /*
13327 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13328 * and old Mac system booting problem. The Expansion
13329 * ROM must be disabled in Function 1 for these systems
13330 */
13331 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13332 /*
13333 * Clear the INTAB (bit 11) if the GPIO 0 input
13334 * indicates the Function 1 interrupt line is wired
13335 * to INTB.
13336 *
13337 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13338 * 1 - Function 1 interrupt line wired to INT A.
13339 * 0 - Function 1 interrupt line wired to INT B.
13340 *
13341 * Note: Function 0 is always wired to INTA.
13342 * Put all 5 GPIO bits in input mode and then read
13343 * their input values.
13344 */
13345 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13346 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13347 if ((ints & 0x01) == 0)
13348 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013350
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013351 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013352 * Assume the 6 byte board serial number that was read from
13353 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013354 */
13355 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013356 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013357 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013358 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013359 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013360 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013362 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013364
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013365 /*
13366 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13367 * EEPROM configuration that was read.
13368 *
13369 * This is the mapping of EEPROM fields to Adv Library fields.
13370 */
13371 asc_dvc->wdtr_able = eep_config.wdtr_able;
13372 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13373 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13374 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13375 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13376 asc_dvc->ppr_able = 0;
13377 asc_dvc->tagqng_able = eep_config.tagqng_able;
13378 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13379 asc_dvc->max_host_qng = eep_config.max_host_qng;
13380 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13381 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13382 asc_dvc->start_motor = eep_config.start_motor;
13383 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13384 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13385 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013386
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013387 /*
13388 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13389 * are set, then set an 'sdtr_able' bit for it.
13390 */
13391 asc_dvc->sdtr_able = 0;
13392 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13393 if (tid == 0) {
13394 sdtr_speed = asc_dvc->sdtr_speed1;
13395 } else if (tid == 4) {
13396 sdtr_speed = asc_dvc->sdtr_speed2;
13397 } else if (tid == 8) {
13398 sdtr_speed = asc_dvc->sdtr_speed3;
13399 } else if (tid == 12) {
13400 sdtr_speed = asc_dvc->sdtr_speed4;
13401 }
13402 if (sdtr_speed & ASC_MAX_TID) {
13403 asc_dvc->sdtr_able |= (1 << tid);
13404 }
13405 sdtr_speed >>= 4;
13406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013407
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013408 /*
13409 * Set the host maximum queuing (max. 253, min. 16) and the per device
13410 * maximum queuing (max. 63, min. 4).
13411 */
13412 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13413 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13414 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13415 /* If the value is zero, assume it is uninitialized. */
13416 if (eep_config.max_host_qng == 0) {
13417 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13418 } else {
13419 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13420 }
13421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013422
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013423 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13424 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13425 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13426 /* If the value is zero, assume it is uninitialized. */
13427 if (eep_config.max_dvc_qng == 0) {
13428 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13429 } else {
13430 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13431 }
13432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013433
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013434 /*
13435 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13436 * set 'max_dvc_qng' to 'max_host_qng'.
13437 */
13438 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13439 eep_config.max_dvc_qng = eep_config.max_host_qng;
13440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013442 /*
13443 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13444 * values based on possibly adjusted EEPROM values.
13445 */
13446 asc_dvc->max_host_qng = eep_config.max_host_qng;
13447 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013448
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013449 /*
13450 * If the EEPROM 'termination' field is set to automatic (0), then set
13451 * the ASC_DVC_CFG 'termination' field to automatic also.
13452 *
13453 * If the termination is specified with a non-zero 'termination'
13454 * value check that a legal value is set and set the ASC_DVC_CFG
13455 * 'termination' field appropriately.
13456 */
13457 if (eep_config.termination_se == 0) {
13458 termination = 0; /* auto termination for SE */
13459 } else {
13460 /* Enable manual control with low off / high off. */
13461 if (eep_config.termination_se == 1) {
13462 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013463
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013464 /* Enable manual control with low off / high on. */
13465 } else if (eep_config.termination_se == 2) {
13466 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013467
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013468 /* Enable manual control with low on / high on. */
13469 } else if (eep_config.termination_se == 3) {
13470 termination = TERM_SE;
13471 } else {
13472 /*
13473 * The EEPROM 'termination_se' field contains a bad value.
13474 * Use automatic termination instead.
13475 */
13476 termination = 0;
13477 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13478 }
13479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013480
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013481 if (eep_config.termination_lvd == 0) {
13482 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13483 } else {
13484 /* Enable manual control with low off / high off. */
13485 if (eep_config.termination_lvd == 1) {
13486 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013487
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013488 /* Enable manual control with low off / high on. */
13489 } else if (eep_config.termination_lvd == 2) {
13490 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013491
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013492 /* Enable manual control with low on / high on. */
13493 } else if (eep_config.termination_lvd == 3) {
13494 asc_dvc->cfg->termination = termination | TERM_LVD;
13495 } else {
13496 /*
13497 * The EEPROM 'termination_lvd' field contains a bad value.
13498 * Use automatic termination instead.
13499 */
13500 asc_dvc->cfg->termination = termination;
13501 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13502 }
13503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013504
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013505 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013506}
13507
13508/*
13509 * Read EEPROM configuration into the specified buffer.
13510 *
13511 * Return a checksum based on the EEPROM configuration read.
13512 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013513static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013514AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13515{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013516 ushort wval, chksum;
13517 ushort *wbuf;
13518 int eep_addr;
13519 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013520
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013521 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13522 wbuf = (ushort *)cfg_buf;
13523 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013524
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013525 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13526 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13527 wval = AdvReadEEPWord(iop_base, eep_addr);
13528 chksum += wval; /* Checksum is calculated from word values. */
13529 if (*charfields++) {
13530 *wbuf = le16_to_cpu(wval);
13531 } else {
13532 *wbuf = wval;
13533 }
13534 }
13535 /* Read checksum word. */
13536 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13537 wbuf++;
13538 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013539
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013540 /* Read rest of EEPROM not covered by the checksum. */
13541 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13542 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13543 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13544 if (*charfields++) {
13545 *wbuf = le16_to_cpu(*wbuf);
13546 }
13547 }
13548 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013549}
13550
13551/*
13552 * Read EEPROM configuration into the specified buffer.
13553 *
13554 * Return a checksum based on the EEPROM configuration read.
13555 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013556static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013557AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013558{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013559 ushort wval, chksum;
13560 ushort *wbuf;
13561 int eep_addr;
13562 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013563
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013564 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13565 wbuf = (ushort *)cfg_buf;
13566 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013567
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013568 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13569 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13570 wval = AdvReadEEPWord(iop_base, eep_addr);
13571 chksum += wval; /* Checksum is calculated from word values. */
13572 if (*charfields++) {
13573 *wbuf = le16_to_cpu(wval);
13574 } else {
13575 *wbuf = wval;
13576 }
13577 }
13578 /* Read checksum word. */
13579 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13580 wbuf++;
13581 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013582
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013583 /* Read rest of EEPROM not covered by the checksum. */
13584 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13585 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13586 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13587 if (*charfields++) {
13588 *wbuf = le16_to_cpu(*wbuf);
13589 }
13590 }
13591 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013592}
13593
13594/*
13595 * Read EEPROM configuration into the specified buffer.
13596 *
13597 * Return a checksum based on the EEPROM configuration read.
13598 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013599static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013600AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013601{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013602 ushort wval, chksum;
13603 ushort *wbuf;
13604 int eep_addr;
13605 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013606
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013607 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13608 wbuf = (ushort *)cfg_buf;
13609 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013610
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013611 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13612 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13613 wval = AdvReadEEPWord(iop_base, eep_addr);
13614 chksum += wval; /* Checksum is calculated from word values. */
13615 if (*charfields++) {
13616 *wbuf = le16_to_cpu(wval);
13617 } else {
13618 *wbuf = wval;
13619 }
13620 }
13621 /* Read checksum word. */
13622 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13623 wbuf++;
13624 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013625
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013626 /* Read rest of EEPROM not covered by the checksum. */
13627 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13628 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13629 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13630 if (*charfields++) {
13631 *wbuf = le16_to_cpu(*wbuf);
13632 }
13633 }
13634 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013635}
13636
13637/*
13638 * Read the EEPROM from specified location
13639 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013640static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013641{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013642 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13643 ASC_EEP_CMD_READ | eep_word_addr);
13644 AdvWaitEEPCmd(iop_base);
13645 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013646}
13647
13648/*
13649 * Wait for EEPROM command to complete
13650 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013651static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013652{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013653 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013654
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013655 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
13656 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
13657 ASC_EEP_CMD_DONE) {
13658 break;
13659 }
13660 DvcSleepMilliSecond(1);
13661 }
13662 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
13663 0) {
13664 ASC_ASSERT(0);
13665 }
13666 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013667}
13668
13669/*
13670 * Write the EEPROM from 'cfg_buf'.
13671 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013672void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013673AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13674{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013675 ushort *wbuf;
13676 ushort addr, chksum;
13677 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013678
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013679 wbuf = (ushort *)cfg_buf;
13680 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13681 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013682
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013683 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13684 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013685
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013686 /*
13687 * Write EEPROM from word 0 to word 20.
13688 */
13689 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13690 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13691 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013692
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013693 if (*charfields++) {
13694 word = cpu_to_le16(*wbuf);
13695 } else {
13696 word = *wbuf;
13697 }
13698 chksum += *wbuf; /* Checksum is calculated from word values. */
13699 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13700 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13701 ASC_EEP_CMD_WRITE | addr);
13702 AdvWaitEEPCmd(iop_base);
13703 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013705
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013706 /*
13707 * Write EEPROM checksum at word 21.
13708 */
13709 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13710 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13711 AdvWaitEEPCmd(iop_base);
13712 wbuf++;
13713 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013714
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013715 /*
13716 * Write EEPROM OEM name at words 22 to 29.
13717 */
13718 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13719 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13720 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013721
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013722 if (*charfields++) {
13723 word = cpu_to_le16(*wbuf);
13724 } else {
13725 word = *wbuf;
13726 }
13727 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13728 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13729 ASC_EEP_CMD_WRITE | addr);
13730 AdvWaitEEPCmd(iop_base);
13731 }
13732 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13733 AdvWaitEEPCmd(iop_base);
13734 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013735}
13736
13737/*
13738 * Write the EEPROM from 'cfg_buf'.
13739 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013740void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013741AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013742{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013743 ushort *wbuf;
13744 ushort *charfields;
13745 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013746
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013747 wbuf = (ushort *)cfg_buf;
13748 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13749 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013750
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013751 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13752 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013753
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013754 /*
13755 * Write EEPROM from word 0 to word 20.
13756 */
13757 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13758 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13759 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013760
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013761 if (*charfields++) {
13762 word = cpu_to_le16(*wbuf);
13763 } else {
13764 word = *wbuf;
13765 }
13766 chksum += *wbuf; /* Checksum is calculated from word values. */
13767 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13768 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13769 ASC_EEP_CMD_WRITE | addr);
13770 AdvWaitEEPCmd(iop_base);
13771 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013773
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013774 /*
13775 * Write EEPROM checksum at word 21.
13776 */
13777 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13778 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13779 AdvWaitEEPCmd(iop_base);
13780 wbuf++;
13781 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013782
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013783 /*
13784 * Write EEPROM OEM name at words 22 to 29.
13785 */
13786 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13787 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13788 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013789
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013790 if (*charfields++) {
13791 word = cpu_to_le16(*wbuf);
13792 } else {
13793 word = *wbuf;
13794 }
13795 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13796 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13797 ASC_EEP_CMD_WRITE | addr);
13798 AdvWaitEEPCmd(iop_base);
13799 }
13800 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13801 AdvWaitEEPCmd(iop_base);
13802 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013803}
13804
13805/*
13806 * Write the EEPROM from 'cfg_buf'.
13807 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013808void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013809AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013810{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013811 ushort *wbuf;
13812 ushort *charfields;
13813 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013814
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013815 wbuf = (ushort *)cfg_buf;
13816 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13817 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013818
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013819 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13820 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013821
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013822 /*
13823 * Write EEPROM from word 0 to word 20.
13824 */
13825 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13826 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13827 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013828
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013829 if (*charfields++) {
13830 word = cpu_to_le16(*wbuf);
13831 } else {
13832 word = *wbuf;
13833 }
13834 chksum += *wbuf; /* Checksum is calculated from word values. */
13835 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13836 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13837 ASC_EEP_CMD_WRITE | addr);
13838 AdvWaitEEPCmd(iop_base);
13839 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013841
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013842 /*
13843 * Write EEPROM checksum at word 21.
13844 */
13845 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13846 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13847 AdvWaitEEPCmd(iop_base);
13848 wbuf++;
13849 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013850
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013851 /*
13852 * Write EEPROM OEM name at words 22 to 29.
13853 */
13854 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13855 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13856 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013857
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013858 if (*charfields++) {
13859 word = cpu_to_le16(*wbuf);
13860 } else {
13861 word = *wbuf;
13862 }
13863 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13864 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13865 ASC_EEP_CMD_WRITE | addr);
13866 AdvWaitEEPCmd(iop_base);
13867 }
13868 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13869 AdvWaitEEPCmd(iop_base);
13870 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013871}
13872
13873/* a_advlib.c */
13874/*
13875 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
13876 *
13877 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
13878 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
13879 * RISC to notify it a new command is ready to be executed.
13880 *
13881 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
13882 * set to SCSI_MAX_RETRY.
13883 *
13884 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
13885 * for DMA addresses or math operations are byte swapped to little-endian
13886 * order.
13887 *
13888 * Return:
13889 * ADV_SUCCESS(1) - The request was successfully queued.
13890 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
13891 * request completes.
13892 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
13893 * host IC error.
13894 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013895static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013896{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013897 ulong last_int_level;
13898 AdvPortAddr iop_base;
13899 ADV_DCNT req_size;
13900 ADV_PADDR req_paddr;
13901 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013902
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013903 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013904
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013905 /*
13906 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
13907 */
13908 if (scsiq->target_id > ADV_MAX_TID) {
13909 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
13910 scsiq->done_status = QD_WITH_ERROR;
13911 return ADV_ERROR;
13912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013913
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013914 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013915
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013916 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070013917
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013918 /*
13919 * Allocate a carrier ensuring at least one carrier always
13920 * remains on the freelist and initialize fields.
13921 */
13922 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
13923 DvcLeaveCritical(last_int_level);
13924 return ADV_BUSY;
13925 }
13926 asc_dvc->carr_freelist = (ADV_CARR_T *)
13927 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
13928 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013929
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013930 /*
13931 * Set the carrier to be a stopper by setting 'next_vpa'
13932 * to the stopper value. The current stopper will be changed
13933 * below to point to the new stopper.
13934 */
13935 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013936
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013937 /*
13938 * Clear the ADV_SCSI_REQ_Q done flag.
13939 */
13940 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013941
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013942 req_size = sizeof(ADV_SCSI_REQ_Q);
13943 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
13944 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013945
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013946 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
13947 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013948
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013949 /* Wait for assertion before making little-endian */
13950 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013951
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013952 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
13953 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
13954 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013955
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013956 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
13957 /*
13958 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
13959 * order during initialization.
13960 */
13961 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013962
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013963 /*
13964 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
13965 * the microcode. The newly allocated stopper will become the new
13966 * stopper.
13967 */
13968 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013969
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013970 /*
13971 * Set the 'next_vpa' pointer for the old stopper to be the
13972 * physical address of the new stopper. The RISC can only
13973 * follow physical addresses.
13974 */
13975 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013976
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013977 /*
13978 * Set the host adapter stopper pointer to point to the new carrier.
13979 */
13980 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013981
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013982 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
13983 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13984 /*
13985 * Tickle the RISC to tell it to read its Command Queue Head pointer.
13986 */
13987 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
13988 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
13989 /*
13990 * Clear the tickle value. In the ASC-3550 the RISC flag
13991 * command 'clr_tickle_a' does not work unless the host
13992 * value is cleared.
13993 */
13994 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
13995 ADV_TICKLE_NOP);
13996 }
13997 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13998 /*
13999 * Notify the RISC a carrier is ready by writing the physical
14000 * address of the new carrier stopper to the COMMA register.
14001 */
14002 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
14003 le32_to_cpu(new_carrp->carr_pa));
14004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014005
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014006 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014007
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014008 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014009}
14010
14011/*
14012 * Reset SCSI Bus and purge all outstanding requests.
14013 *
14014 * Return Value:
14015 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
14016 * ADV_FALSE(0) - Microcode command failed.
14017 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
14018 * may be hung which requires driver recovery.
14019 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014020static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014021{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014022 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014023
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014024 /*
14025 * Send the SCSI Bus Reset idle start idle command which asserts
14026 * the SCSI Bus Reset signal.
14027 */
14028 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
14029 if (status != ADV_TRUE) {
14030 return status;
14031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014032
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014033 /*
14034 * Delay for the specified SCSI Bus Reset hold time.
14035 *
14036 * The hold time delay is done on the host because the RISC has no
14037 * microsecond accurate timer.
14038 */
14039 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014040
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014041 /*
14042 * Send the SCSI Bus Reset end idle command which de-asserts
14043 * the SCSI Bus Reset signal and purges any pending requests.
14044 */
14045 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
14046 if (status != ADV_TRUE) {
14047 return status;
14048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014049
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014050 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014051
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014052 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014053}
14054
14055/*
14056 * Reset chip and SCSI Bus.
14057 *
14058 * Return Value:
14059 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
14060 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
14061 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014062static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014063{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014064 int status;
14065 ushort wdtr_able, sdtr_able, tagqng_able;
14066 ushort ppr_able = 0;
14067 uchar tid, max_cmd[ADV_MAX_TID + 1];
14068 AdvPortAddr iop_base;
14069 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014071 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014072
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014073 /*
14074 * Save current per TID negotiated values.
14075 */
14076 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14077 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14078 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14079 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14080 }
14081 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14082 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14083 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14084 max_cmd[tid]);
14085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014086
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014087 /*
14088 * Force the AdvInitAsc3550/38C0800Driver() function to
14089 * perform a SCSI Bus Reset by clearing the BIOS signature word.
14090 * The initialization functions assumes a SCSI Bus Reset is not
14091 * needed if the BIOS signature word is present.
14092 */
14093 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
14094 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014095
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014096 /*
14097 * Stop chip and reset it.
14098 */
14099 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
14100 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14101 DvcSleepMilliSecond(100);
14102 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
14103 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014104
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014105 /*
14106 * Reset Adv Library error code, if any, and try
14107 * re-initializing the chip.
14108 */
14109 asc_dvc->err_code = 0;
14110 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14111 status = AdvInitAsc38C1600Driver(asc_dvc);
14112 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14113 status = AdvInitAsc38C0800Driver(asc_dvc);
14114 } else {
14115 status = AdvInitAsc3550Driver(asc_dvc);
14116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014117
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014118 /* Translate initialization return value to status value. */
14119 if (status == 0) {
14120 status = ADV_TRUE;
14121 } else {
14122 status = ADV_FALSE;
14123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014124
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014125 /*
14126 * Restore the BIOS signature word.
14127 */
14128 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014129
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014130 /*
14131 * Restore per TID negotiated values.
14132 */
14133 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14134 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14135 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14136 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14137 }
14138 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14139 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14140 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14141 max_cmd[tid]);
14142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014144 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014145}
14146
14147/*
14148 * Adv Library Interrupt Service Routine
14149 *
14150 * This function is called by a driver's interrupt service routine.
14151 * The function disables and re-enables interrupts.
14152 *
14153 * When a microcode idle command is completed, the ADV_DVC_VAR
14154 * 'idle_cmd_done' field is set to ADV_TRUE.
14155 *
14156 * Note: AdvISR() can be called when interrupts are disabled or even
14157 * when there is no hardware interrupt condition present. It will
14158 * always check for completed idle commands and microcode requests.
14159 * This is an important feature that shouldn't be changed because it
14160 * allows commands to be completed from polling mode loops.
14161 *
14162 * Return:
14163 * ADV_TRUE(1) - interrupt was pending
14164 * ADV_FALSE(0) - no interrupt was pending
14165 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014166static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014167{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014168 AdvPortAddr iop_base;
14169 uchar int_stat;
14170 ushort target_bit;
14171 ADV_CARR_T *free_carrp;
14172 ADV_VADDR irq_next_vpa;
14173 int flags;
14174 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014175
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014176 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014177
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014178 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014179
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014180 /* Reading the register clears the interrupt. */
14181 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014182
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014183 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
14184 ADV_INTR_STATUS_INTRC)) == 0) {
14185 DvcLeaveCritical(flags);
14186 return ADV_FALSE;
14187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014188
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189 /*
14190 * Notify the driver of an asynchronous microcode condition by
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014191 * calling the adv_async_callback function. The function
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014192 * is passed the microcode ASC_MC_INTRB_CODE byte value.
14193 */
14194 if (int_stat & ADV_INTR_STATUS_INTRB) {
14195 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014197 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014198
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014199 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14200 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14201 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
14202 asc_dvc->carr_pending_cnt != 0) {
14203 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14204 ADV_TICKLE_A);
14205 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14206 AdvWriteByteRegister(iop_base,
14207 IOPB_TICKLE,
14208 ADV_TICKLE_NOP);
14209 }
14210 }
14211 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014212
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014213 adv_async_callback(asc_dvc, intrb_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014215
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014216 /*
14217 * Check if the IRQ stopper carrier contains a completed request.
14218 */
14219 while (((irq_next_vpa =
14220 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
14221 /*
14222 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
14223 * The RISC will have set 'areq_vpa' to a virtual address.
14224 *
14225 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
14226 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
14227 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
14228 * in AdvExeScsiQueue().
14229 */
14230 scsiq = (ADV_SCSI_REQ_Q *)
14231 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014232
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014233 /*
14234 * Request finished with good status and the queue was not
14235 * DMAed to host memory by the firmware. Set all status fields
14236 * to indicate good status.
14237 */
14238 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
14239 scsiq->done_status = QD_NO_ERROR;
14240 scsiq->host_status = scsiq->scsi_status = 0;
14241 scsiq->data_cnt = 0L;
14242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014243
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014244 /*
14245 * Advance the stopper pointer to the next carrier
14246 * ignoring the lower four bits. Free the previous
14247 * stopper carrier.
14248 */
14249 free_carrp = asc_dvc->irq_sp;
14250 asc_dvc->irq_sp = (ADV_CARR_T *)
14251 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014252
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014253 free_carrp->next_vpa =
14254 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14255 asc_dvc->carr_freelist = free_carrp;
14256 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014257
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014258 ASC_ASSERT(scsiq != NULL);
14259 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014260
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014261 /*
14262 * Clear request microcode control flag.
14263 */
14264 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014265
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014266 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014267 * Notify the driver of the completed request by passing
14268 * the ADV_SCSI_REQ_Q pointer to its callback function.
14269 */
14270 scsiq->a_flag |= ADV_SCSIQ_DONE;
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014271 adv_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014272 /*
14273 * Note: After the driver callback function is called, 'scsiq'
14274 * can no longer be referenced.
14275 *
14276 * Fall through and continue processing other completed
14277 * requests...
14278 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014279
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014280 /*
14281 * Disable interrupts again in case the driver inadvertently
14282 * enabled interrupts in its callback function.
14283 *
14284 * The DvcEnterCritical() return value is ignored, because
14285 * the 'flags' saved when AdvISR() was first entered will be
14286 * used to restore the interrupt flag on exit.
14287 */
14288 (void)DvcEnterCritical();
14289 }
14290 DvcLeaveCritical(flags);
14291 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014292}
14293
14294/*
14295 * Send an idle command to the chip and wait for completion.
14296 *
14297 * Command completion is polled for once per microsecond.
14298 *
14299 * The function can be called from anywhere including an interrupt handler.
14300 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
14301 * functions to prevent reentrancy.
14302 *
14303 * Return Values:
14304 * ADV_TRUE - command completed successfully
14305 * ADV_FALSE - command failed
14306 * ADV_ERROR - command timed out
14307 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014308static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070014309AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014310 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014311{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014312 ulong last_int_level;
14313 int result;
14314 ADV_DCNT i, j;
14315 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014316
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014317 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014318
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014319 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014320
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014321 /*
14322 * Clear the idle command status which is set by the microcode
14323 * to a non-zero value to indicate when the command is completed.
14324 * The non-zero result is one of the IDLE_CMD_STATUS_* values
14325 * defined in a_advlib.h.
14326 */
14327 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014328
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014329 /*
14330 * Write the idle command value after the idle command parameter
14331 * has been written to avoid a race condition. If the order is not
14332 * followed, the microcode may process the idle command before the
14333 * parameters have been written to LRAM.
14334 */
14335 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
14336 cpu_to_le32(idle_cmd_parameter));
14337 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014338
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014339 /*
14340 * Tickle the RISC to tell it to process the idle command.
14341 */
14342 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
14343 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14344 /*
14345 * Clear the tickle value. In the ASC-3550 the RISC flag
14346 * command 'clr_tickle_b' does not work unless the host
14347 * value is cleared.
14348 */
14349 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
14350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014351
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014352 /* Wait for up to 100 millisecond for the idle command to timeout. */
14353 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
14354 /* Poll once each microsecond for command completion. */
14355 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
14356 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
14357 result);
14358 if (result != 0) {
14359 DvcLeaveCritical(last_int_level);
14360 return result;
14361 }
14362 DvcDelayMicroSecond(asc_dvc, (ushort)1);
14363 }
14364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014365
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014366 ASC_ASSERT(0); /* The idle command should never timeout. */
14367 DvcLeaveCritical(last_int_level);
14368 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014369}
14370
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014371static int __devinit
14372advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
14373{
14374 int req_cnt = 0;
14375 adv_req_t *reqp = NULL;
14376 int sg_cnt = 0;
14377 adv_sgblk_t *sgp;
14378 int warn_code, err_code;
14379
14380 /*
14381 * Allocate buffer carrier structures. The total size
14382 * is about 4 KB, so allocate all at once.
14383 */
14384 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
14385 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
14386
14387 if (!boardp->carrp)
14388 goto kmalloc_failed;
14389
14390 /*
14391 * Allocate up to 'max_host_qng' request structures for the Wide
14392 * board. The total size is about 16 KB, so allocate all at once.
14393 * If the allocation fails decrement and try again.
14394 */
14395 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
14396 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
14397
14398 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
14399 "bytes %lu\n", reqp, req_cnt,
14400 (ulong)sizeof(adv_req_t) * req_cnt);
14401
14402 if (reqp)
14403 break;
14404 }
14405
14406 if (!reqp)
14407 goto kmalloc_failed;
14408
14409 boardp->orig_reqp = reqp;
14410
14411 /*
14412 * Allocate up to ADV_TOT_SG_BLOCK request structures for
14413 * the Wide board. Each structure is about 136 bytes.
14414 */
14415 boardp->adv_sgblkp = NULL;
14416 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
14417 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
14418
14419 if (!sgp)
14420 break;
14421
14422 sgp->next_sgblkp = boardp->adv_sgblkp;
14423 boardp->adv_sgblkp = sgp;
14424
14425 }
14426
14427 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
14428 sg_cnt, sizeof(adv_sgblk_t),
14429 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
14430
14431 if (!boardp->adv_sgblkp)
14432 goto kmalloc_failed;
14433
14434 adv_dvc_varp->carrier_buf = boardp->carrp;
14435
14436 /*
14437 * Point 'adv_reqp' to the request structures and
14438 * link them together.
14439 */
14440 req_cnt--;
14441 reqp[req_cnt].next_reqp = NULL;
14442 for (; req_cnt > 0; req_cnt--) {
14443 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
14444 }
14445 boardp->adv_reqp = &reqp[0];
14446
14447 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14448 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
14449 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
14450 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14451 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
14452 "\n");
14453 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
14454 } else {
14455 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
14456 "\n");
14457 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
14458 }
14459 err_code = adv_dvc_varp->err_code;
14460
14461 if (warn_code || err_code) {
14462 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
14463 " error 0x%x\n", boardp->id, warn_code, err_code);
14464 }
14465
14466 goto exit;
14467
14468 kmalloc_failed:
14469 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
14470 "failed\n", boardp->id);
14471 err_code = ADV_ERROR;
14472 exit:
14473 return err_code;
14474}
14475
14476static void advansys_wide_free_mem(asc_board_t *boardp)
14477{
14478 kfree(boardp->carrp);
14479 boardp->carrp = NULL;
14480 kfree(boardp->orig_reqp);
14481 boardp->orig_reqp = boardp->adv_reqp = NULL;
14482 while (boardp->adv_sgblkp) {
14483 adv_sgblk_t *sgp = boardp->adv_sgblkp;
14484 boardp->adv_sgblkp = sgp->next_sgblkp;
14485 kfree(sgp);
14486 }
14487}
14488
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014489static struct Scsi_Host *__devinit
14490advansys_board_found(int iop, struct device *dev, int bus_type)
14491{
14492 struct Scsi_Host *shost;
14493 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
14494 asc_board_t *boardp;
14495 ASC_DVC_VAR *asc_dvc_varp = NULL;
14496 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014497 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014498 int warn_code, err_code;
14499 int ret;
14500
14501 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014502 * Register the adapter, get its configuration, and
14503 * initialize it.
14504 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014505 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
14506 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014507 if (!shost)
14508 return NULL;
14509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014510 /* Initialize private per board data */
14511 boardp = ASC_BOARDP(shost);
14512 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014513 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014514 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014515 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014516
14517 /*
14518 * Handle both narrow and wide boards.
14519 *
14520 * If a Wide board was detected, set the board structure
14521 * wide board flag. Set-up the board structure based on
14522 * the board type.
14523 */
14524#ifdef CONFIG_PCI
14525 if (bus_type == ASC_IS_PCI &&
14526 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14527 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14528 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
14529 boardp->flags |= ASC_IS_WIDE_BOARD;
14530 }
14531#endif /* CONFIG_PCI */
14532
14533 if (ASC_NARROW_BOARD(boardp)) {
14534 ASC_DBG(1, "advansys_board_found: narrow board\n");
14535 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
14536 asc_dvc_varp->bus_type = bus_type;
14537 asc_dvc_varp->drv_ptr = boardp;
14538 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
14539 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
14540 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014541 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014542#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014543 ASC_DBG(1, "advansys_board_found: wide board\n");
14544 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
14545 adv_dvc_varp->drv_ptr = boardp;
14546 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014547 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
14548 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
14549 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
14550 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
14551 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
14552 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
14553 } else {
14554 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
14555 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
14556 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014557
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014558 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
14559 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
14560 boardp->asc_n_io_port);
14561 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014562 ASC_PRINT3
14563 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014564 boardp->id, pci_resource_start(pdev, 1),
14565 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014566 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014567 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014568 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060014569 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014570 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014571
14572 /*
14573 * Even though it isn't used to access wide boards, other
14574 * than for the debug line below, save I/O Port address so
14575 * that it can be reported.
14576 */
14577 boardp->ioport = iop;
14578
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014579 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
14580 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
14581 (ushort)inpw(iop));
14582#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014583 }
14584
14585#ifdef CONFIG_PROC_FS
14586 /*
14587 * Allocate buffer for printing information from
14588 * /proc/scsi/advansys/[0...].
14589 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014590 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
14591 if (!boardp->prtbuf) {
14592 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
14593 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
14594 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014595 }
14596#endif /* CONFIG_PROC_FS */
14597
14598 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014599 /*
14600 * Set the board bus type and PCI IRQ before
14601 * calling AscInitGetConfig().
14602 */
14603 switch (asc_dvc_varp->bus_type) {
14604#ifdef CONFIG_ISA
14605 case ASC_IS_ISA:
14606 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014607 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014608 break;
14609 case ASC_IS_VL:
14610 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014611 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014612 break;
14613 case ASC_IS_EISA:
14614 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014615 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014616 break;
14617#endif /* CONFIG_ISA */
14618#ifdef CONFIG_PCI
14619 case ASC_IS_PCI:
14620 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014621 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014622 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014623 break;
14624#endif /* CONFIG_PCI */
14625 default:
14626 ASC_PRINT2
14627 ("advansys_board_found: board %d: unknown adapter type: %d\n",
14628 boardp->id, asc_dvc_varp->bus_type);
14629 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014630 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014631 break;
14632 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014633
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014634 /*
14635 * NOTE: AscInitGetConfig() may change the board's
14636 * bus_type value. The bus_type value should no
14637 * longer be used. If the bus_type field must be
14638 * referenced only use the bit-wise AND operator "&".
14639 */
14640 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014641 err_code = AscInitGetConfig(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014642 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014643#ifdef CONFIG_PCI
14644 /*
14645 * For Wide boards set PCI information before calling
14646 * AdvInitGetConfig().
14647 */
14648 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
14649 shost->unchecked_isa_dma = FALSE;
14650 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014651 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014652
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014653 err_code = AdvInitGetConfig(pdev, boardp);
14654#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014655 }
14656
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014657 if (err_code != 0)
14658 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014659
14660 /*
14661 * Save the EEPROM configuration so that it can be displayed
14662 * from /proc/scsi/advansys/[0...].
14663 */
14664 if (ASC_NARROW_BOARD(boardp)) {
14665
14666 ASCEEP_CONFIG *ep;
14667
14668 /*
14669 * Set the adapter's target id bit in the 'init_tidmask' field.
14670 */
14671 boardp->init_tidmask |=
14672 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
14673
14674 /*
14675 * Save EEPROM settings for the board.
14676 */
14677 ep = &boardp->eep_config.asc_eep;
14678
14679 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
14680 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
14681 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
14682 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
14683 ep->start_motor = asc_dvc_varp->start_motor;
14684 ep->cntl = asc_dvc_varp->dvc_cntl;
14685 ep->no_scam = asc_dvc_varp->no_scam;
14686 ep->max_total_qng = asc_dvc_varp->max_total_qng;
14687 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
14688 /* 'max_tag_qng' is set to the same value for every device. */
14689 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
14690 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
14691 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
14692 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
14693 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
14694 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
14695 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
14696
14697 /*
14698 * Modify board configuration.
14699 */
14700 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014701 err_code = AscInitSetConfig(pdev, boardp);
14702 if (err_code)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014703 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014704
14705 /*
14706 * Finish initializing the 'Scsi_Host' structure.
14707 */
14708 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
14709 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
14710 shost->irq = asc_dvc_varp->irq_no;
14711 }
14712 } else {
14713 ADVEEP_3550_CONFIG *ep_3550;
14714 ADVEEP_38C0800_CONFIG *ep_38C0800;
14715 ADVEEP_38C1600_CONFIG *ep_38C1600;
14716
14717 /*
14718 * Save Wide EEP Configuration Information.
14719 */
14720 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14721 ep_3550 = &boardp->eep_config.adv_3550_eep;
14722
14723 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
14724 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
14725 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14726 ep_3550->termination = adv_dvc_varp->cfg->termination;
14727 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
14728 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
14729 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
14730 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
14731 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
14732 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
14733 ep_3550->start_motor = adv_dvc_varp->start_motor;
14734 ep_3550->scsi_reset_delay =
14735 adv_dvc_varp->scsi_reset_wait;
14736 ep_3550->serial_number_word1 =
14737 adv_dvc_varp->cfg->serial1;
14738 ep_3550->serial_number_word2 =
14739 adv_dvc_varp->cfg->serial2;
14740 ep_3550->serial_number_word3 =
14741 adv_dvc_varp->cfg->serial3;
14742 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14743 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
14744
14745 ep_38C0800->adapter_scsi_id =
14746 adv_dvc_varp->chip_scsi_id;
14747 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
14748 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14749 ep_38C0800->termination_lvd =
14750 adv_dvc_varp->cfg->termination;
14751 ep_38C0800->disc_enable =
14752 adv_dvc_varp->cfg->disc_enable;
14753 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
14754 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
14755 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14756 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14757 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14758 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14759 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14760 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14761 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
14762 ep_38C0800->scsi_reset_delay =
14763 adv_dvc_varp->scsi_reset_wait;
14764 ep_38C0800->serial_number_word1 =
14765 adv_dvc_varp->cfg->serial1;
14766 ep_38C0800->serial_number_word2 =
14767 adv_dvc_varp->cfg->serial2;
14768 ep_38C0800->serial_number_word3 =
14769 adv_dvc_varp->cfg->serial3;
14770 } else {
14771 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
14772
14773 ep_38C1600->adapter_scsi_id =
14774 adv_dvc_varp->chip_scsi_id;
14775 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
14776 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14777 ep_38C1600->termination_lvd =
14778 adv_dvc_varp->cfg->termination;
14779 ep_38C1600->disc_enable =
14780 adv_dvc_varp->cfg->disc_enable;
14781 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
14782 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
14783 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14784 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14785 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14786 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14787 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14788 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14789 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
14790 ep_38C1600->scsi_reset_delay =
14791 adv_dvc_varp->scsi_reset_wait;
14792 ep_38C1600->serial_number_word1 =
14793 adv_dvc_varp->cfg->serial1;
14794 ep_38C1600->serial_number_word2 =
14795 adv_dvc_varp->cfg->serial2;
14796 ep_38C1600->serial_number_word3 =
14797 adv_dvc_varp->cfg->serial3;
14798 }
14799
14800 /*
14801 * Set the adapter's target id bit in the 'init_tidmask' field.
14802 */
14803 boardp->init_tidmask |=
14804 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014805 }
14806
14807 /*
14808 * Channels are numbered beginning with 0. For AdvanSys one host
14809 * structure supports one channel. Multi-channel boards have a
14810 * separate host structure for each channel.
14811 */
14812 shost->max_channel = 0;
14813 if (ASC_NARROW_BOARD(boardp)) {
14814 shost->max_id = ASC_MAX_TID + 1;
14815 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014816 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014817
14818 shost->io_port = asc_dvc_varp->iop_base;
14819 boardp->asc_n_io_port = ASC_IOADR_GAP;
14820 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
14821
14822 /* Set maximum number of queues the adapter can handle. */
14823 shost->can_queue = asc_dvc_varp->max_total_qng;
14824 } else {
14825 shost->max_id = ADV_MAX_TID + 1;
14826 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014827 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014828
14829 /*
14830 * Save the I/O Port address and length even though
14831 * I/O ports are not used to access Wide boards.
14832 * Instead the Wide boards are accessed with
14833 * PCI Memory Mapped I/O.
14834 */
14835 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014836
14837 shost->this_id = adv_dvc_varp->chip_scsi_id;
14838
14839 /* Set maximum number of queues the adapter can handle. */
14840 shost->can_queue = adv_dvc_varp->max_host_qng;
14841 }
14842
14843 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014844 * Following v1.3.89, 'cmd_per_lun' is no longer needed
14845 * and should be set to zero.
14846 *
14847 * But because of a bug introduced in v1.3.89 if the driver is
14848 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
14849 * SCSI function 'allocate_device' will panic. To allow the driver
14850 * to work as a module in these kernels set 'cmd_per_lun' to 1.
14851 *
14852 * Note: This is wrong. cmd_per_lun should be set to the depth
14853 * you want on untagged devices always.
14854 #ifdef MODULE
14855 */
14856 shost->cmd_per_lun = 1;
14857/* #else
14858 shost->cmd_per_lun = 0;
14859#endif */
14860
14861 /*
14862 * Set the maximum number of scatter-gather elements the
14863 * adapter can handle.
14864 */
14865 if (ASC_NARROW_BOARD(boardp)) {
14866 /*
14867 * Allow two commands with 'sg_tablesize' scatter-gather
14868 * elements to be executed simultaneously. This value is
14869 * the theoretical hardware limit. It may be decreased
14870 * below.
14871 */
14872 shost->sg_tablesize =
14873 (((asc_dvc_varp->max_total_qng - 2) / 2) *
14874 ASC_SG_LIST_PER_Q) + 1;
14875 } else {
14876 shost->sg_tablesize = ADV_MAX_SG_LIST;
14877 }
14878
14879 /*
14880 * The value of 'sg_tablesize' can not exceed the SCSI
14881 * mid-level driver definition of SG_ALL. SG_ALL also
14882 * must not be exceeded, because it is used to define the
14883 * size of the scatter-gather table in 'struct asc_sg_head'.
14884 */
14885 if (shost->sg_tablesize > SG_ALL) {
14886 shost->sg_tablesize = SG_ALL;
14887 }
14888
14889 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
14890
14891 /* BIOS start address. */
14892 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014893 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
14894 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014895 } else {
14896 /*
14897 * Fill-in BIOS board variables. The Wide BIOS saves
14898 * information in LRAM that is used by the driver.
14899 */
14900 AdvReadWordLram(adv_dvc_varp->iop_base,
14901 BIOS_SIGNATURE, boardp->bios_signature);
14902 AdvReadWordLram(adv_dvc_varp->iop_base,
14903 BIOS_VERSION, boardp->bios_version);
14904 AdvReadWordLram(adv_dvc_varp->iop_base,
14905 BIOS_CODESEG, boardp->bios_codeseg);
14906 AdvReadWordLram(adv_dvc_varp->iop_base,
14907 BIOS_CODELEN, boardp->bios_codelen);
14908
14909 ASC_DBG2(1,
14910 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
14911 boardp->bios_signature, boardp->bios_version);
14912
14913 ASC_DBG2(1,
14914 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
14915 boardp->bios_codeseg, boardp->bios_codelen);
14916
14917 /*
14918 * If the BIOS saved a valid signature, then fill in
14919 * the BIOS code segment base address.
14920 */
14921 if (boardp->bios_signature == 0x55AA) {
14922 /*
14923 * Convert x86 realmode code segment to a linear
14924 * address by shifting left 4.
14925 */
14926 shost->base = ((ulong)boardp->bios_codeseg << 4);
14927 } else {
14928 shost->base = 0;
14929 }
14930 }
14931
14932 /*
14933 * Register Board Resources - I/O Port, DMA, IRQ
14934 */
14935
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014936 /* Register DMA Channel for Narrow boards. */
14937 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14938#ifdef CONFIG_ISA
14939 if (ASC_NARROW_BOARD(boardp)) {
14940 /* Register DMA channel for ISA bus. */
14941 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14942 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014943 ret = request_dma(shost->dma_channel, "advansys");
14944 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014945 ASC_PRINT3
14946 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14947 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014948 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014949 }
14950 AscEnableIsaDma(shost->dma_channel);
14951 }
14952 }
14953#endif /* CONFIG_ISA */
14954
14955 /* Register IRQ Number. */
14956 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014957
14958 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
14959 "advansys", shost);
14960
14961 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014962 if (ret == -EBUSY) {
14963 ASC_PRINT2
14964 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
14965 boardp->id, shost->irq);
14966 } else if (ret == -EINVAL) {
14967 ASC_PRINT2
14968 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
14969 boardp->id, shost->irq);
14970 } else {
14971 ASC_PRINT3
14972 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
14973 boardp->id, shost->irq, ret);
14974 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014975 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014976 }
14977
14978 /*
14979 * Initialize board RISC chip and enable interrupts.
14980 */
14981 if (ASC_NARROW_BOARD(boardp)) {
14982 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
14983 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
14984 err_code = asc_dvc_varp->err_code;
14985
14986 if (warn_code || err_code) {
14987 ASC_PRINT4
14988 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
14989 boardp->id,
14990 asc_dvc_varp->init_state, warn_code, err_code);
14991 }
14992 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014993 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014994 }
14995
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014996 if (err_code != 0)
14997 goto err_free_wide_mem;
14998
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014999 ASC_DBG_PRT_SCSI_HOST(2, shost);
15000
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015001 ret = scsi_add_host(shost, dev);
15002 if (ret)
15003 goto err_free_wide_mem;
15004
15005 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015006 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015007
15008 err_free_wide_mem:
15009 advansys_wide_free_mem(boardp);
15010 free_irq(shost->irq, shost);
15011 err_free_dma:
15012 if (shost->dma_channel != NO_ISA_DMA)
15013 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015014 err_free_proc:
15015 kfree(boardp->prtbuf);
15016 err_unmap:
15017 if (boardp->ioremap_addr)
15018 iounmap(boardp->ioremap_addr);
15019 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015020 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015021 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015022}
15023
15024/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015025 * advansys_release()
15026 *
15027 * Release resources allocated for a single AdvanSys adapter.
15028 */
15029static int advansys_release(struct Scsi_Host *shost)
15030{
15031 asc_board_t *boardp;
15032
15033 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015034 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015035 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015036 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015037 if (shost->dma_channel != NO_ISA_DMA) {
15038 ASC_DBG(1, "advansys_release: free_dma()\n");
15039 free_dma(shost->dma_channel);
15040 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015041 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015042 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015043 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015044 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015045 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015046 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015047 ASC_DBG(1, "advansys_release: end\n");
15048 return 0;
15049}
15050
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015051static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
15052 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
15053 0x0210, 0x0230, 0x0250, 0x0330
15054};
15055
15056static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
15057{
15058 PortAddr iop_base = _asc_def_iop_base[id];
15059 struct Scsi_Host *shost;
15060
15061 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015062 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
15063 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015064 return -ENODEV;
15065 }
15066 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015067 if (!AscFindSignature(iop_base))
15068 goto nodev;
15069 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
15070 goto nodev;
15071
15072 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015073 if (!shost)
15074 goto nodev;
15075
15076 dev_set_drvdata(dev, shost);
15077 return 0;
15078
15079 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015080 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015081 return -ENODEV;
15082}
15083
15084static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
15085{
Matthew Wilcox71f36112007-07-30 08:04:53 -060015086 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015087 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015088 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015089 return 0;
15090}
15091
15092static struct isa_driver advansys_isa_driver = {
15093 .probe = advansys_isa_probe,
15094 .remove = __devexit_p(advansys_isa_remove),
15095 .driver = {
15096 .owner = THIS_MODULE,
15097 .name = "advansys",
15098 },
15099};
15100
15101static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
15102{
15103 PortAddr iop_base = _asc_def_iop_base[id];
15104 struct Scsi_Host *shost;
15105
15106 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015107 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
15108 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015109 return -ENODEV;
15110 }
15111 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015112 if (!AscFindSignature(iop_base))
15113 goto nodev;
15114 /*
15115 * I don't think this condition can actually happen, but the old
15116 * driver did it, and the chances of finding a VLB setup in 2007
15117 * to do testing with is slight to none.
15118 */
15119 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
15120 goto nodev;
15121
15122 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015123 if (!shost)
15124 goto nodev;
15125
15126 dev_set_drvdata(dev, shost);
15127 return 0;
15128
15129 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015130 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015131 return -ENODEV;
15132}
15133
15134static struct isa_driver advansys_vlb_driver = {
15135 .probe = advansys_vlb_probe,
15136 .remove = __devexit_p(advansys_isa_remove),
15137 .driver = {
15138 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060015139 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015140 },
15141};
15142
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015143static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
15144 { "ABP7401" },
15145 { "ABP7501" },
15146 { "" }
15147};
15148
15149MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
15150
15151/*
15152 * EISA is a little more tricky than PCI; each EISA device may have two
15153 * channels, and this driver is written to make each channel its own Scsi_Host
15154 */
15155struct eisa_scsi_data {
15156 struct Scsi_Host *host[2];
15157};
15158
15159static int __devinit advansys_eisa_probe(struct device *dev)
15160{
15161 int i, ioport;
15162 int err;
15163 struct eisa_device *edev = to_eisa_device(dev);
15164 struct eisa_scsi_data *data;
15165
15166 err = -ENOMEM;
15167 data = kzalloc(sizeof(*data), GFP_KERNEL);
15168 if (!data)
15169 goto fail;
15170 ioport = edev->base_addr + 0xc30;
15171
15172 err = -ENODEV;
15173 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015174 if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
15175 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
15176 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015177 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015178 }
15179 if (!AscFindSignature(ioport)) {
15180 release_region(ioport, ASC_IOADR_GAP);
15181 continue;
15182 }
15183
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015184 /*
15185 * I don't know why we need to do this for EISA chips, but
15186 * not for any others. It looks to be equivalent to
15187 * AscGetChipCfgMsw, but I may have overlooked something,
15188 * so I'm not converting it until I get an EISA board to
15189 * test with.
15190 */
15191 inw(ioport + 4);
15192 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015193 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015194 err = 0;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015195 } else {
15196 release_region(ioport, ASC_IOADR_GAP);
15197 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015198 }
15199
15200 if (err) {
15201 kfree(data);
15202 } else {
15203 dev_set_drvdata(dev, data);
15204 }
15205
15206 fail:
15207 return err;
15208}
15209
15210static __devexit int advansys_eisa_remove(struct device *dev)
15211{
15212 int i;
15213 struct eisa_scsi_data *data = dev_get_drvdata(dev);
15214
15215 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015216 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015217 struct Scsi_Host *shost = data->host[i];
15218 if (!shost)
15219 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015220 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015221 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015222 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015223 }
15224
15225 kfree(data);
15226 return 0;
15227}
15228
15229static struct eisa_driver advansys_eisa_driver = {
15230 .id_table = advansys_eisa_table,
15231 .driver = {
15232 .name = "advansys",
15233 .probe = advansys_eisa_probe,
15234 .remove = __devexit_p(advansys_eisa_remove),
15235 }
15236};
15237
Dave Jones2672ea82006-08-02 17:11:49 -040015238/* PCI Devices supported by this driver */
15239static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015240 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
15241 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15242 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
15243 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15244 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
15245 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15246 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
15247 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15248 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
15249 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15250 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
15251 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15252 {}
Dave Jones2672ea82006-08-02 17:11:49 -040015253};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015254
Dave Jones2672ea82006-08-02 17:11:49 -040015255MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015256
Matthew Wilcox9649af32007-07-26 21:51:47 -060015257static void __devinit advansys_set_latency(struct pci_dev *pdev)
15258{
15259 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
15260 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
15261 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
15262 } else {
15263 u8 latency;
15264 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
15265 if (latency < 0x20)
15266 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
15267 }
15268}
15269
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015270static int __devinit
15271advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15272{
15273 int err, ioport;
15274 struct Scsi_Host *shost;
15275
15276 err = pci_enable_device(pdev);
15277 if (err)
15278 goto fail;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015279 err = pci_request_regions(pdev, "advansys");
15280 if (err)
15281 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060015282 pci_set_master(pdev);
15283 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015284
15285 if (pci_resource_len(pdev, 0) == 0)
15286 goto nodev;
15287
15288 ioport = pci_resource_start(pdev, 0);
15289 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
15290
15291 if (!shost)
15292 goto nodev;
15293
15294 pci_set_drvdata(pdev, shost);
15295 return 0;
15296
15297 nodev:
15298 err = -ENODEV;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015299 pci_release_regions(pdev);
15300 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015301 pci_disable_device(pdev);
15302 fail:
15303 return err;
15304}
15305
15306static void __devexit advansys_pci_remove(struct pci_dev *pdev)
15307{
15308 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015309 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015310 pci_disable_device(pdev);
15311}
15312
15313static struct pci_driver advansys_pci_driver = {
15314 .name = "advansys",
15315 .id_table = advansys_pci_tbl,
15316 .probe = advansys_pci_probe,
15317 .remove = __devexit_p(advansys_pci_remove),
15318};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015319
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015320static int __init advansys_init(void)
15321{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015322 int error;
15323
15324 error = isa_register_driver(&advansys_isa_driver,
15325 ASC_IOADR_TABLE_MAX_IX);
15326 if (error)
15327 goto fail;
15328
15329 error = isa_register_driver(&advansys_vlb_driver,
15330 ASC_IOADR_TABLE_MAX_IX);
15331 if (error)
15332 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015333
15334 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015335 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015336 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015337
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015338 error = pci_register_driver(&advansys_pci_driver);
15339 if (error)
15340 goto unregister_eisa;
15341
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015342 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015343
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015344 unregister_eisa:
15345 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015346 unregister_vlb:
15347 isa_unregister_driver(&advansys_vlb_driver);
15348 unregister_isa:
15349 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015350 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015351 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015352}
15353
15354static void __exit advansys_exit(void)
15355{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015356 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015357 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015358 isa_unregister_driver(&advansys_vlb_driver);
15359 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015360}
15361
15362module_init(advansys_init);
15363module_exit(advansys_exit);
15364
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015365MODULE_LICENSE("GPL");