blob: d7bc0cf72134b84131d3a9c325e5ef0ae9728fdc [file] [log] [blame]
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04001#define ASC_VERSION "3.4" /* AdvanSys Driver Version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3/*
4 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
5 *
6 * Copyright (c) 1995-2000 Advanced System Products, Inc.
7 * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04008 * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * All Rights Reserved.
10 *
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
19 * changed its name to ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040020 * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 */
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/string.h>
25#include <linux/kernel.h>
26#include <linux/types.h>
27#include <linux/ioport.h>
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <linux/slab.h>
31#include <linux/mm.h>
32#include <linux/proc_fs.h>
33#include <linux/init.h>
34#include <linux/blkdev.h>
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060035#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060036#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040037#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/spinlock.h>
39#include <linux/dma-mapping.h>
40
41#include <asm/io.h>
42#include <asm/system.h>
43#include <asm/dma.h>
44
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040045#include <scsi/scsi_cmnd.h>
46#include <scsi/scsi_device.h>
47#include <scsi/scsi_tcq.h>
48#include <scsi/scsi.h>
49#include <scsi/scsi_host.h>
50
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060051/* FIXME:
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 *
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060053 * 1. Although all of the necessary command mapping places have the
54 * appropriate dma_map.. APIs, the driver still processes its internal
55 * queue using bus_to_virt() and virt_to_bus() which are illegal under
56 * the API. The entire queue processing structure will need to be
57 * altered to fix this.
58 * 2. Need to add memory mapping workaround. Test the memory mapping.
59 * If it doesn't work revert to I/O port access. Can a test be done
60 * safely?
61 * 3. Handle an interrupt not working. Keep an interrupt counter in
62 * the interrupt handler. In the timeout function if the interrupt
63 * has not occurred then print a message and run in polled mode.
64 * 4. Need to add support for target mode commands, cf. CAM XPT.
65 * 5. check DMA mapping functions for failure
Matthew Wilcox349d2c42007-09-09 08:56:34 -060066 * 6. Use scsi_transport_spi
67 * 7. advansys_info is not safe against multiple simultaneous callers
68 * 8. Kill boardp->id
69 * 9. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 */
71#warning this driver is still not properly converted to the DMA API
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073/* Enable driver assertions. */
74#define ADVANSYS_ASSERT
75
76/* Enable driver /proc statistics. */
77#define ADVANSYS_STATS
78
79/* Enable driver tracing. */
80/* #define ADVANSYS_DEBUG */
81
Linus Torvalds1da177e2005-04-16 15:20:36 -070082/*
83 * --- Asc Library Constants and Macros
84 */
85
86#define ASC_LIB_VERSION_MAJOR 1
87#define ASC_LIB_VERSION_MINOR 24
88#define ASC_LIB_SERIAL_NUMBER 123
89
90/*
91 * Portable Data Types
92 *
93 * Any instance where a 32-bit long or pointer type is assumed
94 * for precision or HW defined structures, the following define
95 * types must be used. In Linux the char, short, and int types
96 * are all consistent at 8, 16, and 32 bits respectively. Pointers
97 * and long types are 64 bits on Alpha and UltraSPARC.
98 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040099#define ASC_PADDR __u32 /* Physical/Bus address data type. */
100#define ASC_VADDR __u32 /* Virtual address data type. */
101#define ASC_DCNT __u32 /* Unsigned Data count type. */
102#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104/*
105 * These macros are used to convert a virtual address to a
106 * 32-bit value. This currently can be used on Linux Alpha
107 * which uses 64-bit virtual address but a 32-bit bus address.
108 * This is likely to break in the future, but doing this now
109 * will give us time to change the HW and FW to handle 64-bit
110 * addresses.
111 */
112#define ASC_VADDR_TO_U32 virt_to_bus
113#define ASC_U32_TO_VADDR bus_to_virt
114
115typedef unsigned char uchar;
116
117#ifndef TRUE
118#define TRUE (1)
119#endif
120#ifndef FALSE
121#define FALSE (0)
122#endif
123
124#define EOF (-1)
125#define ERR (-1)
126#define UW_ERR (uint)(0xFFFF)
127#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
129#define ASC_DVCLIB_CALL_DONE (1)
130#define ASC_DVCLIB_CALL_FAILED (0)
131#define ASC_DVCLIB_CALL_ERROR (-1)
132
Dave Jones2672ea82006-08-02 17:11:49 -0400133#define PCI_VENDOR_ID_ASP 0x10cd
134#define PCI_DEVICE_ID_ASP_1200A 0x1100
135#define PCI_DEVICE_ID_ASP_ABP940 0x1200
136#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
137#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
138#define PCI_DEVICE_ID_38C0800_REV1 0x2500
139#define PCI_DEVICE_ID_38C1600_REV1 0x2700
140
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141/*
142 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
143 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
144 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
145 * SRB structure.
146 */
147#define CC_VERY_LONG_SG_LIST 0
148#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
149
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400150#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151#define inp(port) inb(port)
152#define outp(port, byte) outb((byte), (port))
153
154#define inpw(port) inw(port)
155#define outpw(port, word) outw((word), (port))
156
157#define ASC_MAX_SG_QUEUE 7
158#define ASC_MAX_SG_LIST 255
159
160#define ASC_CS_TYPE unsigned short
161
162#define ASC_IS_ISA (0x0001)
163#define ASC_IS_ISAPNP (0x0081)
164#define ASC_IS_EISA (0x0002)
165#define ASC_IS_PCI (0x0004)
166#define ASC_IS_PCI_ULTRA (0x0104)
167#define ASC_IS_PCMCIA (0x0008)
168#define ASC_IS_MCA (0x0020)
169#define ASC_IS_VL (0x0040)
170#define ASC_ISA_PNP_PORT_ADDR (0x279)
171#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
172#define ASC_IS_WIDESCSI_16 (0x0100)
173#define ASC_IS_WIDESCSI_32 (0x0200)
174#define ASC_IS_BIG_ENDIAN (0x8000)
175#define ASC_CHIP_MIN_VER_VL (0x01)
176#define ASC_CHIP_MAX_VER_VL (0x07)
177#define ASC_CHIP_MIN_VER_PCI (0x09)
178#define ASC_CHIP_MAX_VER_PCI (0x0F)
179#define ASC_CHIP_VER_PCI_BIT (0x08)
180#define ASC_CHIP_MIN_VER_ISA (0x11)
181#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
182#define ASC_CHIP_MAX_VER_ISA (0x27)
183#define ASC_CHIP_VER_ISA_BIT (0x30)
184#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
185#define ASC_CHIP_VER_ASYN_BUG (0x21)
186#define ASC_CHIP_VER_PCI 0x08
187#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
188#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
189#define ASC_CHIP_MIN_VER_EISA (0x41)
190#define ASC_CHIP_MAX_VER_EISA (0x47)
191#define ASC_CHIP_VER_EISA_BIT (0x40)
192#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
193#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
194#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
195#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
196#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
197#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
198#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
199#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
200#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
201#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
202#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
203
204#define ASC_SCSI_ID_BITS 3
205#define ASC_SCSI_TIX_TYPE uchar
206#define ASC_ALL_DEVICE_BIT_SET 0xFF
207#define ASC_SCSI_BIT_ID_TYPE uchar
208#define ASC_MAX_TID 7
209#define ASC_MAX_LUN 7
210#define ASC_SCSI_WIDTH_BIT_SET 0xFF
211#define ASC_MAX_SENSE_LEN 32
212#define ASC_MIN_SENSE_LEN 14
213#define ASC_MAX_CDB_LEN 12
214#define ASC_SCSI_RESET_HOLD_TIME_US 60
215
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216/*
217 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
218 * and CmdDt (Command Support Data) field bit definitions.
219 */
220#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
221#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
222#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
223#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
224
225#define ASC_SCSIDIR_NOCHK 0x00
226#define ASC_SCSIDIR_T2H 0x08
227#define ASC_SCSIDIR_H2T 0x10
228#define ASC_SCSIDIR_NODATA 0x18
229#define SCSI_ASC_NOMEDIA 0x3A
230#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
231#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
232#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
233#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237#define ASC_SG_LIST_PER_Q 7
238#define QS_FREE 0x00
239#define QS_READY 0x01
240#define QS_DISC1 0x02
241#define QS_DISC2 0x04
242#define QS_BUSY 0x08
243#define QS_ABORTED 0x40
244#define QS_DONE 0x80
245#define QC_NO_CALLBACK 0x01
246#define QC_SG_SWAP_QUEUE 0x02
247#define QC_SG_HEAD 0x04
248#define QC_DATA_IN 0x08
249#define QC_DATA_OUT 0x10
250#define QC_URGENT 0x20
251#define QC_MSG_OUT 0x40
252#define QC_REQ_SENSE 0x80
253#define QCSG_SG_XFER_LIST 0x02
254#define QCSG_SG_XFER_MORE 0x04
255#define QCSG_SG_XFER_END 0x08
256#define QD_IN_PROGRESS 0x00
257#define QD_NO_ERROR 0x01
258#define QD_ABORTED_BY_HOST 0x02
259#define QD_WITH_ERROR 0x04
260#define QD_INVALID_REQUEST 0x80
261#define QD_INVALID_HOST_NUM 0x81
262#define QD_INVALID_DEVICE 0x82
263#define QD_ERR_INTERNAL 0xFF
264#define QHSTA_NO_ERROR 0x00
265#define QHSTA_M_SEL_TIMEOUT 0x11
266#define QHSTA_M_DATA_OVER_RUN 0x12
267#define QHSTA_M_DATA_UNDER_RUN 0x12
268#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
269#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
270#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
271#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
272#define QHSTA_D_HOST_ABORT_FAILED 0x23
273#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
274#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
275#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
276#define QHSTA_M_WTM_TIMEOUT 0x41
277#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
278#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
279#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
280#define QHSTA_M_TARGET_STATUS_BUSY 0x45
281#define QHSTA_M_BAD_TAG_CODE 0x46
282#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
283#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
284#define QHSTA_D_LRAM_CMP_ERROR 0x81
285#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
286#define ASC_FLAG_SCSIQ_REQ 0x01
287#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
288#define ASC_FLAG_BIOS_ASYNC_IO 0x04
289#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
290#define ASC_FLAG_WIN16 0x10
291#define ASC_FLAG_WIN32 0x20
292#define ASC_FLAG_ISA_OVER_16MB 0x40
293#define ASC_FLAG_DOS_VM_CALLBACK 0x80
294#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
295#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
296#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
297#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
298#define ASC_SCSIQ_CPY_BEG 4
299#define ASC_SCSIQ_SGHD_CPY_BEG 2
300#define ASC_SCSIQ_B_FWD 0
301#define ASC_SCSIQ_B_BWD 1
302#define ASC_SCSIQ_B_STATUS 2
303#define ASC_SCSIQ_B_QNO 3
304#define ASC_SCSIQ_B_CNTL 4
305#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
306#define ASC_SCSIQ_D_DATA_ADDR 8
307#define ASC_SCSIQ_D_DATA_CNT 12
308#define ASC_SCSIQ_B_SENSE_LEN 20
309#define ASC_SCSIQ_DONE_INFO_BEG 22
310#define ASC_SCSIQ_D_SRBPTR 22
311#define ASC_SCSIQ_B_TARGET_IX 26
312#define ASC_SCSIQ_B_CDB_LEN 28
313#define ASC_SCSIQ_B_TAG_CODE 29
314#define ASC_SCSIQ_W_VM_ID 30
315#define ASC_SCSIQ_DONE_STATUS 32
316#define ASC_SCSIQ_HOST_STATUS 33
317#define ASC_SCSIQ_SCSI_STATUS 34
318#define ASC_SCSIQ_CDB_BEG 36
319#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
320#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
321#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
322#define ASC_SCSIQ_B_SG_WK_QP 49
323#define ASC_SCSIQ_B_SG_WK_IX 50
324#define ASC_SCSIQ_W_ALT_DC1 52
325#define ASC_SCSIQ_B_LIST_CNT 6
326#define ASC_SCSIQ_B_CUR_LIST_CNT 7
327#define ASC_SGQ_B_SG_CNTL 4
328#define ASC_SGQ_B_SG_HEAD_QP 5
329#define ASC_SGQ_B_SG_LIST_CNT 6
330#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
331#define ASC_SGQ_LIST_BEG 8
332#define ASC_DEF_SCSI1_QNG 4
333#define ASC_MAX_SCSI1_QNG 4
334#define ASC_DEF_SCSI2_QNG 16
335#define ASC_MAX_SCSI2_QNG 32
336#define ASC_TAG_CODE_MASK 0x23
337#define ASC_STOP_REQ_RISC_STOP 0x01
338#define ASC_STOP_ACK_RISC_STOP 0x03
339#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
340#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
341#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
342#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
343#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
344#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
345#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
346#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
347#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
348#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
349
350typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400351 uchar status;
352 uchar q_no;
353 uchar cntl;
354 uchar sg_queue_cnt;
355 uchar target_id;
356 uchar target_lun;
357 ASC_PADDR data_addr;
358 ASC_DCNT data_cnt;
359 ASC_PADDR sense_addr;
360 uchar sense_len;
361 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362} ASC_SCSIQ_1;
363
364typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400365 ASC_VADDR srb_ptr;
366 uchar target_ix;
367 uchar flag;
368 uchar cdb_len;
369 uchar tag_code;
370 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371} ASC_SCSIQ_2;
372
373typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400374 uchar done_stat;
375 uchar host_stat;
376 uchar scsi_stat;
377 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378} ASC_SCSIQ_3;
379
380typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400381 uchar cdb[ASC_MAX_CDB_LEN];
382 uchar y_first_sg_list_qp;
383 uchar y_working_sg_qp;
384 uchar y_working_sg_ix;
385 uchar y_res;
386 ushort x_req_count;
387 ushort x_reconnect_rtn;
388 ASC_PADDR x_saved_data_addr;
389 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390} ASC_SCSIQ_4;
391
392typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400393 ASC_SCSIQ_2 d2;
394 ASC_SCSIQ_3 d3;
395 uchar q_status;
396 uchar q_no;
397 uchar cntl;
398 uchar sense_len;
399 uchar extra_bytes;
400 uchar res;
401 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402} ASC_QDONE_INFO;
403
404typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400405 ASC_PADDR addr;
406 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407} ASC_SG_LIST;
408
409typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400410 ushort entry_cnt;
411 ushort queue_cnt;
412 ushort entry_to_copy;
413 ushort res;
414 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415} ASC_SG_HEAD;
416
417#define ASC_MIN_SG_LIST 2
418
419typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400420 ushort entry_cnt;
421 ushort queue_cnt;
422 ushort entry_to_copy;
423 ushort res;
424 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425} ASC_MIN_SG_HEAD;
426
427#define QCX_SORT (0x0001)
428#define QCX_COALEASE (0x0002)
429
430typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400431 ASC_SCSIQ_1 q1;
432 ASC_SCSIQ_2 q2;
433 uchar *cdbptr;
434 ASC_SG_HEAD *sg_head;
435 ushort remain_sg_entry_cnt;
436 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437} ASC_SCSI_Q;
438
439typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400440 ASC_SCSIQ_1 r1;
441 ASC_SCSIQ_2 r2;
442 uchar *cdbptr;
443 ASC_SG_HEAD *sg_head;
444 uchar *sense_ptr;
445 ASC_SCSIQ_3 r3;
446 uchar cdb[ASC_MAX_CDB_LEN];
447 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448} ASC_SCSI_REQ_Q;
449
450typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400451 ASC_SCSIQ_1 r1;
452 ASC_SCSIQ_2 r2;
453 uchar *cdbptr;
454 ASC_SG_HEAD *sg_head;
455 uchar *sense_ptr;
456 ASC_SCSIQ_3 r3;
457 uchar cdb[ASC_MAX_CDB_LEN];
458 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459} ASC_SCSI_BIOS_REQ_Q;
460
461typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400462 uchar fwd;
463 uchar bwd;
464 ASC_SCSIQ_1 i1;
465 ASC_SCSIQ_2 i2;
466 ASC_SCSIQ_3 i3;
467 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468} ASC_RISC_Q;
469
470typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400471 uchar seq_no;
472 uchar q_no;
473 uchar cntl;
474 uchar sg_head_qp;
475 uchar sg_list_cnt;
476 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477} ASC_SG_LIST_Q;
478
479typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400480 uchar fwd;
481 uchar bwd;
482 ASC_SG_LIST_Q sg;
483 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484} ASC_RISC_SG_LIST_Q;
485
486#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
487#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
488#define ASCQ_ERR_NO_ERROR 0
489#define ASCQ_ERR_IO_NOT_FOUND 1
490#define ASCQ_ERR_LOCAL_MEM 2
491#define ASCQ_ERR_CHKSUM 3
492#define ASCQ_ERR_START_CHIP 4
493#define ASCQ_ERR_INT_TARGET_ID 5
494#define ASCQ_ERR_INT_LOCAL_MEM 6
495#define ASCQ_ERR_HALT_RISC 7
496#define ASCQ_ERR_GET_ASPI_ENTRY 8
497#define ASCQ_ERR_CLOSE_ASPI 9
498#define ASCQ_ERR_HOST_INQUIRY 0x0A
499#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
500#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
501#define ASCQ_ERR_Q_STATUS 0x0D
502#define ASCQ_ERR_WR_SCSIQ 0x0E
503#define ASCQ_ERR_PC_ADDR 0x0F
504#define ASCQ_ERR_SYN_OFFSET 0x10
505#define ASCQ_ERR_SYN_XFER_TIME 0x11
506#define ASCQ_ERR_LOCK_DMA 0x12
507#define ASCQ_ERR_UNLOCK_DMA 0x13
508#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
509#define ASCQ_ERR_MICRO_CODE_HALT 0x15
510#define ASCQ_ERR_SET_LRAM_ADDR 0x16
511#define ASCQ_ERR_CUR_QNG 0x17
512#define ASCQ_ERR_SG_Q_LINKS 0x18
513#define ASCQ_ERR_SCSIQ_PTR 0x19
514#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
515#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
516#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
517#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
518#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
519#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
520#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
521#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
522#define ASCQ_ERR_SEND_SCSI_Q 0x22
523#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
524#define ASCQ_ERR_RESET_SDTR 0x24
525
526/*
527 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
528 */
529#define ASC_WARN_NO_ERROR 0x0000
530#define ASC_WARN_IO_PORT_ROTATE 0x0001
531#define ASC_WARN_EEPROM_CHKSUM 0x0002
532#define ASC_WARN_IRQ_MODIFIED 0x0004
533#define ASC_WARN_AUTO_CONFIG 0x0008
534#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
535#define ASC_WARN_EEPROM_RECOVER 0x0020
536#define ASC_WARN_CFG_MSW_RECOVER 0x0040
537#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
538
539/*
540 * Error code values are set in ASC_DVC_VAR 'err_code'.
541 */
542#define ASC_IERR_WRITE_EEPROM 0x0001
543#define ASC_IERR_MCODE_CHKSUM 0x0002
544#define ASC_IERR_SET_PC_ADDR 0x0004
545#define ASC_IERR_START_STOP_CHIP 0x0008
546#define ASC_IERR_IRQ_NO 0x0010
547#define ASC_IERR_SET_IRQ_NO 0x0020
548#define ASC_IERR_CHIP_VERSION 0x0040
549#define ASC_IERR_SET_SCSI_ID 0x0080
550#define ASC_IERR_GET_PHY_ADDR 0x0100
551#define ASC_IERR_BAD_SIGNATURE 0x0200
552#define ASC_IERR_NO_BUS_TYPE 0x0400
553#define ASC_IERR_SCAM 0x0800
554#define ASC_IERR_SET_SDTR 0x1000
555#define ASC_IERR_RW_LRAM 0x8000
556
557#define ASC_DEF_IRQ_NO 10
558#define ASC_MAX_IRQ_NO 15
559#define ASC_MIN_IRQ_NO 10
560#define ASC_MIN_REMAIN_Q (0x02)
561#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
562#define ASC_MIN_TAG_Q_PER_DVC (0x04)
563#define ASC_DEF_TAG_Q_PER_DVC (0x04)
564#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
565#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
566#define ASC_MAX_TOTAL_QNG 240
567#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
568#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
569#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
570#define ASC_MAX_INRAM_TAG_QNG 16
571#define ASC_IOADR_TABLE_MAX_IX 11
572#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573#define ASC_LIB_SCSIQ_WK_SP 256
574#define ASC_MAX_SYN_XFER_NO 16
575#define ASC_SYN_MAX_OFFSET 0x0F
576#define ASC_DEF_SDTR_OFFSET 0x0F
577#define ASC_DEF_SDTR_INDEX 0x00
578#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
579#define SYN_XFER_NS_0 25
580#define SYN_XFER_NS_1 30
581#define SYN_XFER_NS_2 35
582#define SYN_XFER_NS_3 40
583#define SYN_XFER_NS_4 50
584#define SYN_XFER_NS_5 60
585#define SYN_XFER_NS_6 70
586#define SYN_XFER_NS_7 85
587#define SYN_ULTRA_XFER_NS_0 12
588#define SYN_ULTRA_XFER_NS_1 19
589#define SYN_ULTRA_XFER_NS_2 25
590#define SYN_ULTRA_XFER_NS_3 32
591#define SYN_ULTRA_XFER_NS_4 38
592#define SYN_ULTRA_XFER_NS_5 44
593#define SYN_ULTRA_XFER_NS_6 50
594#define SYN_ULTRA_XFER_NS_7 57
595#define SYN_ULTRA_XFER_NS_8 63
596#define SYN_ULTRA_XFER_NS_9 69
597#define SYN_ULTRA_XFER_NS_10 75
598#define SYN_ULTRA_XFER_NS_11 82
599#define SYN_ULTRA_XFER_NS_12 88
600#define SYN_ULTRA_XFER_NS_13 94
601#define SYN_ULTRA_XFER_NS_14 100
602#define SYN_ULTRA_XFER_NS_15 107
603
604typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400605 uchar msg_type;
606 uchar msg_len;
607 uchar msg_req;
608 union {
609 struct {
610 uchar sdtr_xfer_period;
611 uchar sdtr_req_ack_offset;
612 } sdtr;
613 struct {
614 uchar wdtr_width;
615 } wdtr;
616 struct {
617 uchar mdp_b3;
618 uchar mdp_b2;
619 uchar mdp_b1;
620 uchar mdp_b0;
621 } mdp;
622 } u_ext_msg;
623 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624} EXT_MSG;
625
626#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
627#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
628#define wdtr_width u_ext_msg.wdtr.wdtr_width
629#define mdp_b3 u_ext_msg.mdp_b3
630#define mdp_b2 u_ext_msg.mdp_b2
631#define mdp_b1 u_ext_msg.mdp_b1
632#define mdp_b0 u_ext_msg.mdp_b0
633
634typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400635 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
636 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
637 ASC_SCSI_BIT_ID_TYPE disc_enable;
638 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
639 uchar chip_scsi_id;
640 uchar isa_dma_speed;
641 uchar isa_dma_channel;
642 uchar chip_version;
643 ushort lib_serial_no;
644 ushort lib_version;
645 ushort mcode_date;
646 ushort mcode_version;
647 uchar max_tag_qng[ASC_MAX_TID + 1];
648 uchar *overrun_buf;
649 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400650 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651} ASC_DVC_CFG;
652
653#define ASC_DEF_DVC_CNTL 0xFFFF
654#define ASC_DEF_CHIP_SCSI_ID 7
655#define ASC_DEF_ISA_DMA_SPEED 4
656#define ASC_INIT_STATE_NULL 0x0000
657#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
658#define ASC_INIT_STATE_END_GET_CFG 0x0002
659#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
660#define ASC_INIT_STATE_END_SET_CFG 0x0008
661#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
662#define ASC_INIT_STATE_END_LOAD_MC 0x0020
663#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
664#define ASC_INIT_STATE_END_INQUIRY 0x0080
665#define ASC_INIT_RESET_SCSI_DONE 0x0100
666#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
668#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
669#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
670#define ASC_MIN_TAGGED_CMD 7
671#define ASC_MAX_SCSI_RESET_WAIT 30
672
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400673struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400676 PortAddr iop_base;
677 ushort err_code;
678 ushort dvc_cntl;
679 ushort bug_fix_cntl;
680 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400681 ASC_SCSI_BIT_ID_TYPE init_sdtr;
682 ASC_SCSI_BIT_ID_TYPE sdtr_done;
683 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
684 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
685 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
686 ASC_SCSI_BIT_ID_TYPE start_motor;
687 uchar scsi_reset_wait;
688 uchar chip_no;
689 char is_in_int;
690 uchar max_total_qng;
691 uchar cur_total_qng;
692 uchar in_critical_cnt;
693 uchar irq_no;
694 uchar last_q_shortage;
695 ushort init_state;
696 uchar cur_dvc_qng[ASC_MAX_TID + 1];
697 uchar max_dvc_qng[ASC_MAX_TID + 1];
698 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
699 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
700 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
701 ASC_DVC_CFG *cfg;
702 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
703 char redo_scam;
704 ushort res2;
705 uchar dos_int13_table[ASC_MAX_TID + 1];
706 ASC_DCNT max_dma_count;
707 ASC_SCSI_BIT_ID_TYPE no_scam;
708 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
709 uchar max_sdtr_index;
710 uchar host_init_sdtr_index;
711 struct asc_board *drv_ptr;
712 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713} ASC_DVC_VAR;
714
715typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400716 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717} ASC_DVC_INQ_INFO;
718
719typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400720 ASC_DCNT lba;
721 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722} ASC_CAP_INFO;
723
724typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400725 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726} ASC_CAP_INFO_ARRAY;
727
728#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
729#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
730#define ASC_CNTL_INITIATOR (ushort)0x0001
731#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
732#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
733#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
734#define ASC_CNTL_NO_SCAM (ushort)0x0010
735#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
736#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
737#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
738#define ASC_CNTL_RESET_SCSI (ushort)0x0200
739#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
740#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
741#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
742#define ASC_CNTL_BURST_MODE (ushort)0x2000
743#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
744#define ASC_EEP_DVC_CFG_BEG_VL 2
745#define ASC_EEP_MAX_DVC_ADDR_VL 15
746#define ASC_EEP_DVC_CFG_BEG 32
747#define ASC_EEP_MAX_DVC_ADDR 45
748#define ASC_EEP_DEFINED_WORDS 10
749#define ASC_EEP_MAX_ADDR 63
750#define ASC_EEP_RES_WORDS 0
751#define ASC_EEP_MAX_RETRY 20
752#define ASC_MAX_INIT_BUSY_RETRY 8
753#define ASC_EEP_ISA_PNP_WSIZE 16
754
755/*
756 * These macros keep the chip SCSI id and ISA DMA speed
757 * bitfields in board order. C bitfields aren't portable
758 * between big and little-endian platforms so they are
759 * not used.
760 */
761
762#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
763#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
764#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
765 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
766#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
767 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
768
769typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400770 ushort cfg_lsw;
771 ushort cfg_msw;
772 uchar init_sdtr;
773 uchar disc_enable;
774 uchar use_cmd_qng;
775 uchar start_motor;
776 uchar max_total_qng;
777 uchar max_tag_qng;
778 uchar bios_scan;
779 uchar power_up_wait;
780 uchar no_scam;
781 uchar id_speed; /* low order 4 bits is chip scsi id */
782 /* high order 4 bits is isa dma speed */
783 uchar dos_int13_table[ASC_MAX_TID + 1];
784 uchar adapter_info[6];
785 ushort cntl;
786 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787} ASCEEP_CONFIG;
788
789#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
790#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
791#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
792
793#define ASC_EEP_CMD_READ 0x80
794#define ASC_EEP_CMD_WRITE 0x40
795#define ASC_EEP_CMD_WRITE_ABLE 0x30
796#define ASC_EEP_CMD_WRITE_DISABLE 0x00
797#define ASC_OVERRUN_BSIZE 0x00000048UL
798#define ASC_CTRL_BREAK_ONCE 0x0001
799#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
800#define ASCV_MSGOUT_BEG 0x0000
801#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
802#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
803#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
804#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
805#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
806#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
807#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
808#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
809#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
810#define ASCV_BREAK_ADDR (ushort)0x0028
811#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
812#define ASCV_BREAK_CONTROL (ushort)0x002C
813#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
814
815#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
816#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
817#define ASCV_MCODE_SIZE_W (ushort)0x0034
818#define ASCV_STOP_CODE_B (ushort)0x0036
819#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
820#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
821#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
822#define ASCV_HALTCODE_W (ushort)0x0040
823#define ASCV_CHKSUM_W (ushort)0x0042
824#define ASCV_MC_DATE_W (ushort)0x0044
825#define ASCV_MC_VER_W (ushort)0x0046
826#define ASCV_NEXTRDY_B (ushort)0x0048
827#define ASCV_DONENEXT_B (ushort)0x0049
828#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
829#define ASCV_SCSIBUSY_B (ushort)0x004B
830#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
831#define ASCV_CURCDB_B (ushort)0x004D
832#define ASCV_RCLUN_B (ushort)0x004E
833#define ASCV_BUSY_QHEAD_B (ushort)0x004F
834#define ASCV_DISC1_QHEAD_B (ushort)0x0050
835#define ASCV_DISC_ENABLE_B (ushort)0x0052
836#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
837#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
838#define ASCV_MCODE_CNTL_B (ushort)0x0056
839#define ASCV_NULL_TARGET_B (ushort)0x0057
840#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
841#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
842#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
843#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
844#define ASCV_HOST_FLAG_B (ushort)0x005D
845#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
846#define ASCV_VER_SERIAL_B (ushort)0x0065
847#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
848#define ASCV_WTM_FLAG_B (ushort)0x0068
849#define ASCV_RISC_FLAG_B (ushort)0x006A
850#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
851#define ASC_HOST_FLAG_IN_ISR 0x01
852#define ASC_HOST_FLAG_ACK_INT 0x02
853#define ASC_RISC_FLAG_GEN_INT 0x01
854#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
855#define IOP_CTRL (0x0F)
856#define IOP_STATUS (0x0E)
857#define IOP_INT_ACK IOP_STATUS
858#define IOP_REG_IFC (0x0D)
859#define IOP_SYN_OFFSET (0x0B)
860#define IOP_EXTRA_CONTROL (0x0D)
861#define IOP_REG_PC (0x0C)
862#define IOP_RAM_ADDR (0x0A)
863#define IOP_RAM_DATA (0x08)
864#define IOP_EEP_DATA (0x06)
865#define IOP_EEP_CMD (0x07)
866#define IOP_VERSION (0x03)
867#define IOP_CONFIG_HIGH (0x04)
868#define IOP_CONFIG_LOW (0x02)
869#define IOP_SIG_BYTE (0x01)
870#define IOP_SIG_WORD (0x00)
871#define IOP_REG_DC1 (0x0E)
872#define IOP_REG_DC0 (0x0C)
873#define IOP_REG_SB (0x0B)
874#define IOP_REG_DA1 (0x0A)
875#define IOP_REG_DA0 (0x08)
876#define IOP_REG_SC (0x09)
877#define IOP_DMA_SPEED (0x07)
878#define IOP_REG_FLAG (0x07)
879#define IOP_FIFO_H (0x06)
880#define IOP_FIFO_L (0x04)
881#define IOP_REG_ID (0x05)
882#define IOP_REG_QP (0x03)
883#define IOP_REG_IH (0x02)
884#define IOP_REG_IX (0x01)
885#define IOP_REG_AX (0x00)
886#define IFC_REG_LOCK (0x00)
887#define IFC_REG_UNLOCK (0x09)
888#define IFC_WR_EN_FILTER (0x10)
889#define IFC_RD_NO_EEPROM (0x10)
890#define IFC_SLEW_RATE (0x20)
891#define IFC_ACT_NEG (0x40)
892#define IFC_INP_FILTER (0x80)
893#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
894#define SC_SEL (uchar)(0x80)
895#define SC_BSY (uchar)(0x40)
896#define SC_ACK (uchar)(0x20)
897#define SC_REQ (uchar)(0x10)
898#define SC_ATN (uchar)(0x08)
899#define SC_IO (uchar)(0x04)
900#define SC_CD (uchar)(0x02)
901#define SC_MSG (uchar)(0x01)
902#define SEC_SCSI_CTL (uchar)(0x80)
903#define SEC_ACTIVE_NEGATE (uchar)(0x40)
904#define SEC_SLEW_RATE (uchar)(0x20)
905#define SEC_ENABLE_FILTER (uchar)(0x10)
906#define ASC_HALT_EXTMSG_IN (ushort)0x8000
907#define ASC_HALT_CHK_CONDITION (ushort)0x8100
908#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
909#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
910#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
911#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
912#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
913#define ASC_MAX_QNO 0xF8
914#define ASC_DATA_SEC_BEG (ushort)0x0080
915#define ASC_DATA_SEC_END (ushort)0x0080
916#define ASC_CODE_SEC_BEG (ushort)0x0080
917#define ASC_CODE_SEC_END (ushort)0x0080
918#define ASC_QADR_BEG (0x4000)
919#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
920#define ASC_QADR_END (ushort)0x7FFF
921#define ASC_QLAST_ADR (ushort)0x7FC0
922#define ASC_QBLK_SIZE 0x40
923#define ASC_BIOS_DATA_QBEG 0xF8
924#define ASC_MIN_ACTIVE_QNO 0x01
925#define ASC_QLINK_END 0xFF
926#define ASC_EEPROM_WORDS 0x10
927#define ASC_MAX_MGS_LEN 0x10
928#define ASC_BIOS_ADDR_DEF 0xDC00
929#define ASC_BIOS_SIZE 0x3800
930#define ASC_BIOS_RAM_OFF 0x3800
931#define ASC_BIOS_RAM_SIZE 0x800
932#define ASC_BIOS_MIN_ADDR 0xC000
933#define ASC_BIOS_MAX_ADDR 0xEC00
934#define ASC_BIOS_BANK_SIZE 0x0400
935#define ASC_MCODE_START_ADDR 0x0080
936#define ASC_CFG0_HOST_INT_ON 0x0020
937#define ASC_CFG0_BIOS_ON 0x0040
938#define ASC_CFG0_VERA_BURST_ON 0x0080
939#define ASC_CFG0_SCSI_PARITY_ON 0x0800
940#define ASC_CFG1_SCSI_TARGET_ON 0x0080
941#define ASC_CFG1_LRAM_8BITS_ON 0x0800
942#define ASC_CFG_MSW_CLR_MASK 0x3080
943#define CSW_TEST1 (ASC_CS_TYPE)0x8000
944#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
945#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
946#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
947#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
948#define CSW_TEST2 (ASC_CS_TYPE)0x0400
949#define CSW_TEST3 (ASC_CS_TYPE)0x0200
950#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
951#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
952#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
953#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
954#define CSW_HALTED (ASC_CS_TYPE)0x0010
955#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
956#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
957#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
958#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
959#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
960#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
961#define CIW_TEST1 (ASC_CS_TYPE)0x0200
962#define CIW_TEST2 (ASC_CS_TYPE)0x0400
963#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
964#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
965#define CC_CHIP_RESET (uchar)0x80
966#define CC_SCSI_RESET (uchar)0x40
967#define CC_HALT (uchar)0x20
968#define CC_SINGLE_STEP (uchar)0x10
969#define CC_DMA_ABLE (uchar)0x08
970#define CC_TEST (uchar)0x04
971#define CC_BANK_ONE (uchar)0x02
972#define CC_DIAG (uchar)0x01
973#define ASC_1000_ID0W 0x04C1
974#define ASC_1000_ID0W_FIX 0x00C1
975#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976#define ASC_EISA_REV_IOP_MASK (0x0C83)
977#define ASC_EISA_PID_IOP_MASK (0x0C80)
978#define ASC_EISA_CFG_IOP_MASK (0x0C86)
979#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980#define INS_HALTINT (ushort)0x6281
981#define INS_HALT (ushort)0x6280
982#define INS_SINT (ushort)0x6200
983#define INS_RFLAG_WTM (ushort)0x7380
984#define ASC_MC_SAVE_CODE_WSIZE 0x500
985#define ASC_MC_SAVE_DATA_WSIZE 0x40
986
987typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400988 ushort data[ASC_MC_SAVE_DATA_WSIZE];
989 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990} ASC_MC_SAVED;
991
992#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
993#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
994#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
995#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
996#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
997#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
998#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
999#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1000#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1001#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1002#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1003#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1004#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1005#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1006#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1007#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1008#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1009#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1010#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1011#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1012#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1013#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1014#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1015#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1016#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1017#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1018#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1019#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1020#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1021#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1022#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1023#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1024#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1025#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1026#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1027#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1028#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1029#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1030#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1031#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1032#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1033#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1034#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1035#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1036#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1037#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1038#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1039#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1040#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1041#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1042#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1043#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1044#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1045#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1046#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1047#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1048#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1049#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1050#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1051#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1052#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1053#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1054#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1055#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1056#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1057#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1058#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1059#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001061static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1062static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1063static void AscWaitEEPRead(void);
1064static void AscWaitEEPWrite(void);
1065static ushort AscReadEEPWord(PortAddr, uchar);
1066static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1067static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1068static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1069static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1070static int AscStartChip(PortAddr);
1071static int AscStopChip(PortAddr);
1072static void AscSetChipIH(PortAddr, ushort);
1073static int AscIsChipHalted(PortAddr);
1074static void AscAckInterrupt(PortAddr);
1075static void AscDisableInterrupt(PortAddr);
1076static void AscEnableInterrupt(PortAddr);
1077static void AscSetBank(PortAddr, uchar);
1078static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001080static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001082static uchar AscReadLramByte(PortAddr, ushort);
1083static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001085static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001087static void AscWriteLramWord(PortAddr, ushort, ushort);
1088static void AscWriteLramByte(PortAddr, ushort, uchar);
1089static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1090static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1091static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1092static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1093static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1094static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1095static ushort AscInitFromEEP(ASC_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001096static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1097static int AscTestExternalLram(ASC_DVC_VAR *);
1098static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1099static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1100static void AscSetChipSDTR(PortAddr, uchar, uchar);
1101static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1102static uchar AscAllocFreeQueue(PortAddr, uchar);
1103static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1104static int AscHostReqRiscHalt(PortAddr);
1105static int AscStopQueueExe(PortAddr);
1106static int AscSendScsiQueue(ASC_DVC_VAR *,
1107 ASC_SCSI_Q *scsiq, uchar n_q_required);
1108static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1109static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1110static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1111static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1112static ushort AscInitLram(ASC_DVC_VAR *);
1113static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1114static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1115static int AscIsrChipHalted(ASC_DVC_VAR *);
1116static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1117 ASC_QDONE_INFO *, ASC_DCNT);
1118static int AscIsrQDone(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001120static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001122static uchar AscGetChipScsiCtrl(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001123static uchar AscGetChipVersion(PortAddr, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001124static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001125static void AscToggleIRQAct(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001126static inline ulong DvcEnterCritical(void);
1127static inline void DvcLeaveCritical(ulong);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001128static void DvcSleepMilliSecond(ASC_DCNT);
1129static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1130static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1131static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001132static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04001133static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001134static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1135static int AscISR(ASC_DVC_VAR *);
1136static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1137static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001139static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001141static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143/*
1144 * --- Adv Library Constants and Macros
1145 */
1146
1147#define ADV_LIB_VERSION_MAJOR 5
1148#define ADV_LIB_VERSION_MINOR 14
1149
1150/*
1151 * Define Adv Library required special types.
1152 */
1153
1154/*
1155 * Portable Data Types
1156 *
1157 * Any instance where a 32-bit long or pointer type is assumed
1158 * for precision or HW defined structures, the following define
1159 * types must be used. In Linux the char, short, and int types
1160 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1161 * and long types are 64 bits on Alpha and UltraSPARC.
1162 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001163#define ADV_PADDR __u32 /* Physical address data type. */
1164#define ADV_VADDR __u32 /* Virtual address data type. */
1165#define ADV_DCNT __u32 /* Unsigned Data count type. */
1166#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
1168/*
1169 * These macros are used to convert a virtual address to a
1170 * 32-bit value. This currently can be used on Linux Alpha
1171 * which uses 64-bit virtual address but a 32-bit bus address.
1172 * This is likely to break in the future, but doing this now
1173 * will give us time to change the HW and FW to handle 64-bit
1174 * addresses.
1175 */
1176#define ADV_VADDR_TO_U32 virt_to_bus
1177#define ADV_U32_TO_VADDR bus_to_virt
1178
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001179#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
1181/*
1182 * Define Adv Library required memory access macros.
1183 */
1184#define ADV_MEM_READB(addr) readb(addr)
1185#define ADV_MEM_READW(addr) readw(addr)
1186#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1187#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1188#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1189
1190#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1191
1192/*
1193 * For wide boards a CDB length maximum of 16 bytes
1194 * is supported.
1195 */
1196#define ADV_MAX_CDB_LEN 16
1197
1198/*
1199 * Define total number of simultaneous maximum element scatter-gather
1200 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1201 * maximum number of outstanding commands per wide host adapter. Each
1202 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1203 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1204 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1205 * structures or 255 scatter-gather elements.
1206 *
1207 */
1208#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1209
1210/*
1211 * Define Adv Library required maximum number of scatter-gather
1212 * elements per request.
1213 */
1214#define ADV_MAX_SG_LIST 255
1215
1216/* Number of SG blocks needed. */
1217#define ADV_NUM_SG_BLOCK \
1218 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1219
1220/* Total contiguous memory needed for SG blocks. */
1221#define ADV_SG_TOTAL_MEM_SIZE \
1222 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1223
1224#define ADV_PAGE_SIZE PAGE_SIZE
1225
1226#define ADV_NUM_PAGE_CROSSING \
1227 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1230#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001231#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1233
1234#define ADV_EEP_DELAY_MS 100
1235
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001236#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1237#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238/*
1239 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1240 * For later ICs Bit 13 controls whether the CIS (Card Information
1241 * Service Section) is loaded from EEPROM.
1242 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001243#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1244#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245/*
1246 * ASC38C1600 Bit 11
1247 *
1248 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1249 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1250 * Function 0 will specify INT B.
1251 *
1252 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1253 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1254 * Function 1 will specify INT A.
1255 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001256#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001258typedef struct adveep_3550_config {
1259 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001261 ushort cfg_lsw; /* 00 power up initialization */
1262 /* bit 13 set - Term Polarity Control */
1263 /* bit 14 set - BIOS Enable */
1264 /* bit 15 set - Big Endian Mode */
1265 ushort cfg_msw; /* 01 unused */
1266 ushort disc_enable; /* 02 disconnect enable */
1267 ushort wdtr_able; /* 03 Wide DTR able */
1268 ushort sdtr_able; /* 04 Synchronous DTR able */
1269 ushort start_motor; /* 05 send start up motor */
1270 ushort tagqng_able; /* 06 tag queuing able */
1271 ushort bios_scan; /* 07 BIOS device control */
1272 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001274 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1275 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001277 uchar scsi_reset_delay; /* 10 reset delay */
1278 uchar bios_id_lun; /* first boot device scsi id & lun */
1279 /* high nibble is lun */
1280 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001282 uchar termination; /* 11 0 - automatic */
1283 /* 1 - low off / high off */
1284 /* 2 - low off / high on */
1285 /* 3 - low on / high on */
1286 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001288 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001290 ushort bios_ctrl; /* 12 BIOS control bits */
1291 /* bit 0 BIOS don't act as initiator. */
1292 /* bit 1 BIOS > 1 GB support */
1293 /* bit 2 BIOS > 2 Disk Support */
1294 /* bit 3 BIOS don't support removables */
1295 /* bit 4 BIOS support bootable CD */
1296 /* bit 5 BIOS scan enabled */
1297 /* bit 6 BIOS support multiple LUNs */
1298 /* bit 7 BIOS display of message */
1299 /* bit 8 SCAM disabled */
1300 /* bit 9 Reset SCSI bus during init. */
1301 /* bit 10 */
1302 /* bit 11 No verbose initialization. */
1303 /* bit 12 SCSI parity enabled */
1304 /* bit 13 */
1305 /* bit 14 */
1306 /* bit 15 */
1307 ushort ultra_able; /* 13 ULTRA speed able */
1308 ushort reserved2; /* 14 reserved */
1309 uchar max_host_qng; /* 15 maximum host queuing */
1310 uchar max_dvc_qng; /* maximum per device queuing */
1311 ushort dvc_cntl; /* 16 control bit for driver */
1312 ushort bug_fix; /* 17 control bit for bug fix */
1313 ushort serial_number_word1; /* 18 Board serial number word 1 */
1314 ushort serial_number_word2; /* 19 Board serial number word 2 */
1315 ushort serial_number_word3; /* 20 Board serial number word 3 */
1316 ushort check_sum; /* 21 EEP check sum */
1317 uchar oem_name[16]; /* 22 OEM name */
1318 ushort dvc_err_code; /* 30 last device driver error code */
1319 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1320 ushort adv_err_addr; /* 32 last uc error address */
1321 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1322 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1323 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1324 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325} ADVEEP_3550_CONFIG;
1326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001327typedef struct adveep_38C0800_config {
1328 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001330 ushort cfg_lsw; /* 00 power up initialization */
1331 /* bit 13 set - Load CIS */
1332 /* bit 14 set - BIOS Enable */
1333 /* bit 15 set - Big Endian Mode */
1334 ushort cfg_msw; /* 01 unused */
1335 ushort disc_enable; /* 02 disconnect enable */
1336 ushort wdtr_able; /* 03 Wide DTR able */
1337 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1338 ushort start_motor; /* 05 send start up motor */
1339 ushort tagqng_able; /* 06 tag queuing able */
1340 ushort bios_scan; /* 07 BIOS device control */
1341 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001343 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1344 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001346 uchar scsi_reset_delay; /* 10 reset delay */
1347 uchar bios_id_lun; /* first boot device scsi id & lun */
1348 /* high nibble is lun */
1349 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001351 uchar termination_se; /* 11 0 - automatic */
1352 /* 1 - low off / high off */
1353 /* 2 - low off / high on */
1354 /* 3 - low on / high on */
1355 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001357 uchar termination_lvd; /* 11 0 - automatic */
1358 /* 1 - low off / high off */
1359 /* 2 - low off / high on */
1360 /* 3 - low on / high on */
1361 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001363 ushort bios_ctrl; /* 12 BIOS control bits */
1364 /* bit 0 BIOS don't act as initiator. */
1365 /* bit 1 BIOS > 1 GB support */
1366 /* bit 2 BIOS > 2 Disk Support */
1367 /* bit 3 BIOS don't support removables */
1368 /* bit 4 BIOS support bootable CD */
1369 /* bit 5 BIOS scan enabled */
1370 /* bit 6 BIOS support multiple LUNs */
1371 /* bit 7 BIOS display of message */
1372 /* bit 8 SCAM disabled */
1373 /* bit 9 Reset SCSI bus during init. */
1374 /* bit 10 */
1375 /* bit 11 No verbose initialization. */
1376 /* bit 12 SCSI parity enabled */
1377 /* bit 13 */
1378 /* bit 14 */
1379 /* bit 15 */
1380 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1381 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1382 uchar max_host_qng; /* 15 maximum host queueing */
1383 uchar max_dvc_qng; /* maximum per device queuing */
1384 ushort dvc_cntl; /* 16 control bit for driver */
1385 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1386 ushort serial_number_word1; /* 18 Board serial number word 1 */
1387 ushort serial_number_word2; /* 19 Board serial number word 2 */
1388 ushort serial_number_word3; /* 20 Board serial number word 3 */
1389 ushort check_sum; /* 21 EEP check sum */
1390 uchar oem_name[16]; /* 22 OEM name */
1391 ushort dvc_err_code; /* 30 last device driver error code */
1392 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1393 ushort adv_err_addr; /* 32 last uc error address */
1394 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1395 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1396 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1397 ushort reserved36; /* 36 reserved */
1398 ushort reserved37; /* 37 reserved */
1399 ushort reserved38; /* 38 reserved */
1400 ushort reserved39; /* 39 reserved */
1401 ushort reserved40; /* 40 reserved */
1402 ushort reserved41; /* 41 reserved */
1403 ushort reserved42; /* 42 reserved */
1404 ushort reserved43; /* 43 reserved */
1405 ushort reserved44; /* 44 reserved */
1406 ushort reserved45; /* 45 reserved */
1407 ushort reserved46; /* 46 reserved */
1408 ushort reserved47; /* 47 reserved */
1409 ushort reserved48; /* 48 reserved */
1410 ushort reserved49; /* 49 reserved */
1411 ushort reserved50; /* 50 reserved */
1412 ushort reserved51; /* 51 reserved */
1413 ushort reserved52; /* 52 reserved */
1414 ushort reserved53; /* 53 reserved */
1415 ushort reserved54; /* 54 reserved */
1416 ushort reserved55; /* 55 reserved */
1417 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1418 ushort cisprt_msw; /* 57 CIS PTR MSW */
1419 ushort subsysvid; /* 58 SubSystem Vendor ID */
1420 ushort subsysid; /* 59 SubSystem ID */
1421 ushort reserved60; /* 60 reserved */
1422 ushort reserved61; /* 61 reserved */
1423 ushort reserved62; /* 62 reserved */
1424 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425} ADVEEP_38C0800_CONFIG;
1426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001427typedef struct adveep_38C1600_config {
1428 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001430 ushort cfg_lsw; /* 00 power up initialization */
1431 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1432 /* clear - Func. 0 INTA, Func. 1 INTB */
1433 /* bit 13 set - Load CIS */
1434 /* bit 14 set - BIOS Enable */
1435 /* bit 15 set - Big Endian Mode */
1436 ushort cfg_msw; /* 01 unused */
1437 ushort disc_enable; /* 02 disconnect enable */
1438 ushort wdtr_able; /* 03 Wide DTR able */
1439 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1440 ushort start_motor; /* 05 send start up motor */
1441 ushort tagqng_able; /* 06 tag queuing able */
1442 ushort bios_scan; /* 07 BIOS device control */
1443 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001445 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1446 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001448 uchar scsi_reset_delay; /* 10 reset delay */
1449 uchar bios_id_lun; /* first boot device scsi id & lun */
1450 /* high nibble is lun */
1451 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001453 uchar termination_se; /* 11 0 - automatic */
1454 /* 1 - low off / high off */
1455 /* 2 - low off / high on */
1456 /* 3 - low on / high on */
1457 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001459 uchar termination_lvd; /* 11 0 - automatic */
1460 /* 1 - low off / high off */
1461 /* 2 - low off / high on */
1462 /* 3 - low on / high on */
1463 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001465 ushort bios_ctrl; /* 12 BIOS control bits */
1466 /* bit 0 BIOS don't act as initiator. */
1467 /* bit 1 BIOS > 1 GB support */
1468 /* bit 2 BIOS > 2 Disk Support */
1469 /* bit 3 BIOS don't support removables */
1470 /* bit 4 BIOS support bootable CD */
1471 /* bit 5 BIOS scan enabled */
1472 /* bit 6 BIOS support multiple LUNs */
1473 /* bit 7 BIOS display of message */
1474 /* bit 8 SCAM disabled */
1475 /* bit 9 Reset SCSI bus during init. */
1476 /* bit 10 Basic Integrity Checking disabled */
1477 /* bit 11 No verbose initialization. */
1478 /* bit 12 SCSI parity enabled */
1479 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1480 /* bit 14 */
1481 /* bit 15 */
1482 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1483 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1484 uchar max_host_qng; /* 15 maximum host queueing */
1485 uchar max_dvc_qng; /* maximum per device queuing */
1486 ushort dvc_cntl; /* 16 control bit for driver */
1487 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1488 ushort serial_number_word1; /* 18 Board serial number word 1 */
1489 ushort serial_number_word2; /* 19 Board serial number word 2 */
1490 ushort serial_number_word3; /* 20 Board serial number word 3 */
1491 ushort check_sum; /* 21 EEP check sum */
1492 uchar oem_name[16]; /* 22 OEM name */
1493 ushort dvc_err_code; /* 30 last device driver error code */
1494 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1495 ushort adv_err_addr; /* 32 last uc error address */
1496 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1497 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1498 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1499 ushort reserved36; /* 36 reserved */
1500 ushort reserved37; /* 37 reserved */
1501 ushort reserved38; /* 38 reserved */
1502 ushort reserved39; /* 39 reserved */
1503 ushort reserved40; /* 40 reserved */
1504 ushort reserved41; /* 41 reserved */
1505 ushort reserved42; /* 42 reserved */
1506 ushort reserved43; /* 43 reserved */
1507 ushort reserved44; /* 44 reserved */
1508 ushort reserved45; /* 45 reserved */
1509 ushort reserved46; /* 46 reserved */
1510 ushort reserved47; /* 47 reserved */
1511 ushort reserved48; /* 48 reserved */
1512 ushort reserved49; /* 49 reserved */
1513 ushort reserved50; /* 50 reserved */
1514 ushort reserved51; /* 51 reserved */
1515 ushort reserved52; /* 52 reserved */
1516 ushort reserved53; /* 53 reserved */
1517 ushort reserved54; /* 54 reserved */
1518 ushort reserved55; /* 55 reserved */
1519 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1520 ushort cisprt_msw; /* 57 CIS PTR MSW */
1521 ushort subsysvid; /* 58 SubSystem Vendor ID */
1522 ushort subsysid; /* 59 SubSystem ID */
1523 ushort reserved60; /* 60 reserved */
1524 ushort reserved61; /* 61 reserved */
1525 ushort reserved62; /* 62 reserved */
1526 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527} ADVEEP_38C1600_CONFIG;
1528
1529/*
1530 * EEPROM Commands
1531 */
1532#define ASC_EEP_CMD_DONE 0x0200
1533#define ASC_EEP_CMD_DONE_ERR 0x0001
1534
1535/* cfg_word */
1536#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
1537
1538/* bios_ctrl */
1539#define BIOS_CTRL_BIOS 0x0001
1540#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1541#define BIOS_CTRL_GT_2_DISK 0x0004
1542#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1543#define BIOS_CTRL_BOOTABLE_CD 0x0010
1544#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1545#define BIOS_CTRL_DISPLAY_MSG 0x0080
1546#define BIOS_CTRL_NO_SCAM 0x0100
1547#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1548#define BIOS_CTRL_INIT_VERBOSE 0x0800
1549#define BIOS_CTRL_SCSI_PARITY 0x1000
1550#define BIOS_CTRL_AIPP_DIS 0x2000
1551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001552#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001554#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556/*
1557 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1558 * a special 16K Adv Library and Microcode version. After the issue is
1559 * resolved, should restore 32K support.
1560 *
1561 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1562 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001563#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
1565/*
1566 * Byte I/O register address from base of 'iop_base'.
1567 */
1568#define IOPB_INTR_STATUS_REG 0x00
1569#define IOPB_CHIP_ID_1 0x01
1570#define IOPB_INTR_ENABLES 0x02
1571#define IOPB_CHIP_TYPE_REV 0x03
1572#define IOPB_RES_ADDR_4 0x04
1573#define IOPB_RES_ADDR_5 0x05
1574#define IOPB_RAM_DATA 0x06
1575#define IOPB_RES_ADDR_7 0x07
1576#define IOPB_FLAG_REG 0x08
1577#define IOPB_RES_ADDR_9 0x09
1578#define IOPB_RISC_CSR 0x0A
1579#define IOPB_RES_ADDR_B 0x0B
1580#define IOPB_RES_ADDR_C 0x0C
1581#define IOPB_RES_ADDR_D 0x0D
1582#define IOPB_SOFT_OVER_WR 0x0E
1583#define IOPB_RES_ADDR_F 0x0F
1584#define IOPB_MEM_CFG 0x10
1585#define IOPB_RES_ADDR_11 0x11
1586#define IOPB_GPIO_DATA 0x12
1587#define IOPB_RES_ADDR_13 0x13
1588#define IOPB_FLASH_PAGE 0x14
1589#define IOPB_RES_ADDR_15 0x15
1590#define IOPB_GPIO_CNTL 0x16
1591#define IOPB_RES_ADDR_17 0x17
1592#define IOPB_FLASH_DATA 0x18
1593#define IOPB_RES_ADDR_19 0x19
1594#define IOPB_RES_ADDR_1A 0x1A
1595#define IOPB_RES_ADDR_1B 0x1B
1596#define IOPB_RES_ADDR_1C 0x1C
1597#define IOPB_RES_ADDR_1D 0x1D
1598#define IOPB_RES_ADDR_1E 0x1E
1599#define IOPB_RES_ADDR_1F 0x1F
1600#define IOPB_DMA_CFG0 0x20
1601#define IOPB_DMA_CFG1 0x21
1602#define IOPB_TICKLE 0x22
1603#define IOPB_DMA_REG_WR 0x23
1604#define IOPB_SDMA_STATUS 0x24
1605#define IOPB_SCSI_BYTE_CNT 0x25
1606#define IOPB_HOST_BYTE_CNT 0x26
1607#define IOPB_BYTE_LEFT_TO_XFER 0x27
1608#define IOPB_BYTE_TO_XFER_0 0x28
1609#define IOPB_BYTE_TO_XFER_1 0x29
1610#define IOPB_BYTE_TO_XFER_2 0x2A
1611#define IOPB_BYTE_TO_XFER_3 0x2B
1612#define IOPB_ACC_GRP 0x2C
1613#define IOPB_RES_ADDR_2D 0x2D
1614#define IOPB_DEV_ID 0x2E
1615#define IOPB_RES_ADDR_2F 0x2F
1616#define IOPB_SCSI_DATA 0x30
1617#define IOPB_RES_ADDR_31 0x31
1618#define IOPB_RES_ADDR_32 0x32
1619#define IOPB_SCSI_DATA_HSHK 0x33
1620#define IOPB_SCSI_CTRL 0x34
1621#define IOPB_RES_ADDR_35 0x35
1622#define IOPB_RES_ADDR_36 0x36
1623#define IOPB_RES_ADDR_37 0x37
1624#define IOPB_RAM_BIST 0x38
1625#define IOPB_PLL_TEST 0x39
1626#define IOPB_PCI_INT_CFG 0x3A
1627#define IOPB_RES_ADDR_3B 0x3B
1628#define IOPB_RFIFO_CNT 0x3C
1629#define IOPB_RES_ADDR_3D 0x3D
1630#define IOPB_RES_ADDR_3E 0x3E
1631#define IOPB_RES_ADDR_3F 0x3F
1632
1633/*
1634 * Word I/O register address from base of 'iop_base'.
1635 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001636#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1637#define IOPW_CTRL_REG 0x02 /* CC */
1638#define IOPW_RAM_ADDR 0x04 /* LA */
1639#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001641#define IOPW_RISC_CSR 0x0A /* CSR */
1642#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1643#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001645#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001647#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001649#define IOPW_EE_CMD 0x1A /* EC */
1650#define IOPW_EE_DATA 0x1C /* ED */
1651#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001653#define IOPW_Q_BASE 0x22 /* QB */
1654#define IOPW_QP 0x24 /* QP */
1655#define IOPW_IX 0x26 /* IX */
1656#define IOPW_SP 0x28 /* SP */
1657#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658#define IOPW_RES_ADDR_2C 0x2C
1659#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001660#define IOPW_SCSI_DATA 0x30 /* SD */
1661#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1662#define IOPW_SCSI_CTRL 0x34 /* SC */
1663#define IOPW_HSHK_CFG 0x36 /* HCFG */
1664#define IOPW_SXFR_STATUS 0x36 /* SXS */
1665#define IOPW_SXFR_CNTL 0x38 /* SXL */
1666#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001668#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670/*
1671 * Doubleword I/O register address from base of 'iop_base'.
1672 */
1673#define IOPDW_RES_ADDR_0 0x00
1674#define IOPDW_RAM_DATA 0x04
1675#define IOPDW_RES_ADDR_8 0x08
1676#define IOPDW_RES_ADDR_C 0x0C
1677#define IOPDW_RES_ADDR_10 0x10
1678#define IOPDW_COMMA 0x14
1679#define IOPDW_COMMB 0x18
1680#define IOPDW_RES_ADDR_1C 0x1C
1681#define IOPDW_SDMA_ADDR0 0x20
1682#define IOPDW_SDMA_ADDR1 0x24
1683#define IOPDW_SDMA_COUNT 0x28
1684#define IOPDW_SDMA_ERROR 0x2C
1685#define IOPDW_RDMA_ADDR0 0x30
1686#define IOPDW_RDMA_ADDR1 0x34
1687#define IOPDW_RDMA_COUNT 0x38
1688#define IOPDW_RDMA_ERROR 0x3C
1689
1690#define ADV_CHIP_ID_BYTE 0x25
1691#define ADV_CHIP_ID_WORD 0x04C1
1692
1693#define ADV_SC_SCSI_BUS_RESET 0x2000
1694
1695#define ADV_INTR_ENABLE_HOST_INTR 0x01
1696#define ADV_INTR_ENABLE_SEL_INTR 0x02
1697#define ADV_INTR_ENABLE_DPR_INTR 0x04
1698#define ADV_INTR_ENABLE_RTA_INTR 0x08
1699#define ADV_INTR_ENABLE_RMA_INTR 0x10
1700#define ADV_INTR_ENABLE_RST_INTR 0x20
1701#define ADV_INTR_ENABLE_DPE_INTR 0x40
1702#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1703
1704#define ADV_INTR_STATUS_INTRA 0x01
1705#define ADV_INTR_STATUS_INTRB 0x02
1706#define ADV_INTR_STATUS_INTRC 0x04
1707
1708#define ADV_RISC_CSR_STOP (0x0000)
1709#define ADV_RISC_TEST_COND (0x2000)
1710#define ADV_RISC_CSR_RUN (0x4000)
1711#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1712
1713#define ADV_CTRL_REG_HOST_INTR 0x0100
1714#define ADV_CTRL_REG_SEL_INTR 0x0200
1715#define ADV_CTRL_REG_DPR_INTR 0x0400
1716#define ADV_CTRL_REG_RTA_INTR 0x0800
1717#define ADV_CTRL_REG_RMA_INTR 0x1000
1718#define ADV_CTRL_REG_RES_BIT14 0x2000
1719#define ADV_CTRL_REG_DPE_INTR 0x4000
1720#define ADV_CTRL_REG_POWER_DONE 0x8000
1721#define ADV_CTRL_REG_ANY_INTR 0xFF00
1722
1723#define ADV_CTRL_REG_CMD_RESET 0x00C6
1724#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1725#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1726#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1727#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1728
1729#define ADV_TICKLE_NOP 0x00
1730#define ADV_TICKLE_A 0x01
1731#define ADV_TICKLE_B 0x02
1732#define ADV_TICKLE_C 0x03
1733
1734#define ADV_SCSI_CTRL_RSTOUT 0x2000
1735
1736#define AdvIsIntPending(port) \
1737 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1738
1739/*
1740 * SCSI_CFG0 Register bit definitions
1741 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001742#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1743#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1744#define EVEN_PARITY 0x1000 /* Select Even Parity */
1745#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1746#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1747#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1748#define SCAM_EN 0x0080 /* Enable SCAM selection */
1749#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1750#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1751#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1752#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
1754/*
1755 * SCSI_CFG1 Register bit definitions
1756 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001757#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1758#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1759#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1760#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1761#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1762#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1763#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1764#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1765#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1766#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1767#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1768#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1769#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1770#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1771#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
1773/*
1774 * Addendum for ASC-38C0800 Chip
1775 *
1776 * The ASC-38C1600 Chip uses the same definitions except that the
1777 * bus mode override bits [12:10] have been moved to byte register
1778 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1779 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1780 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1781 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1782 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1783 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001784#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1785#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1786#define HVD 0x1000 /* HVD Device Detect */
1787#define LVD 0x0800 /* LVD Device Detect */
1788#define SE 0x0400 /* SE Device Detect */
1789#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1790#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1791#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1792#define TERM_SE 0x0030 /* SE Termination Bits */
1793#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1794#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1795#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1796#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1797#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1798#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1799#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1800#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
1802#define CABLE_ILLEGAL_A 0x7
1803 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1804
1805#define CABLE_ILLEGAL_B 0xB
1806 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1807
1808/*
1809 * MEM_CFG Register bit definitions
1810 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001811#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1812#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1813#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1814#define RAM_SZ_2KB 0x00 /* 2 KB */
1815#define RAM_SZ_4KB 0x04 /* 4 KB */
1816#define RAM_SZ_8KB 0x08 /* 8 KB */
1817#define RAM_SZ_16KB 0x0C /* 16 KB */
1818#define RAM_SZ_32KB 0x10 /* 32 KB */
1819#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821/*
1822 * DMA_CFG0 Register bit definitions
1823 *
1824 * This register is only accessible to the host.
1825 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001826#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1827#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1828#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1829#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1830#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1831#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1832#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1833#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1834#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1835#define START_CTL 0x0C /* DMA start conditions */
1836#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1837#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1838#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1839#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1840#define READ_CMD 0x03 /* Memory Read Method */
1841#define READ_CMD_MR 0x00 /* Memory Read */
1842#define READ_CMD_MRL 0x02 /* Memory Read Long */
1843#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
1845/*
1846 * ASC-38C0800 RAM BIST Register bit definitions
1847 */
1848#define RAM_TEST_MODE 0x80
1849#define PRE_TEST_MODE 0x40
1850#define NORMAL_MODE 0x00
1851#define RAM_TEST_DONE 0x10
1852#define RAM_TEST_STATUS 0x0F
1853#define RAM_TEST_HOST_ERROR 0x08
1854#define RAM_TEST_INTRAM_ERROR 0x04
1855#define RAM_TEST_RISC_ERROR 0x02
1856#define RAM_TEST_SCSI_ERROR 0x01
1857#define RAM_TEST_SUCCESS 0x00
1858#define PRE_TEST_VALUE 0x05
1859#define NORMAL_VALUE 0x00
1860
1861/*
1862 * ASC38C1600 Definitions
1863 *
1864 * IOPB_PCI_INT_CFG Bit Field Definitions
1865 */
1866
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001867#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
1869/*
1870 * Bit 1 can be set to change the interrupt for the Function to operate in
1871 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1872 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1873 * mode, otherwise the operating mode is undefined.
1874 */
1875#define TOTEMPOLE 0x02
1876
1877/*
1878 * Bit 0 can be used to change the Int Pin for the Function. The value is
1879 * 0 by default for both Functions with Function 0 using INT A and Function
1880 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1881 * INT A is used.
1882 *
1883 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1884 * value specified in the PCI Configuration Space.
1885 */
1886#define INTAB 0x01
1887
1888/* a_advlib.h */
1889
1890/*
1891 * Adv Library Status Definitions
1892 */
1893#define ADV_TRUE 1
1894#define ADV_FALSE 0
1895#define ADV_NOERROR 1
1896#define ADV_SUCCESS 1
1897#define ADV_BUSY 0
1898#define ADV_ERROR (-1)
1899
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900/*
1901 * ADV_DVC_VAR 'warn_code' values
1902 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001903#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1904#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1905#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
1906#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
1907#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001909#define ADV_MAX_TID 15 /* max. target identifier */
1910#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
1912/*
1913 * Error code values are set in ADV_DVC_VAR 'err_code'.
1914 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001915#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
1916#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
1917#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
1918#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
1919#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
1920#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
1921#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
1922#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
1923#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
1924#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
1925#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
1926#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
1927#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
1928#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
1930/*
1931 * Fixed locations of microcode operating variables.
1932 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001933#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1934#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1935#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1936#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1937#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1938#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1939#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1940#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1941#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1942#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1943#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1944#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1945#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946#define ASC_MC_CHIP_TYPE 0x009A
1947#define ASC_MC_INTRB_CODE 0x009B
1948#define ASC_MC_WDTR_ABLE 0x009C
1949#define ASC_MC_SDTR_ABLE 0x009E
1950#define ASC_MC_TAGQNG_ABLE 0x00A0
1951#define ASC_MC_DISC_ENABLE 0x00A2
1952#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1953#define ASC_MC_IDLE_CMD 0x00A6
1954#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1955#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1956#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1957#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1958#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1959#define ASC_MC_SDTR_DONE 0x00B6
1960#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1961#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1962#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001963#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001965#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966#define ASC_MC_ICQ 0x0160
1967#define ASC_MC_IRQ 0x0164
1968#define ASC_MC_PPR_ABLE 0x017A
1969
1970/*
1971 * BIOS LRAM variable absolute offsets.
1972 */
1973#define BIOS_CODESEG 0x54
1974#define BIOS_CODELEN 0x56
1975#define BIOS_SIGNATURE 0x58
1976#define BIOS_VERSION 0x5A
1977
1978/*
1979 * Microcode Control Flags
1980 *
1981 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1982 * and handled by the microcode.
1983 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001984#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1985#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
1987/*
1988 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1989 */
1990#define HSHK_CFG_WIDE_XFR 0x8000
1991#define HSHK_CFG_RATE 0x0F00
1992#define HSHK_CFG_OFFSET 0x001F
1993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001994#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1995#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1996#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1997#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001999#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2000#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2001#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2002#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2003#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002005#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2006#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2007#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2008#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2009#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010/*
2011 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2012 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2013 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002014#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2015#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
2017/*
2018 * All fields here are accessed by the board microcode and need to be
2019 * little-endian.
2020 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002021typedef struct adv_carr_t {
2022 ADV_VADDR carr_va; /* Carrier Virtual Address */
2023 ADV_PADDR carr_pa; /* Carrier Physical Address */
2024 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2025 /*
2026 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2027 *
2028 * next_vpa [3:1] Reserved Bits
2029 * next_vpa [0] Done Flag set in Response Queue.
2030 */
2031 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032} ADV_CARR_T;
2033
2034/*
2035 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2036 */
2037#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2038
2039#define ASC_RQ_DONE 0x00000001
2040#define ASC_RQ_GOOD 0x00000002
2041#define ASC_CQ_STOPPER 0x00000000
2042
2043#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2044
2045#define ADV_CARRIER_NUM_PAGE_CROSSING \
2046 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2047 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2048
2049#define ADV_CARRIER_BUFSIZE \
2050 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2051
2052/*
2053 * ASC_SCSI_REQ_Q 'a_flag' definitions
2054 *
2055 * The Adv Library should limit use to the lower nibble (4 bits) of
2056 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2057 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002058#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2059#define ADV_SCSIQ_DONE 0x02 /* request done */
2060#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002062#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2063#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2064#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
2066/*
2067 * Adapter temporary configuration structure
2068 *
2069 * This structure can be discarded after initialization. Don't add
2070 * fields here needed after initialization.
2071 *
2072 * Field naming convention:
2073 *
2074 * *_enable indicates the field enables or disables a feature. The
2075 * value of the field is never reset.
2076 */
2077typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002078 ushort disc_enable; /* enable disconnection */
2079 uchar chip_version; /* chip version */
2080 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2081 ushort lib_version; /* Adv Library version number */
2082 ushort control_flag; /* Microcode Control Flag */
2083 ushort mcode_date; /* Microcode date */
2084 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002085 ushort serial1; /* EEPROM serial number word 1 */
2086 ushort serial2; /* EEPROM serial number word 2 */
2087 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088} ADV_DVC_CFG;
2089
2090struct adv_dvc_var;
2091struct adv_scsi_req_q;
2092
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093/*
2094 * Adapter operation variable structure.
2095 *
2096 * One structure is required per host adapter.
2097 *
2098 * Field naming convention:
2099 *
2100 * *_able indicates both whether a feature should be enabled or disabled
2101 * and whether a device isi capable of the feature. At initialization
2102 * this field may be set, but later if a device is found to be incapable
2103 * of the feature, the field is cleared.
2104 */
2105typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002106 AdvPortAddr iop_base; /* I/O port address */
2107 ushort err_code; /* fatal error code */
2108 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002109 ushort wdtr_able; /* try WDTR for a device */
2110 ushort sdtr_able; /* try SDTR for a device */
2111 ushort ultra_able; /* try SDTR Ultra speed for a device */
2112 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2113 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2114 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2115 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2116 ushort tagqng_able; /* try tagged queuing with a device */
2117 ushort ppr_able; /* PPR message capable per TID bitmask. */
2118 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2119 ushort start_motor; /* start motor command allowed */
2120 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2121 uchar chip_no; /* should be assigned by caller */
2122 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2123 uchar irq_no; /* IRQ number */
2124 ushort no_scam; /* scam_tolerant of EEPROM */
2125 struct asc_board *drv_ptr; /* driver pointer to private structure */
2126 uchar chip_scsi_id; /* chip SCSI target ID */
2127 uchar chip_type;
2128 uchar bist_err_code;
2129 ADV_CARR_T *carrier_buf;
2130 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2131 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2132 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2133 ushort carr_pending_cnt; /* Count of pending carriers. */
2134 /*
2135 * Note: The following fields will not be used after initialization. The
2136 * driver may discard the buffer after initialization is done.
2137 */
2138 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139} ADV_DVC_VAR;
2140
2141#define NO_OF_SG_PER_BLOCK 15
2142
2143typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002144 uchar reserved1;
2145 uchar reserved2;
2146 uchar reserved3;
2147 uchar sg_cnt; /* Valid entries in block. */
2148 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
2149 struct {
2150 ADV_PADDR sg_addr; /* SG element address. */
2151 ADV_DCNT sg_count; /* SG element count. */
2152 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153} ADV_SG_BLOCK;
2154
2155/*
2156 * ADV_SCSI_REQ_Q - microcode request structure
2157 *
2158 * All fields in this structure up to byte 60 are used by the microcode.
2159 * The microcode makes assumptions about the size and ordering of fields
2160 * in this structure. Do not change the structure definition here without
2161 * coordinating the change with the microcode.
2162 *
2163 * All fields accessed by microcode must be maintained in little_endian
2164 * order.
2165 */
2166typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002167 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2168 uchar target_cmd;
2169 uchar target_id; /* Device target identifier. */
2170 uchar target_lun; /* Device target logical unit number. */
2171 ADV_PADDR data_addr; /* Data buffer physical address. */
2172 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
2173 ADV_PADDR sense_addr;
2174 ADV_PADDR carr_pa;
2175 uchar mflag;
2176 uchar sense_len;
2177 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
2178 uchar scsi_cntl;
2179 uchar done_status; /* Completion status. */
2180 uchar scsi_status; /* SCSI status byte. */
2181 uchar host_status; /* Ucode host status. */
2182 uchar sg_working_ix;
2183 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
2184 ADV_PADDR sg_real_addr; /* SG list physical address. */
2185 ADV_PADDR scsiq_rptr;
2186 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
2187 ADV_VADDR scsiq_ptr;
2188 ADV_VADDR carr_va;
2189 /*
2190 * End of microcode structure - 60 bytes. The rest of the structure
2191 * is used by the Adv Library and ignored by the microcode.
2192 */
2193 ADV_VADDR srb_ptr;
2194 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2195 char *vdata_addr; /* Data buffer virtual address. */
2196 uchar a_flag;
2197 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198} ADV_SCSI_REQ_Q;
2199
2200/*
2201 * Microcode idle loop commands
2202 */
2203#define IDLE_CMD_COMPLETED 0
2204#define IDLE_CMD_STOP_CHIP 0x0001
2205#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2206#define IDLE_CMD_SEND_INT 0x0004
2207#define IDLE_CMD_ABORT 0x0008
2208#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002209#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
2210#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211#define IDLE_CMD_SCSIREQ 0x0080
2212
2213#define IDLE_CMD_STATUS_SUCCESS 0x0001
2214#define IDLE_CMD_STATUS_FAILURE 0x0002
2215
2216/*
2217 * AdvSendIdleCmd() flag definitions.
2218 */
2219#define ADV_NOWAIT 0x01
2220
2221/*
2222 * Wait loop time out values.
2223 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002224#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
2225#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2226#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
2227#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
2228#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002230#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2231#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2232#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2233#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002235#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236
2237/*
2238 * Device drivers must define the following functions.
2239 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002240static inline ulong DvcEnterCritical(void);
2241static inline void DvcLeaveCritical(ulong);
2242static void DvcSleepMilliSecond(ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002243static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2244 uchar *, ASC_SDCNT *, int);
2245static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
2247/*
2248 * Adv Library functions available to drivers.
2249 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002250static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2251static int AdvISR(ADV_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002252static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2253static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
2254static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
2255static int AdvResetChipAndSB(ADV_DVC_VAR *);
2256static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258/*
2259 * Internal Adv Library functions.
2260 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002261static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002262static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
2263static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
2264static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
2265static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2266static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2267static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2268static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2269static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2270static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2271static void AdvWaitEEPCmd(AdvPortAddr);
2272static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274/* Read byte from a register. */
2275#define AdvReadByteRegister(iop_base, reg_off) \
2276 (ADV_MEM_READB((iop_base) + (reg_off)))
2277
2278/* Write byte to a register. */
2279#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2280 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2281
2282/* Read word (2 bytes) from a register. */
2283#define AdvReadWordRegister(iop_base, reg_off) \
2284 (ADV_MEM_READW((iop_base) + (reg_off)))
2285
2286/* Write word (2 bytes) to a register. */
2287#define AdvWriteWordRegister(iop_base, reg_off, word) \
2288 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2289
2290/* Write dword (4 bytes) to a register. */
2291#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2292 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2293
2294/* Read byte from LRAM. */
2295#define AdvReadByteLram(iop_base, addr, byte) \
2296do { \
2297 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2298 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2299} while (0)
2300
2301/* Write byte to LRAM. */
2302#define AdvWriteByteLram(iop_base, addr, byte) \
2303 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2304 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2305
2306/* Read word (2 bytes) from LRAM. */
2307#define AdvReadWordLram(iop_base, addr, word) \
2308do { \
2309 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2310 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2311} while (0)
2312
2313/* Write word (2 bytes) to LRAM. */
2314#define AdvWriteWordLram(iop_base, addr, word) \
2315 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2316 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2317
2318/* Write little-endian double word (4 bytes) to LRAM */
2319/* Because of unspecified C language ordering don't use auto-increment. */
2320#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2321 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2322 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2323 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2324 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2325 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2326 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2327
2328/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2329#define AdvReadWordAutoIncLram(iop_base) \
2330 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2331
2332/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2333#define AdvWriteWordAutoIncLram(iop_base, word) \
2334 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2335
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336/*
2337 * Define macro to check for Condor signature.
2338 *
2339 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2340 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2341 */
2342#define AdvFindSignature(iop_base) \
2343 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2344 ADV_CHIP_ID_BYTE) && \
2345 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2346 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2347
2348/*
2349 * Define macro to Return the version number of the chip at 'iop_base'.
2350 *
2351 * The second parameter 'bus_type' is currently unused.
2352 */
2353#define AdvGetChipVersion(iop_base, bus_type) \
2354 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2355
2356/*
2357 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2358 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2359 *
2360 * If the request has not yet been sent to the device it will simply be
2361 * aborted from RISC memory. If the request is disconnected it will be
2362 * aborted on reselection by sending an Abort Message to the target ID.
2363 *
2364 * Return value:
2365 * ADV_TRUE(1) - Queue was successfully aborted.
2366 * ADV_FALSE(0) - Queue was not found on the active queue list.
2367 */
2368#define AdvAbortQueue(asc_dvc, scsiq) \
2369 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2370 (ADV_DCNT) (scsiq))
2371
2372/*
2373 * Send a Bus Device Reset Message to the specified target ID.
2374 *
2375 * All outstanding commands will be purged if sending the
2376 * Bus Device Reset Message is successful.
2377 *
2378 * Return Value:
2379 * ADV_TRUE(1) - All requests on the target are purged.
2380 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2381 * are not purged.
2382 */
2383#define AdvResetDevice(asc_dvc, target_id) \
2384 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2385 (ADV_DCNT) (target_id))
2386
2387/*
2388 * SCSI Wide Type definition.
2389 */
2390#define ADV_SCSI_BIT_ID_TYPE ushort
2391
2392/*
2393 * AdvInitScsiTarget() 'cntl_flag' options.
2394 */
2395#define ADV_SCAN_LUN 0x01
2396#define ADV_CAPINFO_NOLUN 0x02
2397
2398/*
2399 * Convert target id to target id bit mask.
2400 */
2401#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2402
2403/*
2404 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2405 */
2406
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002407#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408#define QD_NO_ERROR 0x01
2409#define QD_ABORTED_BY_HOST 0x02
2410#define QD_WITH_ERROR 0x04
2411
2412#define QHSTA_NO_ERROR 0x00
2413#define QHSTA_M_SEL_TIMEOUT 0x11
2414#define QHSTA_M_DATA_OVER_RUN 0x12
2415#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2416#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002417#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2418#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2419#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2420#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2421#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2422#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2423#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002425#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2426#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2427#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2428#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2429#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2430#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2431#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2432#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433#define QHSTA_M_WTM_TIMEOUT 0x41
2434#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2435#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2436#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002437#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2438#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2439#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 * DvcGetPhyAddr() flag arguments
2443 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002444#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2445#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2446#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2447#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2448#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2449#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
2451/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2452#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2453#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2454#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2455
2456/*
2457 * Total contiguous memory needed for driver SG blocks.
2458 *
2459 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2460 * number of scatter-gather elements the driver supports in a
2461 * single request.
2462 */
2463
2464#define ADV_SG_LIST_MAX_BYTE_SIZE \
2465 (sizeof(ADV_SG_BLOCK) * \
2466 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2467
2468/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 * --- Driver Constants and Macros
2470 */
2471
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472/* Reference Scsi_Host hostdata */
2473#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
2474
2475/* asc_board_t flags */
2476#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002477#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478#define ASC_SELECT_QUEUE_DEPTHS 0x08
2479
2480#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
2481#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
2482
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002483#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002485#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
2487#ifdef CONFIG_PROC_FS
2488/* /proc/scsi/advansys/[0...] related definitions */
2489#define ASC_PRTBUF_SIZE 2048
2490#define ASC_PRTLINE_SIZE 160
2491
2492#define ASC_PRT_NEXT() \
2493 if (cp) { \
2494 totlen += len; \
2495 leftlen -= len; \
2496 if (leftlen == 0) { \
2497 return totlen; \
2498 } \
2499 cp += len; \
2500 }
2501#endif /* CONFIG_PROC_FS */
2502
2503/* Asc Library return codes */
2504#define ASC_TRUE 1
2505#define ASC_FALSE 0
2506#define ASC_NOERROR 1
2507#define ASC_BUSY 0
2508#define ASC_ERROR (-1)
2509
2510/* struct scsi_cmnd function return codes */
2511#define STATUS_BYTE(byte) (byte)
2512#define MSG_BYTE(byte) ((byte) << 8)
2513#define HOST_BYTE(byte) ((byte) << 16)
2514#define DRIVER_BYTE(byte) ((byte) << 24)
2515
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002517#define ASC_STATS(shost, counter)
2518#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002520#define ASC_STATS(shost, counter) \
2521 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002523#define ASC_STATS_ADD(shost, counter, count) \
2524 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525#endif /* ADVANSYS_STATS */
2526
2527#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2528
2529/* If the result wraps when calculating tenths, return 0. */
2530#define ASC_TENTHS(num, den) \
2531 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2532 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2533
2534/*
2535 * Display a message to the console.
2536 */
2537#define ASC_PRINT(s) \
2538 { \
2539 printk("advansys: "); \
2540 printk(s); \
2541 }
2542
2543#define ASC_PRINT1(s, a1) \
2544 { \
2545 printk("advansys: "); \
2546 printk((s), (a1)); \
2547 }
2548
2549#define ASC_PRINT2(s, a1, a2) \
2550 { \
2551 printk("advansys: "); \
2552 printk((s), (a1), (a2)); \
2553 }
2554
2555#define ASC_PRINT3(s, a1, a2, a3) \
2556 { \
2557 printk("advansys: "); \
2558 printk((s), (a1), (a2), (a3)); \
2559 }
2560
2561#define ASC_PRINT4(s, a1, a2, a3, a4) \
2562 { \
2563 printk("advansys: "); \
2564 printk((s), (a1), (a2), (a3), (a4)); \
2565 }
2566
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567#ifndef ADVANSYS_DEBUG
2568
2569#define ASC_DBG(lvl, s)
2570#define ASC_DBG1(lvl, s, a1)
2571#define ASC_DBG2(lvl, s, a1, a2)
2572#define ASC_DBG3(lvl, s, a1, a2, a3)
2573#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2574#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2575#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
2576#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2577#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2578#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2579#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2580#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2581#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2582#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2583#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2584
2585#else /* ADVANSYS_DEBUG */
2586
2587/*
2588 * Debugging Message Levels:
2589 * 0: Errors Only
2590 * 1: High-Level Tracing
2591 * 2-N: Verbose Tracing
2592 */
2593
2594#define ASC_DBG(lvl, s) \
2595 { \
2596 if (asc_dbglvl >= (lvl)) { \
2597 printk(s); \
2598 } \
2599 }
2600
2601#define ASC_DBG1(lvl, s, a1) \
2602 { \
2603 if (asc_dbglvl >= (lvl)) { \
2604 printk((s), (a1)); \
2605 } \
2606 }
2607
2608#define ASC_DBG2(lvl, s, a1, a2) \
2609 { \
2610 if (asc_dbglvl >= (lvl)) { \
2611 printk((s), (a1), (a2)); \
2612 } \
2613 }
2614
2615#define ASC_DBG3(lvl, s, a1, a2, a3) \
2616 { \
2617 if (asc_dbglvl >= (lvl)) { \
2618 printk((s), (a1), (a2), (a3)); \
2619 } \
2620 }
2621
2622#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2623 { \
2624 if (asc_dbglvl >= (lvl)) { \
2625 printk((s), (a1), (a2), (a3), (a4)); \
2626 } \
2627 }
2628
2629#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2630 { \
2631 if (asc_dbglvl >= (lvl)) { \
2632 asc_prt_scsi_host(s); \
2633 } \
2634 }
2635
2636#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
2637 { \
2638 if (asc_dbglvl >= (lvl)) { \
2639 asc_prt_scsi_cmnd(s); \
2640 } \
2641 }
2642
2643#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2644 { \
2645 if (asc_dbglvl >= (lvl)) { \
2646 asc_prt_asc_scsi_q(scsiqp); \
2647 } \
2648 }
2649
2650#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2651 { \
2652 if (asc_dbglvl >= (lvl)) { \
2653 asc_prt_asc_qdone_info(qdone); \
2654 } \
2655 }
2656
2657#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2658 { \
2659 if (asc_dbglvl >= (lvl)) { \
2660 asc_prt_adv_scsi_req_q(scsiqp); \
2661 } \
2662 }
2663
2664#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2665 { \
2666 if (asc_dbglvl >= (lvl)) { \
2667 asc_prt_hex((name), (start), (length)); \
2668 } \
2669 }
2670
2671#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2672 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2673
2674#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2675 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2676
2677#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2678 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2679#endif /* ADVANSYS_DEBUG */
2680
2681#ifndef ADVANSYS_ASSERT
2682#define ASC_ASSERT(a)
2683#else /* ADVANSYS_ASSERT */
2684
2685#define ASC_ASSERT(a) \
2686 { \
2687 if (!(a)) { \
2688 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
2689 __FILE__, __LINE__); \
2690 } \
2691 }
2692
2693#endif /* ADVANSYS_ASSERT */
2694
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695/*
2696 * --- Driver Structures
2697 */
2698
2699#ifdef ADVANSYS_STATS
2700
2701/* Per board statistics structure */
2702struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002703 /* Driver Entrypoint Statistics */
2704 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2705 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2706 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2707 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2708 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2709 ADV_DCNT done; /* # calls to request's scsi_done function */
2710 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2711 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2712 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2713 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2714 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2715 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2716 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2717 ADV_DCNT exe_unknown; /* # unknown returns. */
2718 /* Data Transfer Statistics */
2719 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2720 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2721 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2722 ADV_DCNT sg_elem; /* # scatter-gather elements */
2723 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724};
2725#endif /* ADVANSYS_STATS */
2726
2727/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 * Adv Library Request Structures
2729 *
2730 * The following two structures are used to process Wide Board requests.
2731 *
2732 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2733 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2734 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2735 * Mid-Level SCSI request structure.
2736 *
2737 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2738 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2739 * up to 255 scatter-gather elements may be used per request or
2740 * ADV_SCSI_REQ_Q.
2741 *
2742 * Both structures must be 32 byte aligned.
2743 */
2744typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002745 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2746 uchar align[32]; /* Sgblock structure padding. */
2747 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748} adv_sgblk_t;
2749
2750typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002751 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2752 uchar align[32]; /* Request structure padding. */
2753 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2754 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2755 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756} adv_req_t;
2757
2758/*
2759 * Structure allocated for each board.
2760 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002761 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 * of the 'Scsi_Host' structure starting at the 'hostdata'
2763 * field. It is guaranteed to be allocated from DMA-able memory.
2764 */
2765typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002766 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002767 int id; /* Board Id */
2768 uint flags; /* Board flags */
2769 union {
2770 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2771 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2772 } dvc_var;
2773 union {
2774 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2775 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2776 } dvc_cfg;
2777 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002778 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
2779 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
2780 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2781 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2782 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2783 union {
2784 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2785 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2786 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2787 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2788 } eep_config;
2789 ulong last_reset; /* Saved last reset time */
2790 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002791 /* /proc/scsi/advansys/[0...] */
2792 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002794 struct asc_stats asc_stats; /* Board statistics */
2795#endif /* ADVANSYS_STATS */
2796 /*
2797 * The following fields are used only for Narrow Boards.
2798 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002799 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2800 /*
2801 * The following fields are used only for Wide Boards.
2802 */
2803 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2804 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002805 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002806 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2807 adv_req_t *adv_reqp; /* Request structures. */
2808 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2809 ushort bios_signature; /* BIOS Signature. */
2810 ushort bios_version; /* BIOS Version. */
2811 ushort bios_codeseg; /* BIOS Code Segment. */
2812 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813} asc_board_t;
2814
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002815#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2816 dvc_var.adv_dvc_var)
2817#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2818
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002820static int asc_board_count;
2821
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002823static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
2825/*
2826 * Global structures required to issue a command.
2827 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002828static ASC_SCSI_Q asc_scsi_q = { {0} };
2829static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002832static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833#endif /* ADVANSYS_DEBUG */
2834
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835/*
2836 * --- Driver Function Prototypes
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 */
2838
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002839static int advansys_slave_configure(struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002840static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
2841static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
2842static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
2843static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002845static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
2846static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
2847static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
2848static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
2849static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
2850static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
2851static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
2852static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
2853static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
2854static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855#endif /* CONFIG_PROC_FS */
2856
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857/* Statistics function prototypes. */
2858#ifdef ADVANSYS_STATS
2859#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002860static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861#endif /* CONFIG_PROC_FS */
2862#endif /* ADVANSYS_STATS */
2863
2864/* Debug function prototypes. */
2865#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002866static void asc_prt_scsi_host(struct Scsi_Host *);
2867static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
2868static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
2869static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
2870static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
2871static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
2872static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
2873static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
2874static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
2875static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
2876static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877#endif /* ADVANSYS_DEBUG */
2878
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879#ifdef CONFIG_PROC_FS
2880/*
Matthew Wilcoxc304ec92007-07-30 09:18:45 -06002881 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882 *
2883 * *buffer: I/O buffer
2884 * **start: if inout == FALSE pointer into buffer where user read should start
2885 * offset: current offset into a /proc/scsi/advansys/[0...] file
2886 * length: length of buffer
2887 * hostno: Scsi_Host host_no
2888 * inout: TRUE - user is writing; FALSE - user is reading
2889 *
2890 * Return the number of bytes read from or written to a
2891 * /proc/scsi/advansys/[0...] file.
2892 *
2893 * Note: This function uses the per board buffer 'prtbuf' which is
2894 * allocated when the board is initialized in advansys_detect(). The
2895 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
2896 * used to write to the buffer. The way asc_proc_copy() is written
2897 * if 'prtbuf' is too small it will not be overwritten. Instead the
2898 * user just won't get all the available statistics.
2899 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07002900static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002902 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002904 asc_board_t *boardp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002905 char *cp;
2906 int cplen;
2907 int cnt;
2908 int totcnt;
2909 int leftlen;
2910 char *curbuf;
2911 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002913 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002915 /*
2916 * User write not supported.
2917 */
2918 if (inout == TRUE) {
2919 return (-ENOSYS);
2920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002922 /*
2923 * User read of /proc/scsi/advansys/[0...] file.
2924 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
Matthew Wilcox2a437952007-07-26 11:00:51 -04002926 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002928 /* Copy read data starting at the beginning of the buffer. */
2929 *start = buffer;
2930 curbuf = buffer;
2931 advoffset = 0;
2932 totcnt = 0;
2933 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002935 /*
2936 * Get board configuration information.
2937 *
2938 * advansys_info() returns the board string from its own static buffer.
2939 */
Matthew Wilcox2a437952007-07-26 11:00:51 -04002940 cp = (char *)advansys_info(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002941 strcat(cp, "\n");
2942 cplen = strlen(cp);
2943 /* Copy board information. */
2944 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2945 totcnt += cnt;
2946 leftlen -= cnt;
2947 if (leftlen == 0) {
2948 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2949 return totcnt;
2950 }
2951 advoffset += cplen;
2952 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002954 /*
2955 * Display Wide Board BIOS Information.
2956 */
2957 if (ASC_WIDE_BOARD(boardp)) {
2958 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002959 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002960 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002961 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002962 cplen);
2963 totcnt += cnt;
2964 leftlen -= cnt;
2965 if (leftlen == 0) {
2966 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2967 return totcnt;
2968 }
2969 advoffset += cplen;
2970 curbuf += cnt;
2971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002973 /*
2974 * Display driver information for each device attached to the board.
2975 */
2976 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002977 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002978 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
2979 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2980 totcnt += cnt;
2981 leftlen -= cnt;
2982 if (leftlen == 0) {
2983 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2984 return totcnt;
2985 }
2986 advoffset += cplen;
2987 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002989 /*
2990 * Display EEPROM configuration for the board.
2991 */
2992 cp = boardp->prtbuf;
2993 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04002994 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002995 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04002996 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002997 }
2998 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
2999 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3000 totcnt += cnt;
3001 leftlen -= cnt;
3002 if (leftlen == 0) {
3003 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3004 return totcnt;
3005 }
3006 advoffset += cplen;
3007 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003009 /*
3010 * Display driver configuration and information for the board.
3011 */
3012 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003013 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003014 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3015 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3016 totcnt += cnt;
3017 leftlen -= cnt;
3018 if (leftlen == 0) {
3019 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3020 return totcnt;
3021 }
3022 advoffset += cplen;
3023 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
3025#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003026 /*
3027 * Display driver statistics for the board.
3028 */
3029 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003030 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003031 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
3032 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3033 totcnt += cnt;
3034 leftlen -= cnt;
3035 if (leftlen == 0) {
3036 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3037 return totcnt;
3038 }
3039 advoffset += cplen;
3040 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041#endif /* ADVANSYS_STATS */
3042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003043 /*
3044 * Display Asc Library dynamic configuration information
3045 * for the board.
3046 */
3047 cp = boardp->prtbuf;
3048 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003049 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003050 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003051 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003052 }
3053 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3054 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3055 totcnt += cnt;
3056 leftlen -= cnt;
3057 if (leftlen == 0) {
3058 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3059 return totcnt;
3060 }
3061 advoffset += cplen;
3062 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003064 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003066 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067}
3068#endif /* CONFIG_PROC_FS */
3069
3070/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 * advansys_info()
3072 *
3073 * Return suitable for printing on the console with the argument
3074 * adapter's configuration information.
3075 *
3076 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
3077 * otherwise the static 'info' array will be overrun.
3078 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003079static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003081 static char info[ASC_INFO_SIZE];
3082 asc_board_t *boardp;
3083 ASC_DVC_VAR *asc_dvc_varp;
3084 ADV_DVC_VAR *adv_dvc_varp;
3085 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003086 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003088 boardp = ASC_BOARDP(shost);
3089 if (ASC_NARROW_BOARD(boardp)) {
3090 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3091 ASC_DBG(1, "advansys_info: begin\n");
3092 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3093 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
3094 ASC_IS_ISAPNP) {
3095 busname = "ISA PnP";
3096 } else {
3097 busname = "ISA";
3098 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003099 sprintf(info,
3100 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
3101 ASC_VERSION, busname,
3102 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003103 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3104 shost->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003105 } else {
3106 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
3107 busname = "VL";
3108 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
3109 busname = "EISA";
3110 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
3111 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
3112 == ASC_IS_PCI_ULTRA) {
3113 busname = "PCI Ultra";
3114 } else {
3115 busname = "PCI";
3116 }
3117 } else {
3118 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003119 ASC_PRINT2("advansys_info: board %d: unknown "
3120 "bus type %d\n", boardp->id,
3121 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003122 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003123 sprintf(info,
3124 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003125 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003126 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3127 shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003128 }
3129 } else {
3130 /*
3131 * Wide Adapter Information
3132 *
3133 * Memory-mapped I/O is used instead of I/O space to access
3134 * the adapter, but display the I/O Port range. The Memory
3135 * I/O address is displayed through the driver /proc file.
3136 */
3137 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3138 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003139 widename = "Ultra-Wide";
3140 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003141 widename = "Ultra2-Wide";
3142 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003143 widename = "Ultra3-Wide";
3144 }
3145 sprintf(info,
3146 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
3147 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003148 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003149 }
3150 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
3151 ASC_DBG(1, "advansys_info: end\n");
3152 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153}
3154
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003155static void asc_scsi_done(struct scsi_cmnd *scp)
3156{
3157 struct asc_board *boardp = ASC_BOARDP(scp->device->host);
3158
3159 if (scp->use_sg)
3160 dma_unmap_sg(boardp->dev,
3161 (struct scatterlist *)scp->request_buffer,
3162 scp->use_sg, scp->sc_data_direction);
3163 else if (scp->request_bufflen)
3164 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
3165 scp->request_bufflen, scp->sc_data_direction);
3166
3167 ASC_STATS(scp->device->host, done);
3168
3169 scp->scsi_done(scp);
3170}
3171
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172/*
3173 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
3174 *
3175 * This function always returns 0. Command return status is saved
3176 * in the 'scp' result field.
3177 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003178static int
Matthew 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.
3859 *
3860 * For narrow boards a CDB length maximum of 12 bytes
3861 * is supported.
3862 */
3863 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003864 ASC_PRINT3("asc_build_req: board %d: cmd_len %d > "
3865 "ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len,
3866 ASC_MAX_CDB_LEN);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003867 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003868 return ASC_ERROR;
3869 }
3870 asc_scsi_q.cdbptr = &scp->cmnd[0];
3871 asc_scsi_q.q2.cdb_len = scp->cmd_len;
3872 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
3873 asc_scsi_q.q1.target_lun = scp->device->lun;
3874 asc_scsi_q.q2.target_ix =
3875 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
3876 asc_scsi_q.q1.sense_addr =
3877 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
3878 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003880 /*
3881 * If there are any outstanding requests for the current target,
3882 * then every 255th request send an ORDERED request. This heuristic
3883 * tries to retain the benefit of request sorting while preventing
3884 * request starvation. 255 is the max number of tags or pending commands
3885 * a device may have outstanding.
3886 *
3887 * The request count is incremented below for every successfully
3888 * started request.
3889 *
3890 */
3891 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
3892 (boardp->reqcnt[scp->device->id] % 255) == 0) {
3893 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
3894 } else {
3895 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
3896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003898 /*
3899 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
3900 * buffer command.
3901 */
3902 if (scp->use_sg == 0) {
3903 /*
3904 * CDB request of single contiguous buffer.
3905 */
3906 ASC_STATS(scp->device->host, cont_cnt);
3907 scp->SCp.dma_handle = scp->request_bufflen ?
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003908 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003909 scp->request_bufflen,
3910 scp->sc_data_direction) : 0;
3911 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
3912 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
3913 ASC_STATS_ADD(scp->device->host, cont_xfer,
3914 ASC_CEILING(scp->request_bufflen, 512));
3915 asc_scsi_q.q1.sg_queue_cnt = 0;
3916 asc_scsi_q.sg_head = NULL;
3917 } else {
3918 /*
3919 * CDB scatter-gather request list.
3920 */
3921 int sgcnt;
3922 int use_sg;
3923 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003925 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003926 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
3927 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003929 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003930 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
3931 "sg_tablesize %d\n", boardp->id, use_sg,
3932 scp->device->host->sg_tablesize);
3933 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003934 scp->sc_data_direction);
3935 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003936 return ASC_ERROR;
3937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003939 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003941 /*
3942 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
3943 * structure to point to it.
3944 */
3945 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003947 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
3948 asc_scsi_q.sg_head = &asc_sg_head;
3949 asc_scsi_q.q1.data_cnt = 0;
3950 asc_scsi_q.q1.data_addr = 0;
3951 /* This is a byte value, otherwise it would need to be swapped. */
3952 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
3953 ASC_STATS_ADD(scp->device->host, sg_elem,
3954 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003956 /*
3957 * Convert scatter-gather list into ASC_SG_HEAD list.
3958 */
3959 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
3960 asc_sg_head.sg_list[sgcnt].addr =
3961 cpu_to_le32(sg_dma_address(slp));
3962 asc_sg_head.sg_list[sgcnt].bytes =
3963 cpu_to_le32(sg_dma_len(slp));
3964 ASC_STATS_ADD(scp->device->host, sg_xfer,
3965 ASC_CEILING(sg_dma_len(slp), 512));
3966 }
3967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003969 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
3970 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003972 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973}
3974
3975/*
3976 * Build a request structure for the Adv Library (Wide Board).
3977 *
3978 * If an adv_req_t can not be allocated to issue the request,
3979 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
3980 *
3981 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
3982 * microcode for DMA addresses or math operations are byte swapped
3983 * to little-endian order.
3984 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003985static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003987 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003989 adv_req_t *reqp;
3990 ADV_SCSI_REQ_Q *scsiqp;
3991 int i;
3992 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003994 /*
3995 * Allocate an adv_req_t structure from the board to execute
3996 * the command.
3997 */
3998 if (boardp->adv_reqp == NULL) {
3999 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
4000 ASC_STATS(scp->device->host, adv_build_noreq);
4001 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004003 reqp = boardp->adv_reqp;
4004 boardp->adv_reqp = reqp->next_reqp;
4005 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004008 /*
4009 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
4010 */
4011 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004013 /*
4014 * Initialize the structure.
4015 */
4016 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004018 /*
4019 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
4020 */
4021 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004023 /*
4024 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
4025 */
4026 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004028 /*
4029 * Build the ADV_SCSI_REQ_Q request.
4030 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004032 /*
4033 * Set CDB length and copy it to the request structure.
4034 * For wide boards a CDB length maximum of 16 bytes
4035 * is supported.
4036 */
4037 if (scp->cmd_len > ADV_MAX_CDB_LEN) {
4038 ASC_PRINT3
4039 ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
4040 boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
4041 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004042 return ASC_ERROR;
4043 }
4044 scsiqp->cdb_len = scp->cmd_len;
4045 /* Copy first 12 CDB bytes to cdb[]. */
4046 for (i = 0; i < scp->cmd_len && i < 12; i++) {
4047 scsiqp->cdb[i] = scp->cmnd[i];
4048 }
4049 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
4050 for (; i < scp->cmd_len; i++) {
4051 scsiqp->cdb16[i - 12] = scp->cmnd[i];
4052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004054 scsiqp->target_id = scp->device->id;
4055 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004057 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4058 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004060 /*
4061 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
4062 * buffer command.
4063 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004065 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4066 scsiqp->vdata_addr = scp->request_buffer;
4067 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
4068
4069 if (scp->use_sg == 0) {
4070 /*
4071 * CDB request of single contiguous buffer.
4072 */
4073 reqp->sgblkp = NULL;
4074 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4075 if (scp->request_bufflen) {
4076 scsiqp->vdata_addr = scp->request_buffer;
4077 scp->SCp.dma_handle =
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004078 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004079 scp->request_bufflen,
4080 scp->sc_data_direction);
4081 } else {
4082 scsiqp->vdata_addr = NULL;
4083 scp->SCp.dma_handle = 0;
4084 }
4085 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
4086 scsiqp->sg_list_ptr = NULL;
4087 scsiqp->sg_real_addr = 0;
4088 ASC_STATS(scp->device->host, cont_cnt);
4089 ASC_STATS_ADD(scp->device->host, cont_xfer,
4090 ASC_CEILING(scp->request_bufflen, 512));
4091 } else {
4092 /*
4093 * CDB scatter-gather request list.
4094 */
4095 struct scatterlist *slp;
4096 int use_sg;
4097
4098 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004099 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4100 scp->sc_data_direction);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004101
4102 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004103 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
4104 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
4105 scp->device->host->sg_tablesize);
4106 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004107 scp->sc_data_direction);
4108 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004109
4110 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004111 * Free the 'adv_req_t' structure by adding it back
4112 * to the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004113 */
4114 reqp->next_reqp = boardp->adv_reqp;
4115 boardp->adv_reqp = reqp;
4116
4117 return ASC_ERROR;
4118 }
4119
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004120 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
4121 if (ret != ADV_SUCCESS) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004122 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004123 * Free the adv_req_t structure by adding it back to
4124 * the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004125 */
4126 reqp->next_reqp = boardp->adv_reqp;
4127 boardp->adv_reqp = reqp;
4128
4129 return ret;
4130 }
4131
4132 ASC_STATS(scp->device->host, sg_cnt);
4133 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
4134 }
4135
4136 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
4137 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
4138
4139 *adv_scsiqpp = scsiqp;
4140
4141 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142}
4143
4144/*
4145 * Build scatter-gather list for Adv Library (Wide Board).
4146 *
4147 * Additional ADV_SG_BLOCK structures will need to be allocated
4148 * if the total number of scatter-gather elements exceeds
4149 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
4150 * assumed to be physically contiguous.
4151 *
4152 * Return:
4153 * ADV_SUCCESS(1) - SG List successfully created
4154 * ADV_ERROR(-1) - SG List creation failed
4155 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004156static int
4157adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
4158 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004160 adv_sgblk_t *sgblkp;
4161 ADV_SCSI_REQ_Q *scsiqp;
4162 struct scatterlist *slp;
4163 int sg_elem_cnt;
4164 ADV_SG_BLOCK *sg_block, *prev_sg_block;
4165 ADV_PADDR sg_block_paddr;
4166 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004168 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
4169 slp = (struct scatterlist *)scp->request_buffer;
4170 sg_elem_cnt = use_sg;
4171 prev_sg_block = NULL;
4172 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004174 do {
4175 /*
4176 * Allocate a 'adv_sgblk_t' structure from the board free
4177 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
4178 * (15) scatter-gather elements.
4179 */
4180 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
4181 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
4182 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004184 /*
4185 * Allocation failed. Free 'adv_sgblk_t' structures already
4186 * allocated for the request.
4187 */
4188 while ((sgblkp = reqp->sgblkp) != NULL) {
4189 /* Remove 'sgblkp' from the request list. */
4190 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004192 /* Add 'sgblkp' to the board free list. */
4193 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4194 boardp->adv_sgblkp = sgblkp;
4195 }
4196 return ASC_BUSY;
4197 } else {
4198 /* Complete 'adv_sgblk_t' board allocation. */
4199 boardp->adv_sgblkp = sgblkp->next_sgblkp;
4200 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004202 /*
4203 * Get 8 byte aligned virtual and physical addresses for
4204 * the allocated ADV_SG_BLOCK structure.
4205 */
4206 sg_block =
4207 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
4208 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004210 /*
4211 * Check if this is the first 'adv_sgblk_t' for the request.
4212 */
4213 if (reqp->sgblkp == NULL) {
4214 /* Request's first scatter-gather block. */
4215 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004217 /*
4218 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
4219 * address pointers.
4220 */
4221 scsiqp->sg_list_ptr = sg_block;
4222 scsiqp->sg_real_addr =
4223 cpu_to_le32(sg_block_paddr);
4224 } else {
4225 /* Request's second or later scatter-gather block. */
4226 sgblkp->next_sgblkp = reqp->sgblkp;
4227 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004229 /*
4230 * Point the previous ADV_SG_BLOCK structure to
4231 * the newly allocated ADV_SG_BLOCK structure.
4232 */
4233 ASC_ASSERT(prev_sg_block != NULL);
4234 prev_sg_block->sg_ptr =
4235 cpu_to_le32(sg_block_paddr);
4236 }
4237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004239 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
4240 sg_block->sg_list[i].sg_addr =
4241 cpu_to_le32(sg_dma_address(slp));
4242 sg_block->sg_list[i].sg_count =
4243 cpu_to_le32(sg_dma_len(slp));
4244 ASC_STATS_ADD(scp->device->host, sg_xfer,
4245 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004247 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
4248 sg_block->sg_cnt = i + 1;
4249 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
4250 return ADV_SUCCESS;
4251 }
4252 slp++;
4253 }
4254 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
4255 prev_sg_block = sg_block;
4256 }
4257 while (1);
4258 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259}
4260
4261/*
4262 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
4263 *
4264 * Interrupt callback function for the Narrow SCSI Asc Library.
4265 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004266static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004268 asc_board_t *boardp;
4269 struct scsi_cmnd *scp;
4270 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004272 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
4273 (ulong)asc_dvc_varp, (ulong)qdonep);
4274 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004276 /*
4277 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4278 * command that has been completed.
4279 */
4280 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
4281 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004283 if (scp == NULL) {
4284 ASC_PRINT("asc_isr_callback: scp is NULL\n");
4285 return;
4286 }
4287 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004289 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004290 ASC_STATS(shost, callback);
4291 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004293 boardp = ASC_BOARDP(shost);
4294 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004296 /*
4297 * 'qdonep' contains the command's ending status.
4298 */
4299 switch (qdonep->d3.done_stat) {
4300 case QD_NO_ERROR:
4301 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
4302 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004304 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004305 * Check for an underrun condition.
4306 *
4307 * If there was no error and an underrun condition, then
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004308 * return the number of underrun bytes.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004309 */
4310 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
4311 qdonep->remain_bytes <= scp->request_bufflen) {
4312 ASC_DBG1(1,
4313 "asc_isr_callback: underrun condition %u bytes\n",
4314 (unsigned)qdonep->remain_bytes);
4315 scp->resid = qdonep->remain_bytes;
4316 }
4317 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004319 case QD_WITH_ERROR:
4320 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
4321 switch (qdonep->d3.host_stat) {
4322 case QHSTA_NO_ERROR:
4323 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
4324 ASC_DBG(2,
4325 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4326 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4327 sizeof(scp->sense_buffer));
4328 /*
4329 * Note: The 'status_byte()' macro used by target drivers
4330 * defined in scsi.h shifts the status byte returned by
4331 * host drivers right by 1 bit. This is why target drivers
4332 * also use right shifted status byte definitions. For
4333 * instance target drivers use CHECK_CONDITION, defined to
4334 * 0x1, instead of the SCSI defined check condition value
4335 * of 0x2. Host drivers are supposed to return the status
4336 * byte as it is defined by SCSI.
4337 */
4338 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4339 STATUS_BYTE(qdonep->d3.scsi_stat);
4340 } else {
4341 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
4342 }
4343 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004345 default:
4346 /* QHSTA error occurred */
4347 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
4348 qdonep->d3.host_stat);
4349 scp->result = HOST_BYTE(DID_BAD_TARGET);
4350 break;
4351 }
4352 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004354 case QD_ABORTED_BY_HOST:
4355 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
4356 scp->result =
4357 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
4358 scsi_msg) |
4359 STATUS_BYTE(qdonep->d3.scsi_stat);
4360 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004362 default:
4363 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
4364 qdonep->d3.done_stat);
4365 scp->result =
4366 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
4367 scsi_msg) |
4368 STATUS_BYTE(qdonep->d3.scsi_stat);
4369 break;
4370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004372 /*
4373 * If the 'init_tidmask' bit isn't already set for the target and the
4374 * current request finished normally, then set the bit for the target
4375 * to indicate that a device is present.
4376 */
4377 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4378 qdonep->d3.done_stat == QD_NO_ERROR &&
4379 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
4380 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004383 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004385 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386}
4387
4388/*
4389 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
4390 *
4391 * Callback function for the Wide SCSI Adv Library.
4392 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004393static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004395 asc_board_t *boardp;
4396 adv_req_t *reqp;
4397 adv_sgblk_t *sgblkp;
4398 struct scsi_cmnd *scp;
4399 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004400 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004402 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
4403 (ulong)adv_dvc_varp, (ulong)scsiqp);
4404 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004406 /*
4407 * Get the adv_req_t structure for the command that has been
4408 * completed. The adv_req_t structure actually contains the
4409 * completed ADV_SCSI_REQ_Q structure.
4410 */
4411 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
4412 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
4413 if (reqp == NULL) {
4414 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
4415 return;
4416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004418 /*
4419 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4420 * command that has been completed.
4421 *
4422 * Note: The adv_req_t request structure and adv_sgblk_t structure,
4423 * if any, are dropped, because a board structure pointer can not be
4424 * determined.
4425 */
4426 scp = reqp->cmndp;
4427 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
4428 if (scp == NULL) {
4429 ASC_PRINT
4430 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
4431 return;
4432 }
4433 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004435 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004436 ASC_STATS(shost, callback);
4437 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004439 boardp = ASC_BOARDP(shost);
4440 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004442 /*
4443 * 'done_status' contains the command's ending status.
4444 */
4445 switch (scsiqp->done_status) {
4446 case QD_NO_ERROR:
4447 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
4448 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004450 /*
4451 * Check for an underrun condition.
4452 *
4453 * If there was no error and an underrun condition, then
4454 * then return the number of underrun bytes.
4455 */
4456 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
4457 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
4458 resid_cnt <= scp->request_bufflen) {
4459 ASC_DBG1(1,
4460 "adv_isr_callback: underrun condition %lu bytes\n",
4461 (ulong)resid_cnt);
4462 scp->resid = resid_cnt;
4463 }
4464 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004466 case QD_WITH_ERROR:
4467 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
4468 switch (scsiqp->host_status) {
4469 case QHSTA_NO_ERROR:
4470 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
4471 ASC_DBG(2,
4472 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4473 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4474 sizeof(scp->sense_buffer));
4475 /*
4476 * Note: The 'status_byte()' macro used by target drivers
4477 * defined in scsi.h shifts the status byte returned by
4478 * host drivers right by 1 bit. This is why target drivers
4479 * also use right shifted status byte definitions. For
4480 * instance target drivers use CHECK_CONDITION, defined to
4481 * 0x1, instead of the SCSI defined check condition value
4482 * of 0x2. Host drivers are supposed to return the status
4483 * byte as it is defined by SCSI.
4484 */
4485 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4486 STATUS_BYTE(scsiqp->scsi_status);
4487 } else {
4488 scp->result = STATUS_BYTE(scsiqp->scsi_status);
4489 }
4490 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004492 default:
4493 /* Some other QHSTA error occurred. */
4494 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
4495 scsiqp->host_status);
4496 scp->result = HOST_BYTE(DID_BAD_TARGET);
4497 break;
4498 }
4499 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004501 case QD_ABORTED_BY_HOST:
4502 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
4503 scp->result =
4504 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
4505 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004507 default:
4508 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
4509 scsiqp->done_status);
4510 scp->result =
4511 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
4512 break;
4513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004515 /*
4516 * If the 'init_tidmask' bit isn't already set for the target and the
4517 * current request finished normally, then set the bit for the target
4518 * to indicate that a device is present.
4519 */
4520 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4521 scsiqp->done_status == QD_NO_ERROR &&
4522 scsiqp->host_status == QHSTA_NO_ERROR) {
4523 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004526 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004528 /*
4529 * Free all 'adv_sgblk_t' structures allocated for the request.
4530 */
4531 while ((sgblkp = reqp->sgblkp) != NULL) {
4532 /* Remove 'sgblkp' from the request list. */
4533 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004535 /* Add 'sgblkp' to the board free list. */
4536 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4537 boardp->adv_sgblkp = sgblkp;
4538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004540 /*
4541 * Free the adv_req_t structure used with the command by adding
4542 * it back to the board free list.
4543 */
4544 reqp->next_reqp = boardp->adv_reqp;
4545 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004547 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004549 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550}
4551
4552/*
4553 * adv_async_callback() - Adv Library asynchronous event callback function.
4554 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004555static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004557 switch (code) {
4558 case ADV_ASYNC_SCSI_BUS_RESET_DET:
4559 /*
4560 * The firmware detected a SCSI Bus reset.
4561 */
4562 ASC_DBG(0,
4563 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
4564 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004566 case ADV_ASYNC_RDMA_FAILURE:
4567 /*
4568 * Handle RDMA failure by resetting the SCSI Bus and
4569 * possibly the chip if it is unresponsive. Log the error
4570 * with a unique code.
4571 */
4572 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
4573 AdvResetChipAndSB(adv_dvc_varp);
4574 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004576 case ADV_HOST_SCSI_BUS_RESET:
4577 /*
4578 * Host generated SCSI bus reset occurred.
4579 */
4580 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
4581 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004583 default:
4584 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
4585 break;
4586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587}
4588
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589#ifdef CONFIG_PROC_FS
4590/*
4591 * asc_prt_board_devices()
4592 *
4593 * Print driver information for devices attached to the board.
4594 *
4595 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4596 * cf. asc_prt_line().
4597 *
4598 * Return the number of characters copied into 'cp'. No more than
4599 * 'cplen' characters will be copied to 'cp'.
4600 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004601static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004603 asc_board_t *boardp;
4604 int leftlen;
4605 int totlen;
4606 int len;
4607 int chip_scsi_id;
4608 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004610 boardp = ASC_BOARDP(shost);
4611 leftlen = cplen;
4612 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004614 len = asc_prt_line(cp, leftlen,
4615 "\nDevice Information for AdvanSys SCSI Host %d:\n",
4616 shost->host_no);
4617 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004619 if (ASC_NARROW_BOARD(boardp)) {
4620 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
4621 } else {
4622 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
4623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004625 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
4626 ASC_PRT_NEXT();
4627 for (i = 0; i <= ADV_MAX_TID; i++) {
4628 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
4629 len = asc_prt_line(cp, leftlen, " %X,", i);
4630 ASC_PRT_NEXT();
4631 }
4632 }
4633 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
4634 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004636 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637}
4638
4639/*
4640 * Display Wide Board BIOS Information.
4641 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004642static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004644 asc_board_t *boardp;
4645 int leftlen;
4646 int totlen;
4647 int len;
4648 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004650 boardp = ASC_BOARDP(shost);
4651 leftlen = cplen;
4652 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004654 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
4655 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004657 /*
4658 * If the BIOS saved a valid signature, then fill in
4659 * the BIOS code segment base address.
4660 */
4661 if (boardp->bios_signature != 0x55AA) {
4662 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
4663 ASC_PRT_NEXT();
4664 len = asc_prt_line(cp, leftlen,
4665 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
4666 ASC_PRT_NEXT();
4667 len = asc_prt_line(cp, leftlen,
4668 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
4669 ASC_PRT_NEXT();
4670 } else {
4671 major = (boardp->bios_version >> 12) & 0xF;
4672 minor = (boardp->bios_version >> 8) & 0xF;
4673 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004675 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
4676 major, minor,
4677 letter >= 26 ? '?' : letter + 'A');
4678 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004679
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004680 /*
4681 * Current available ROM BIOS release is 3.1I for UW
4682 * and 3.2I for U2W. This code doesn't differentiate
4683 * UW and U2W boards.
4684 */
4685 if (major < 3 || (major <= 3 && minor < 1) ||
4686 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
4687 len = asc_prt_line(cp, leftlen,
4688 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
4689 ASC_PRT_NEXT();
4690 len = asc_prt_line(cp, leftlen,
4691 "ftp://ftp.connectcom.net/pub\n");
4692 ASC_PRT_NEXT();
4693 }
4694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004696 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697}
4698
4699/*
4700 * Add serial number to information bar if signature AAh
4701 * is found in at bit 15-9 (7 bits) of word 1.
4702 *
4703 * Serial Number consists fo 12 alpha-numeric digits.
4704 *
4705 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
4706 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
4707 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
4708 * 5 - Product revision (A-J) Word0: " "
4709 *
4710 * Signature Word1: 15-9 (7 bits)
4711 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
4712 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
4713 *
4714 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
4715 *
4716 * Note 1: Only production cards will have a serial number.
4717 *
4718 * Note 2: Signature is most significant 7 bits (0xFE).
4719 *
4720 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
4721 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004722static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004724 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004726 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
4727 return ASC_FALSE;
4728 } else {
4729 /*
4730 * First word - 6 digits.
4731 */
4732 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004734 /* Product type - 1st digit. */
4735 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
4736 /* Product type is P=Prototype */
4737 *cp += 0x8;
4738 }
4739 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004741 /* Manufacturing location - 2nd digit. */
4742 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004744 /* Product ID - 3rd, 4th digits. */
4745 num = w & 0x3FF;
4746 *cp++ = '0' + (num / 100);
4747 num %= 100;
4748 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004750 /* Product revision - 5th digit. */
4751 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004753 /*
4754 * Second word
4755 */
4756 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004758 /*
4759 * Year - 6th digit.
4760 *
4761 * If bit 15 of third word is set, then the
4762 * last digit of the year is greater than 7.
4763 */
4764 if (serialnum[2] & 0x8000) {
4765 *cp++ = '8' + ((w & 0x1C0) >> 6);
4766 } else {
4767 *cp++ = '0' + ((w & 0x1C0) >> 6);
4768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004770 /* Week of year - 7th, 8th digits. */
4771 num = w & 0x003F;
4772 *cp++ = '0' + num / 10;
4773 num %= 10;
4774 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004776 /*
4777 * Third word
4778 */
4779 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004781 /* Serial number - 9th digit. */
4782 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004784 /* 10th, 11th, 12th digits. */
4785 num = w % 1000;
4786 *cp++ = '0' + num / 100;
4787 num %= 100;
4788 *cp++ = '0' + num / 10;
4789 num %= 10;
4790 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004792 *cp = '\0'; /* Null Terminate the string. */
4793 return ASC_TRUE;
4794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795}
4796
4797/*
4798 * asc_prt_asc_board_eeprom()
4799 *
4800 * Print board EEPROM configuration.
4801 *
4802 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4803 * cf. asc_prt_line().
4804 *
4805 * Return the number of characters copied into 'cp'. No more than
4806 * 'cplen' characters will be copied to 'cp'.
4807 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004808static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004810 asc_board_t *boardp;
4811 ASC_DVC_VAR *asc_dvc_varp;
4812 int leftlen;
4813 int totlen;
4814 int len;
4815 ASCEEP_CONFIG *ep;
4816 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004818 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07004819#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004820 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004822 boardp = ASC_BOARDP(shost);
4823 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4824 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004826 leftlen = cplen;
4827 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004829 len = asc_prt_line(cp, leftlen,
4830 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4831 shost->host_no);
4832 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004833
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004834 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
4835 == ASC_TRUE) {
4836 len =
4837 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4838 serialstr);
4839 ASC_PRT_NEXT();
4840 } else {
4841 if (ep->adapter_info[5] == 0xBB) {
4842 len = asc_prt_line(cp, leftlen,
4843 " Default Settings Used for EEPROM-less Adapter.\n");
4844 ASC_PRT_NEXT();
4845 } else {
4846 len = asc_prt_line(cp, leftlen,
4847 " Serial Number Signature Not Present.\n");
4848 ASC_PRT_NEXT();
4849 }
4850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004852 len = asc_prt_line(cp, leftlen,
4853 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4854 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
4855 ep->max_tag_qng);
4856 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004858 len = asc_prt_line(cp, leftlen,
4859 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
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, " Target ID: ");
4863 ASC_PRT_NEXT();
4864 for (i = 0; i <= ASC_MAX_TID; i++) {
4865 len = asc_prt_line(cp, leftlen, " %d", i);
4866 ASC_PRT_NEXT();
4867 }
4868 len = asc_prt_line(cp, leftlen, "\n");
4869 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004871 len = asc_prt_line(cp, leftlen, " Disconnects: ");
4872 ASC_PRT_NEXT();
4873 for (i = 0; i <= ASC_MAX_TID; i++) {
4874 len = asc_prt_line(cp, leftlen, " %c",
4875 (ep->
4876 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4877 'N');
4878 ASC_PRT_NEXT();
4879 }
4880 len = asc_prt_line(cp, leftlen, "\n");
4881 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004883 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
4884 ASC_PRT_NEXT();
4885 for (i = 0; i <= ASC_MAX_TID; i++) {
4886 len = asc_prt_line(cp, leftlen, " %c",
4887 (ep->
4888 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4889 'N');
4890 ASC_PRT_NEXT();
4891 }
4892 len = asc_prt_line(cp, leftlen, "\n");
4893 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004895 len = asc_prt_line(cp, leftlen, " Start Motor: ");
4896 ASC_PRT_NEXT();
4897 for (i = 0; i <= ASC_MAX_TID; i++) {
4898 len = asc_prt_line(cp, leftlen, " %c",
4899 (ep->
4900 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4901 'N');
4902 ASC_PRT_NEXT();
4903 }
4904 len = asc_prt_line(cp, leftlen, "\n");
4905 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004907 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
4908 ASC_PRT_NEXT();
4909 for (i = 0; i <= ASC_MAX_TID; i++) {
4910 len = asc_prt_line(cp, leftlen, " %c",
4911 (ep->
4912 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4913 'N');
4914 ASC_PRT_NEXT();
4915 }
4916 len = asc_prt_line(cp, leftlen, "\n");
4917 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918
4919#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004920 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4921 len = asc_prt_line(cp, leftlen,
4922 " Host ISA DMA speed: %d MB/S\n",
4923 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
4924 ASC_PRT_NEXT();
4925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926#endif /* CONFIG_ISA */
4927
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004928 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004929}
4930
4931/*
4932 * asc_prt_adv_board_eeprom()
4933 *
4934 * Print board EEPROM configuration.
4935 *
4936 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4937 * cf. asc_prt_line().
4938 *
4939 * Return the number of characters copied into 'cp'. No more than
4940 * 'cplen' characters will be copied to 'cp'.
4941 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004942static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004944 asc_board_t *boardp;
4945 ADV_DVC_VAR *adv_dvc_varp;
4946 int leftlen;
4947 int totlen;
4948 int len;
4949 int i;
4950 char *termstr;
4951 uchar serialstr[13];
4952 ADVEEP_3550_CONFIG *ep_3550 = NULL;
4953 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
4954 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
4955 ushort word;
4956 ushort *wordp;
4957 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004959 boardp = ASC_BOARDP(shost);
4960 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4961 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4962 ep_3550 = &boardp->eep_config.adv_3550_eep;
4963 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4964 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
4965 } else {
4966 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
4967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004969 leftlen = cplen;
4970 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004972 len = asc_prt_line(cp, leftlen,
4973 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4974 shost->host_no);
4975 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004977 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4978 wordp = &ep_3550->serial_number_word1;
4979 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4980 wordp = &ep_38C0800->serial_number_word1;
4981 } else {
4982 wordp = &ep_38C1600->serial_number_word1;
4983 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004985 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
4986 len =
4987 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4988 serialstr);
4989 ASC_PRT_NEXT();
4990 } else {
4991 len = asc_prt_line(cp, leftlen,
4992 " Serial Number Signature Not Present.\n");
4993 ASC_PRT_NEXT();
4994 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004996 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4997 len = asc_prt_line(cp, leftlen,
4998 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4999 ep_3550->adapter_scsi_id,
5000 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
5001 ASC_PRT_NEXT();
5002 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5003 len = asc_prt_line(cp, leftlen,
5004 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5005 ep_38C0800->adapter_scsi_id,
5006 ep_38C0800->max_host_qng,
5007 ep_38C0800->max_dvc_qng);
5008 ASC_PRT_NEXT();
5009 } else {
5010 len = asc_prt_line(cp, leftlen,
5011 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5012 ep_38C1600->adapter_scsi_id,
5013 ep_38C1600->max_host_qng,
5014 ep_38C1600->max_dvc_qng);
5015 ASC_PRT_NEXT();
5016 }
5017 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5018 word = ep_3550->termination;
5019 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5020 word = ep_38C0800->termination_lvd;
5021 } else {
5022 word = ep_38C1600->termination_lvd;
5023 }
5024 switch (word) {
5025 case 1:
5026 termstr = "Low Off/High Off";
5027 break;
5028 case 2:
5029 termstr = "Low Off/High On";
5030 break;
5031 case 3:
5032 termstr = "Low On/High On";
5033 break;
5034 default:
5035 case 0:
5036 termstr = "Automatic";
5037 break;
5038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005040 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5041 len = asc_prt_line(cp, leftlen,
5042 " termination: %u (%s), bios_ctrl: 0x%x\n",
5043 ep_3550->termination, termstr,
5044 ep_3550->bios_ctrl);
5045 ASC_PRT_NEXT();
5046 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5047 len = asc_prt_line(cp, leftlen,
5048 " termination: %u (%s), bios_ctrl: 0x%x\n",
5049 ep_38C0800->termination_lvd, termstr,
5050 ep_38C0800->bios_ctrl);
5051 ASC_PRT_NEXT();
5052 } else {
5053 len = asc_prt_line(cp, leftlen,
5054 " termination: %u (%s), bios_ctrl: 0x%x\n",
5055 ep_38C1600->termination_lvd, termstr,
5056 ep_38C1600->bios_ctrl);
5057 ASC_PRT_NEXT();
5058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005060 len = asc_prt_line(cp, leftlen, " Target ID: ");
5061 ASC_PRT_NEXT();
5062 for (i = 0; i <= ADV_MAX_TID; i++) {
5063 len = asc_prt_line(cp, leftlen, " %X", i);
5064 ASC_PRT_NEXT();
5065 }
5066 len = asc_prt_line(cp, leftlen, "\n");
5067 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005069 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5070 word = ep_3550->disc_enable;
5071 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5072 word = ep_38C0800->disc_enable;
5073 } else {
5074 word = ep_38C1600->disc_enable;
5075 }
5076 len = asc_prt_line(cp, leftlen, " Disconnects: ");
5077 ASC_PRT_NEXT();
5078 for (i = 0; i <= ADV_MAX_TID; i++) {
5079 len = asc_prt_line(cp, leftlen, " %c",
5080 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5081 ASC_PRT_NEXT();
5082 }
5083 len = asc_prt_line(cp, leftlen, "\n");
5084 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005086 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5087 word = ep_3550->tagqng_able;
5088 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5089 word = ep_38C0800->tagqng_able;
5090 } else {
5091 word = ep_38C1600->tagqng_able;
5092 }
5093 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
5094 ASC_PRT_NEXT();
5095 for (i = 0; i <= ADV_MAX_TID; i++) {
5096 len = asc_prt_line(cp, leftlen, " %c",
5097 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5098 ASC_PRT_NEXT();
5099 }
5100 len = asc_prt_line(cp, leftlen, "\n");
5101 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005103 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5104 word = ep_3550->start_motor;
5105 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5106 word = ep_38C0800->start_motor;
5107 } else {
5108 word = ep_38C1600->start_motor;
5109 }
5110 len = asc_prt_line(cp, leftlen, " Start Motor: ");
5111 ASC_PRT_NEXT();
5112 for (i = 0; i <= ADV_MAX_TID; i++) {
5113 len = asc_prt_line(cp, leftlen, " %c",
5114 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5115 ASC_PRT_NEXT();
5116 }
5117 len = asc_prt_line(cp, leftlen, "\n");
5118 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005120 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5121 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5122 ASC_PRT_NEXT();
5123 for (i = 0; i <= ADV_MAX_TID; i++) {
5124 len = asc_prt_line(cp, leftlen, " %c",
5125 (ep_3550->
5126 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
5127 'Y' : 'N');
5128 ASC_PRT_NEXT();
5129 }
5130 len = asc_prt_line(cp, leftlen, "\n");
5131 ASC_PRT_NEXT();
5132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005134 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5135 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
5136 ASC_PRT_NEXT();
5137 for (i = 0; i <= ADV_MAX_TID; i++) {
5138 len = asc_prt_line(cp, leftlen, " %c",
5139 (ep_3550->
5140 ultra_able & ADV_TID_TO_TIDMASK(i))
5141 ? 'Y' : 'N');
5142 ASC_PRT_NEXT();
5143 }
5144 len = asc_prt_line(cp, leftlen, "\n");
5145 ASC_PRT_NEXT();
5146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005148 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5149 word = ep_3550->wdtr_able;
5150 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5151 word = ep_38C0800->wdtr_able;
5152 } else {
5153 word = ep_38C1600->wdtr_able;
5154 }
5155 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
5156 ASC_PRT_NEXT();
5157 for (i = 0; i <= ADV_MAX_TID; i++) {
5158 len = asc_prt_line(cp, leftlen, " %c",
5159 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5160 ASC_PRT_NEXT();
5161 }
5162 len = asc_prt_line(cp, leftlen, "\n");
5163 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005165 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
5166 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
5167 len = asc_prt_line(cp, leftlen,
5168 " Synchronous Transfer Speed (Mhz):\n ");
5169 ASC_PRT_NEXT();
5170 for (i = 0; i <= ADV_MAX_TID; i++) {
5171 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005173 if (i == 0) {
5174 sdtr_speed = adv_dvc_varp->sdtr_speed1;
5175 } else if (i == 4) {
5176 sdtr_speed = adv_dvc_varp->sdtr_speed2;
5177 } else if (i == 8) {
5178 sdtr_speed = adv_dvc_varp->sdtr_speed3;
5179 } else if (i == 12) {
5180 sdtr_speed = adv_dvc_varp->sdtr_speed4;
5181 }
5182 switch (sdtr_speed & ADV_MAX_TID) {
5183 case 0:
5184 speed_str = "Off";
5185 break;
5186 case 1:
5187 speed_str = " 5";
5188 break;
5189 case 2:
5190 speed_str = " 10";
5191 break;
5192 case 3:
5193 speed_str = " 20";
5194 break;
5195 case 4:
5196 speed_str = " 40";
5197 break;
5198 case 5:
5199 speed_str = " 80";
5200 break;
5201 default:
5202 speed_str = "Unk";
5203 break;
5204 }
5205 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
5206 ASC_PRT_NEXT();
5207 if (i == 7) {
5208 len = asc_prt_line(cp, leftlen, "\n ");
5209 ASC_PRT_NEXT();
5210 }
5211 sdtr_speed >>= 4;
5212 }
5213 len = asc_prt_line(cp, leftlen, "\n");
5214 ASC_PRT_NEXT();
5215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005217 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218}
5219
5220/*
5221 * asc_prt_driver_conf()
5222 *
5223 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5224 * cf. asc_prt_line().
5225 *
5226 * Return the number of characters copied into 'cp'. No more than
5227 * 'cplen' characters will be copied to 'cp'.
5228 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005229static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005231 asc_board_t *boardp;
5232 int leftlen;
5233 int totlen;
5234 int len;
5235 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005237 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005239 leftlen = cplen;
5240 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005242 len = asc_prt_line(cp, leftlen,
5243 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
5244 shost->host_no);
5245 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005247 len = asc_prt_line(cp, leftlen,
5248 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
5249 shost->host_busy, shost->last_reset, shost->max_id,
5250 shost->max_lun, shost->max_channel);
5251 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005253 len = asc_prt_line(cp, leftlen,
5254 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
5255 shost->unique_id, shost->can_queue, shost->this_id,
5256 shost->sg_tablesize, shost->cmd_per_lun);
5257 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005259 len = asc_prt_line(cp, leftlen,
5260 " unchecked_isa_dma %d, use_clustering %d\n",
5261 shost->unchecked_isa_dma, shost->use_clustering);
5262 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005264 len = asc_prt_line(cp, leftlen,
5265 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
5266 boardp->flags, boardp->last_reset, jiffies,
5267 boardp->asc_n_io_port);
5268 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04005270 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005271 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005273 if (ASC_NARROW_BOARD(boardp)) {
5274 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
5275 } else {
5276 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
5277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005279 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280}
5281
5282/*
5283 * asc_prt_asc_board_info()
5284 *
5285 * Print dynamic board configuration information.
5286 *
5287 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5288 * cf. asc_prt_line().
5289 *
5290 * Return the number of characters copied into 'cp'. No more than
5291 * 'cplen' characters will be copied to 'cp'.
5292 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005293static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005295 asc_board_t *boardp;
5296 int chip_scsi_id;
5297 int leftlen;
5298 int totlen;
5299 int len;
5300 ASC_DVC_VAR *v;
5301 ASC_DVC_CFG *c;
5302 int i;
5303 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005305 boardp = ASC_BOARDP(shost);
5306 v = &boardp->dvc_var.asc_dvc_var;
5307 c = &boardp->dvc_cfg.asc_dvc_cfg;
5308 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005310 leftlen = cplen;
5311 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005313 len = asc_prt_line(cp, leftlen,
5314 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5315 shost->host_no);
5316 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005318 len = asc_prt_line(cp, leftlen,
5319 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
5320 c->chip_version, c->lib_version, c->lib_serial_no,
5321 c->mcode_date);
5322 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005324 len = asc_prt_line(cp, leftlen,
5325 " mcode_version 0x%x, err_code %u\n",
5326 c->mcode_version, v->err_code);
5327 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005329 /* Current number of commands waiting for the host. */
5330 len = asc_prt_line(cp, leftlen,
5331 " Total Command Pending: %d\n", v->cur_total_qng);
5332 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005334 len = asc_prt_line(cp, leftlen, " Command Queuing:");
5335 ASC_PRT_NEXT();
5336 for (i = 0; i <= ASC_MAX_TID; i++) {
5337 if ((chip_scsi_id == i) ||
5338 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5339 continue;
5340 }
5341 len = asc_prt_line(cp, leftlen, " %X:%c",
5342 i,
5343 (v->
5344 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
5345 'Y' : 'N');
5346 ASC_PRT_NEXT();
5347 }
5348 len = asc_prt_line(cp, leftlen, "\n");
5349 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005351 /* Current number of commands waiting for a device. */
5352 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
5353 ASC_PRT_NEXT();
5354 for (i = 0; i <= ASC_MAX_TID; i++) {
5355 if ((chip_scsi_id == i) ||
5356 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5357 continue;
5358 }
5359 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
5360 ASC_PRT_NEXT();
5361 }
5362 len = asc_prt_line(cp, leftlen, "\n");
5363 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005365 /* Current limit on number of commands that can be sent to a device. */
5366 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
5367 ASC_PRT_NEXT();
5368 for (i = 0; i <= ASC_MAX_TID; i++) {
5369 if ((chip_scsi_id == i) ||
5370 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5371 continue;
5372 }
5373 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
5374 ASC_PRT_NEXT();
5375 }
5376 len = asc_prt_line(cp, leftlen, "\n");
5377 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005379 /* Indicate whether the device has returned queue full status. */
5380 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
5381 ASC_PRT_NEXT();
5382 for (i = 0; i <= ASC_MAX_TID; i++) {
5383 if ((chip_scsi_id == i) ||
5384 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5385 continue;
5386 }
5387 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
5388 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
5389 i, boardp->queue_full_cnt[i]);
5390 } else {
5391 len = asc_prt_line(cp, leftlen, " %X:N", i);
5392 }
5393 ASC_PRT_NEXT();
5394 }
5395 len = asc_prt_line(cp, leftlen, "\n");
5396 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005398 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5399 ASC_PRT_NEXT();
5400 for (i = 0; i <= ASC_MAX_TID; i++) {
5401 if ((chip_scsi_id == i) ||
5402 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5403 continue;
5404 }
5405 len = asc_prt_line(cp, leftlen, " %X:%c",
5406 i,
5407 (v->
5408 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5409 'N');
5410 ASC_PRT_NEXT();
5411 }
5412 len = asc_prt_line(cp, leftlen, "\n");
5413 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005415 for (i = 0; i <= ASC_MAX_TID; i++) {
5416 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005418 if ((chip_scsi_id == i) ||
5419 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5420 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
5421 continue;
5422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005424 len = asc_prt_line(cp, leftlen, " %X:", i);
5425 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005427 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
5428 len = asc_prt_line(cp, leftlen, " Asynchronous");
5429 ASC_PRT_NEXT();
5430 } else {
5431 syn_period_ix =
5432 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
5433 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005435 len = asc_prt_line(cp, leftlen,
5436 " Transfer Period Factor: %d (%d.%d Mhz),",
5437 v->sdtr_period_tbl[syn_period_ix],
5438 250 /
5439 v->sdtr_period_tbl[syn_period_ix],
5440 ASC_TENTHS(250,
5441 v->
5442 sdtr_period_tbl
5443 [syn_period_ix]));
5444 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005446 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5447 boardp->
5448 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
5449 ASC_PRT_NEXT();
5450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005452 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5453 len = asc_prt_line(cp, leftlen, "*\n");
5454 renegotiate = 1;
5455 } else {
5456 len = asc_prt_line(cp, leftlen, "\n");
5457 }
5458 ASC_PRT_NEXT();
5459 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005461 if (renegotiate) {
5462 len = asc_prt_line(cp, leftlen,
5463 " * = Re-negotiation pending before next command.\n");
5464 ASC_PRT_NEXT();
5465 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005467 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468}
5469
5470/*
5471 * asc_prt_adv_board_info()
5472 *
5473 * Print dynamic board configuration information.
5474 *
5475 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5476 * cf. asc_prt_line().
5477 *
5478 * Return the number of characters copied into 'cp'. No more than
5479 * 'cplen' characters will be copied to 'cp'.
5480 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005481static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005482{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005483 asc_board_t *boardp;
5484 int leftlen;
5485 int totlen;
5486 int len;
5487 int i;
5488 ADV_DVC_VAR *v;
5489 ADV_DVC_CFG *c;
5490 AdvPortAddr iop_base;
5491 ushort chip_scsi_id;
5492 ushort lramword;
5493 uchar lrambyte;
5494 ushort tagqng_able;
5495 ushort sdtr_able, wdtr_able;
5496 ushort wdtr_done, sdtr_done;
5497 ushort period = 0;
5498 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005500 boardp = ASC_BOARDP(shost);
5501 v = &boardp->dvc_var.adv_dvc_var;
5502 c = &boardp->dvc_cfg.adv_dvc_cfg;
5503 iop_base = v->iop_base;
5504 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005506 leftlen = cplen;
5507 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005509 len = asc_prt_line(cp, leftlen,
5510 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5511 shost->host_no);
5512 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005514 len = asc_prt_line(cp, leftlen,
5515 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
5516 v->iop_base,
5517 AdvReadWordRegister(iop_base,
5518 IOPW_SCSI_CFG1) & CABLE_DETECT,
5519 v->err_code);
5520 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005522 len = asc_prt_line(cp, leftlen,
5523 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
5524 c->chip_version, c->lib_version, c->mcode_date,
5525 c->mcode_version);
5526 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005528 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
5529 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
5530 ASC_PRT_NEXT();
5531 for (i = 0; i <= ADV_MAX_TID; i++) {
5532 if ((chip_scsi_id == i) ||
5533 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5534 continue;
5535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005537 len = asc_prt_line(cp, leftlen, " %X:%c",
5538 i,
5539 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5540 'N');
5541 ASC_PRT_NEXT();
5542 }
5543 len = asc_prt_line(cp, leftlen, "\n");
5544 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005546 len = asc_prt_line(cp, leftlen, " Queue Limit:");
5547 ASC_PRT_NEXT();
5548 for (i = 0; i <= ADV_MAX_TID; i++) {
5549 if ((chip_scsi_id == i) ||
5550 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5551 continue;
5552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005554 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
5555 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005557 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5558 ASC_PRT_NEXT();
5559 }
5560 len = asc_prt_line(cp, leftlen, "\n");
5561 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005563 len = asc_prt_line(cp, leftlen, " Command Pending:");
5564 ASC_PRT_NEXT();
5565 for (i = 0; i <= ADV_MAX_TID; i++) {
5566 if ((chip_scsi_id == i) ||
5567 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5568 continue;
5569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005571 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
5572 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005574 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5575 ASC_PRT_NEXT();
5576 }
5577 len = asc_prt_line(cp, leftlen, "\n");
5578 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005580 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
5581 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
5582 ASC_PRT_NEXT();
5583 for (i = 0; i <= ADV_MAX_TID; i++) {
5584 if ((chip_scsi_id == i) ||
5585 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5586 continue;
5587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005589 len = asc_prt_line(cp, leftlen, " %X:%c",
5590 i,
5591 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5592 'N');
5593 ASC_PRT_NEXT();
5594 }
5595 len = asc_prt_line(cp, leftlen, "\n");
5596 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005598 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
5599 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
5600 ASC_PRT_NEXT();
5601 for (i = 0; i <= ADV_MAX_TID; i++) {
5602 if ((chip_scsi_id == i) ||
5603 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5604 continue;
5605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005607 AdvReadWordLram(iop_base,
5608 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5609 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005611 len = asc_prt_line(cp, leftlen, " %X:%d",
5612 i, (lramword & 0x8000) ? 16 : 8);
5613 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005614
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005615 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
5616 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5617 len = asc_prt_line(cp, leftlen, "*");
5618 ASC_PRT_NEXT();
5619 renegotiate = 1;
5620 }
5621 }
5622 len = asc_prt_line(cp, leftlen, "\n");
5623 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005625 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
5626 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
5627 ASC_PRT_NEXT();
5628 for (i = 0; i <= ADV_MAX_TID; i++) {
5629 if ((chip_scsi_id == i) ||
5630 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5631 continue;
5632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005634 len = asc_prt_line(cp, leftlen, " %X:%c",
5635 i,
5636 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5637 'N');
5638 ASC_PRT_NEXT();
5639 }
5640 len = asc_prt_line(cp, leftlen, "\n");
5641 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005643 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
5644 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005646 AdvReadWordLram(iop_base,
5647 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5648 lramword);
5649 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005651 if ((chip_scsi_id == i) ||
5652 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5653 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
5654 continue;
5655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005657 len = asc_prt_line(cp, leftlen, " %X:", i);
5658 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005660 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
5661 len = asc_prt_line(cp, leftlen, " Asynchronous");
5662 ASC_PRT_NEXT();
5663 } else {
5664 len =
5665 asc_prt_line(cp, leftlen,
5666 " Transfer Period Factor: ");
5667 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005669 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
5670 len =
5671 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
5672 ASC_PRT_NEXT();
5673 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
5674 len =
5675 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
5676 ASC_PRT_NEXT();
5677 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005679 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005681 if (period == 0) { /* Should never happen. */
5682 len =
5683 asc_prt_line(cp, leftlen,
5684 "%d (? Mhz), ");
5685 ASC_PRT_NEXT();
5686 } else {
5687 len = asc_prt_line(cp, leftlen,
5688 "%d (%d.%d Mhz),",
5689 period, 250 / period,
5690 ASC_TENTHS(250,
5691 period));
5692 ASC_PRT_NEXT();
5693 }
5694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005696 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5697 lramword & 0x1F);
5698 ASC_PRT_NEXT();
5699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005701 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5702 len = asc_prt_line(cp, leftlen, "*\n");
5703 renegotiate = 1;
5704 } else {
5705 len = asc_prt_line(cp, leftlen, "\n");
5706 }
5707 ASC_PRT_NEXT();
5708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005710 if (renegotiate) {
5711 len = asc_prt_line(cp, leftlen,
5712 " * = Re-negotiation pending before next command.\n");
5713 ASC_PRT_NEXT();
5714 }
5715
5716 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717}
5718
5719/*
5720 * asc_proc_copy()
5721 *
5722 * Copy proc information to a read buffer taking into account the current
5723 * read offset in the file and the remaining space in the read buffer.
5724 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005725static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005727 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005728{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005729 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005731 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
5732 (unsigned)offset, (unsigned)advoffset, cplen);
5733 if (offset <= advoffset) {
5734 /* Read offset below current offset, copy everything. */
5735 cnt = min(cplen, leftlen);
5736 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5737 (ulong)curbuf, (ulong)cp, cnt);
5738 memcpy(curbuf, cp, cnt);
5739 } else if (offset < advoffset + cplen) {
5740 /* Read offset within current range, partial copy. */
5741 cnt = (advoffset + cplen) - offset;
5742 cp = (cp + cplen) - cnt;
5743 cnt = min(cnt, leftlen);
5744 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5745 (ulong)curbuf, (ulong)cp, cnt);
5746 memcpy(curbuf, cp, cnt);
5747 }
5748 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005749}
5750
5751/*
5752 * asc_prt_line()
5753 *
5754 * If 'cp' is NULL print to the console, otherwise print to a buffer.
5755 *
5756 * Return 0 if printing to the console, otherwise return the number of
5757 * bytes written to the buffer.
5758 *
5759 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
5760 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
5761 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005762static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005764 va_list args;
5765 int ret;
5766 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005768 va_start(args, fmt);
5769 ret = vsprintf(s, fmt, args);
5770 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
5771 if (buf == NULL) {
5772 (void)printk(s);
5773 ret = 0;
5774 } else {
5775 ret = min(buflen, ret);
5776 memcpy(buf, s, ret);
5777 }
5778 va_end(args);
5779 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780}
5781#endif /* CONFIG_PROC_FS */
5782
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783/*
5784 * --- Functions Required by the Asc Library
5785 */
5786
5787/*
5788 * Delay for 'n' milliseconds. Don't use the 'jiffies'
5789 * global variable which is incremented once every 5 ms
5790 * from a timer interrupt, because this function may be
5791 * called when interrupts are disabled.
5792 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005793static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005795 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
5796 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797}
5798
5799/*
5800 * Currently and inline noop but leave as a placeholder.
5801 * Leave DvcEnterCritical() as a noop placeholder.
5802 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005803static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005805 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806}
5807
5808/*
5809 * Critical sections are all protected by the board spinlock.
5810 * Leave DvcLeaveCritical() as a noop placeholder.
5811 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005812static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005814 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815}
5816
5817/*
5818 * void
5819 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5820 *
5821 * Calling/Exit State:
5822 * none
5823 *
5824 * Description:
5825 * Output an ASC_SCSI_Q structure to the chip
5826 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005827static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005828DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5829{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005830 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005831
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005832 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
5833 AscSetChipLramAddr(iop_base, s_addr);
5834 for (i = 0; i < 2 * words; i += 2) {
5835 if (i == 4 || i == 20) {
5836 continue;
5837 }
5838 outpw(iop_base + IOP_RAM_DATA,
5839 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
5840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841}
5842
5843/*
5844 * void
5845 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5846 *
5847 * Calling/Exit State:
5848 * none
5849 *
5850 * Description:
5851 * Input an ASC_QDONE_INFO structure from the chip
5852 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005853static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5855{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005856 int i;
5857 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005859 AscSetChipLramAddr(iop_base, s_addr);
5860 for (i = 0; i < 2 * words; i += 2) {
5861 if (i == 10) {
5862 continue;
5863 }
5864 word = inpw(iop_base + IOP_RAM_DATA);
5865 inbuf[i] = word & 0xff;
5866 inbuf[i + 1] = (word >> 8) & 0xff;
5867 }
5868 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869}
5870
5871/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872 * Return the BIOS address of the adapter at the specified
5873 * I/O port and with the specified bus type.
5874 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005875static unsigned short __devinit
5876AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005878 unsigned short cfg_lsw;
5879 unsigned short bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005881 /*
5882 * The PCI BIOS is re-located by the motherboard BIOS. Because
5883 * of this the driver can not determine where a PCI BIOS is
5884 * loaded and executes.
5885 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005886 if (bus_type & ASC_IS_PCI)
5887 return 0;
5888
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005890 if ((bus_type & ASC_IS_EISA) != 0) {
5891 cfg_lsw = AscGetEisaChipCfg(iop_base);
5892 cfg_lsw &= 0x000F;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005893 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
5894 return bios_addr;
5895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005896#endif /* CONFIG_ISA */
5897
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005898 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005900 /*
5901 * ISA PnP uses the top bit as the 32K BIOS flag
5902 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005903 if (bus_type == ASC_IS_ISAPNP)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005904 cfg_lsw &= 0x7FFF;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005905 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
5906 return bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907}
5908
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909/*
5910 * --- Functions Required by the Adv Library
5911 */
5912
5913/*
5914 * DvcGetPhyAddr()
5915 *
5916 * Return the physical address of 'vaddr' and set '*lenp' to the
5917 * number of physically contiguous bytes that follow 'vaddr'.
5918 * 'flag' indicates the type of structure whose physical address
5919 * is being translated.
5920 *
5921 * Note: Because Linux currently doesn't page the kernel and all
5922 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
5923 */
5924ADV_PADDR
5925DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005926 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005928 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005930 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005932 ASC_DBG4(4,
5933 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
5934 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
5935 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005937 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005938}
5939
5940/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941 * --- Tracing and Debugging Functions
5942 */
5943
5944#ifdef ADVANSYS_STATS
5945#ifdef CONFIG_PROC_FS
5946/*
5947 * asc_prt_board_stats()
5948 *
5949 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5950 * cf. asc_prt_line().
5951 *
5952 * Return the number of characters copied into 'cp'. No more than
5953 * 'cplen' characters will be copied to 'cp'.
5954 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005955static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005957 int leftlen;
5958 int totlen;
5959 int len;
5960 struct asc_stats *s;
5961 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005963 leftlen = cplen;
5964 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005966 boardp = ASC_BOARDP(shost);
5967 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005969 len = asc_prt_line(cp, leftlen,
5970 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
5971 shost->host_no);
5972 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005974 len = asc_prt_line(cp, leftlen,
5975 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
5976 s->queuecommand, s->reset, s->biosparam,
5977 s->interrupt);
5978 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005980 len = asc_prt_line(cp, leftlen,
5981 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
5982 s->callback, s->done, s->build_error,
5983 s->adv_build_noreq, s->adv_build_nosg);
5984 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005986 len = asc_prt_line(cp, leftlen,
5987 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
5988 s->exe_noerror, s->exe_busy, s->exe_error,
5989 s->exe_unknown);
5990 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005992 /*
5993 * Display data transfer statistics.
5994 */
5995 if (s->cont_cnt > 0) {
5996 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
5997 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005999 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
6000 s->cont_xfer / 2,
6001 ASC_TENTHS(s->cont_xfer, 2));
6002 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006004 /* Contiguous transfer average size */
6005 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
6006 (s->cont_xfer / 2) / s->cont_cnt,
6007 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
6008 ASC_PRT_NEXT();
6009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006011 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006013 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
6014 s->sg_cnt, s->sg_elem);
6015 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006017 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
6018 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
6019 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006020
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006021 /* Scatter gather transfer statistics */
6022 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
6023 s->sg_elem / s->sg_cnt,
6024 ASC_TENTHS(s->sg_elem, s->sg_cnt));
6025 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006027 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
6028 (s->sg_xfer / 2) / s->sg_elem,
6029 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
6030 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006032 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
6033 (s->sg_xfer / 2) / s->sg_cnt,
6034 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
6035 ASC_PRT_NEXT();
6036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006038 /*
6039 * Display request queuing statistics.
6040 */
6041 len = asc_prt_line(cp, leftlen,
6042 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
6043 HZ);
6044 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006046 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006047}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048#endif /* CONFIG_PROC_FS */
6049#endif /* ADVANSYS_STATS */
6050
6051#ifdef ADVANSYS_DEBUG
6052/*
6053 * asc_prt_scsi_host()
6054 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006055static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006057 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006059 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006061 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
6062 printk(" host_busy %u, host_no %d, last_reset %d,\n",
6063 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04006065 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
6066 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006068 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
6069 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006071 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
6072 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006074 if (ASC_NARROW_BOARD(boardp)) {
6075 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
6076 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
6077 } else {
6078 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
6079 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
6080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081}
6082
6083/*
6084 * asc_prt_scsi_cmnd()
6085 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006086static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006088 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006090 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
6091 (ulong)s->device->host, (ulong)s->device, s->device->id,
6092 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006094 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006096 printk("sc_data_direction %u, resid %d\n",
6097 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006099 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006101 printk(" serial_number 0x%x, retries %d, allowed %d\n",
6102 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006104 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006106 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
6107 s->scsi_done, s->done, s->host_scribble, s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006109 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110}
6111
6112/*
6113 * asc_prt_asc_dvc_var()
6114 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006115static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006117 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006119 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
6120 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Matthew Wilcox895d6b42007-07-26 11:57:06 -04006122 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
6123 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006125 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
6126 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
6127 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
6128 (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006130 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
6131 "%u,\n", (unsigned)h->queue_full_or_busy,
6132 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006133
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006134 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
6135 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
6136 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
6137 (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006139 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
6140 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
6141 (unsigned)h->init_state, (unsigned)h->no_scam,
6142 (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006144 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145}
6146
6147/*
6148 * asc_prt_asc_dvc_cfg()
6149 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006150static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006152 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006154 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
6155 h->can_tagged_qng, h->cmd_qng_enabled);
6156 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
6157 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006158
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006159 printk
6160 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
6161 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
6162 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006164 printk
6165 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
6166 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
6167 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006168
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006169 printk(" mcode_version %d, overrun_buf 0x%lx\n",
6170 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006171}
6172
6173/*
6174 * asc_prt_asc_scsi_q()
6175 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006176static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006177{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006178 ASC_SG_HEAD *sgp;
6179 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006181 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006182
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006183 printk
6184 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
6185 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
6186 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006188 printk
6189 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6190 (ulong)le32_to_cpu(q->q1.data_addr),
6191 (ulong)le32_to_cpu(q->q1.data_cnt),
6192 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006193
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006194 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
6195 (ulong)q->cdbptr, q->q2.cdb_len,
6196 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006198 if (q->sg_head) {
6199 sgp = q->sg_head;
6200 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
6201 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
6202 sgp->queue_cnt);
6203 for (i = 0; i < sgp->entry_cnt; i++) {
6204 printk(" [%u]: addr 0x%lx, bytes %lu\n",
6205 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
6206 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
6207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006208
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210}
6211
6212/*
6213 * asc_prt_asc_qdone_info()
6214 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006215static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006217 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
6218 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
6219 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
6220 q->d2.tag_code);
6221 printk
6222 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
6223 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224}
6225
6226/*
6227 * asc_prt_adv_dvc_var()
6228 *
6229 * Display an ADV_DVC_VAR structure.
6230 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006231static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006233 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006235 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
6236 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006238 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
6239 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
6240 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006241
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006242 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
6243 (unsigned)h->start_motor,
6244 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006246 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
6247 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
6248 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006250 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
6251 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006253 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
6254 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006256 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
6257 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258}
6259
6260/*
6261 * asc_prt_adv_dvc_cfg()
6262 *
6263 * Display an ADV_DVC_CFG structure.
6264 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006265static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006267 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006268
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006269 printk(" disc_enable 0x%x, termination 0x%x\n",
6270 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006272 printk(" chip_version 0x%x, mcode_date 0x%x\n",
6273 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006275 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
6276 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06006278 printk(" control_flag 0x%x\n", h->control_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006279}
6280
6281/*
6282 * asc_prt_adv_scsi_req_q()
6283 *
6284 * Display an ADV_SCSI_REQ_Q structure.
6285 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006286static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006287{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006288 int sg_blk_cnt;
6289 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006291 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006293 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
6294 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006295
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006296 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
6297 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006299 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6300 (ulong)le32_to_cpu(q->data_cnt),
6301 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006303 printk
6304 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
6305 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006307 printk(" sg_working_ix 0x%x, target_cmd %u\n",
6308 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006310 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
6311 (ulong)le32_to_cpu(q->scsiq_rptr),
6312 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006314 /* Display the request's ADV_SG_BLOCK structures. */
6315 if (q->sg_list_ptr != NULL) {
6316 sg_blk_cnt = 0;
6317 while (1) {
6318 /*
6319 * 'sg_ptr' is a physical address. Convert it to a virtual
6320 * address by indexing 'sg_blk_cnt' into the virtual address
6321 * array 'sg_list_ptr'.
6322 *
6323 * XXX - Assumes all SG physical blocks are virtually contiguous.
6324 */
6325 sg_ptr =
6326 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
6327 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
6328 if (sg_ptr->sg_ptr == 0) {
6329 break;
6330 }
6331 sg_blk_cnt++;
6332 }
6333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334}
6335
6336/*
6337 * asc_prt_adv_sgblock()
6338 *
6339 * Display an ADV_SG_BLOCK structure.
6340 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006341static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006342{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006343 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006345 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
6346 (ulong)b, sgblockno);
6347 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
6348 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
6349 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
6350 if (b->sg_ptr != 0) {
6351 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
6352 }
6353 for (i = 0; i < b->sg_cnt; i++) {
6354 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
6355 i, (ulong)b->sg_list[i].sg_addr,
6356 (ulong)b->sg_list[i].sg_count);
6357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006358}
6359
6360/*
6361 * asc_prt_hex()
6362 *
6363 * Print hexadecimal output in 4 byte groupings 32 bytes
6364 * or 8 double-words per line.
6365 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006366static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006367{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006368 int i;
6369 int j;
6370 int k;
6371 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006373 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006374
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006375 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006377 /* Display a maximum of 8 double-words per line. */
6378 if ((k = (l - i) / 4) >= 8) {
6379 k = 8;
6380 m = 0;
6381 } else {
6382 m = (l - i) % 4;
6383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006384
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006385 for (j = 0; j < k; j++) {
6386 printk(" %2.2X%2.2X%2.2X%2.2X",
6387 (unsigned)s[i + (j * 4)],
6388 (unsigned)s[i + (j * 4) + 1],
6389 (unsigned)s[i + (j * 4) + 2],
6390 (unsigned)s[i + (j * 4) + 3]);
6391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006392
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006393 switch (m) {
6394 case 0:
6395 default:
6396 break;
6397 case 1:
6398 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
6399 break;
6400 case 2:
6401 printk(" %2.2X%2.2X",
6402 (unsigned)s[i + (j * 4)],
6403 (unsigned)s[i + (j * 4) + 1]);
6404 break;
6405 case 3:
6406 printk(" %2.2X%2.2X%2.2X",
6407 (unsigned)s[i + (j * 4) + 1],
6408 (unsigned)s[i + (j * 4) + 2],
6409 (unsigned)s[i + (j * 4) + 3]);
6410 break;
6411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006413 printk("\n");
6414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006415}
6416#endif /* ADVANSYS_DEBUG */
6417
6418/*
6419 * --- Asc Library Functions
6420 */
6421
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006422static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006424 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006425
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006426 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6427 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
6428 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006429}
6430
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006431static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006433 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006435 if (AscGetChipScsiID(iop_base) == new_host_id) {
6436 return (new_host_id);
6437 }
6438 cfg_lsw = AscGetChipCfgLsw(iop_base);
6439 cfg_lsw &= 0xF8FF;
6440 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
6441 AscSetChipCfgLsw(iop_base, cfg_lsw);
6442 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006443}
6444
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006445static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006446{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006447 unsigned char sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006449 AscSetBank(iop_base, 1);
6450 sc = inp(iop_base + IOP_REG_SC);
6451 AscSetBank(iop_base, 0);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006452 return sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006453}
6454
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006455static unsigned char __devinit
6456AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006458 if (bus_type & ASC_IS_EISA) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006459 PortAddr eisa_iop;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006460 unsigned char revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006461 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6462 (PortAddr) ASC_EISA_REV_IOP_MASK;
6463 revision = inp(eisa_iop);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006464 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006465 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006466 return AscGetChipVerNo(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006467}
6468
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006469static ASC_DCNT
6470AscLoadMicroCode(PortAddr iop_base,
6471 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006472{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006473 ASC_DCNT chksum;
6474 ushort mcode_word_size;
6475 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006476
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006477 /* Write the microcode buffer starting at LRAM address 0. */
6478 mcode_word_size = (ushort)(mcode_size >> 1);
6479 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
6480 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006481
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006482 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
6483 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
6484 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
6485 (ushort)ASC_CODE_SEC_BEG,
6486 (ushort)((mcode_size -
6487 s_addr - (ushort)
6488 ASC_CODE_SEC_BEG) /
6489 2));
6490 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
6491 (ulong)mcode_chksum);
6492 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
6493 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
6494 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006495}
6496
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006497static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006498{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006499 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006501 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
6502 iop_base, AscGetChipSignatureByte(iop_base));
6503 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
6504 ASC_DBG2(1,
6505 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
6506 iop_base, AscGetChipSignatureWord(iop_base));
6507 sig_word = AscGetChipSignatureWord(iop_base);
6508 if ((sig_word == (ushort)ASC_1000_ID0W) ||
6509 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
6510 return (1);
6511 }
6512 }
6513 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006514}
6515
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006516static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006517{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006518 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
6519 AscSetChipStatus(iop_base, 0);
6520 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006521}
6522
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006523static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006524{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006525 ushort cfg_lsw;
6526 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006528 if ((bus_type & ASC_IS_EISA) != 0) {
6529 cfg_lsw = AscGetEisaChipCfg(iop_base);
6530 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
6531 if ((chip_irq == 13) || (chip_irq > 15)) {
6532 return (0);
6533 }
6534 return (chip_irq);
6535 }
6536 if ((bus_type & ASC_IS_VL) != 0) {
6537 cfg_lsw = AscGetChipCfgLsw(iop_base);
6538 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
6539 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
6540 return (0);
6541 }
6542 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
6543 }
6544 cfg_lsw = AscGetChipCfgLsw(iop_base);
6545 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
6546 if (chip_irq == 3)
6547 chip_irq += (uchar)2;
6548 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006549}
6550
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006551static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006552AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006553{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006554 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006555
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006556 if ((bus_type & ASC_IS_VL) != 0) {
6557 if (irq_no != 0) {
6558 if ((irq_no < ASC_MIN_IRQ_NO)
6559 || (irq_no > ASC_MAX_IRQ_NO)) {
6560 irq_no = 0;
6561 } else {
6562 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
6563 }
6564 }
6565 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
6566 cfg_lsw |= (ushort)0x0010;
6567 AscSetChipCfgLsw(iop_base, cfg_lsw);
6568 AscToggleIRQAct(iop_base);
6569 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
6570 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
6571 AscSetChipCfgLsw(iop_base, cfg_lsw);
6572 AscToggleIRQAct(iop_base);
6573 return (AscGetChipIRQ(iop_base, bus_type));
6574 }
6575 if ((bus_type & (ASC_IS_ISA)) != 0) {
6576 if (irq_no == 15)
6577 irq_no -= (uchar)2;
6578 irq_no -= (uchar)ASC_MIN_IRQ_NO;
6579 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
6580 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
6581 AscSetChipCfgLsw(iop_base, cfg_lsw);
6582 return (AscGetChipIRQ(iop_base, bus_type));
6583 }
6584 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006585}
6586
6587#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006588static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006590 if (dma_channel < 4) {
6591 outp(0x000B, (ushort)(0xC0 | dma_channel));
6592 outp(0x000A, dma_channel);
6593 } else if (dma_channel < 8) {
6594 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
6595 outp(0x00D4, (ushort)(dma_channel - 4));
6596 }
6597 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006598}
6599#endif /* CONFIG_ISA */
6600
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006601static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006602{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006603 EXT_MSG ext_msg;
6604 EXT_MSG out_msg;
6605 ushort halt_q_addr;
6606 int sdtr_accept;
6607 ushort int_halt_code;
6608 ASC_SCSI_BIT_ID_TYPE scsi_busy;
6609 ASC_SCSI_BIT_ID_TYPE target_id;
6610 PortAddr iop_base;
6611 uchar tag_code;
6612 uchar q_status;
6613 uchar halt_qp;
6614 uchar sdtr_data;
6615 uchar target_ix;
6616 uchar q_cntl, tid_no;
6617 uchar cur_dvc_qng;
6618 uchar asyn_sdtr;
6619 uchar scsi_status;
6620 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006622 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
6623 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006624
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006625 iop_base = asc_dvc->iop_base;
6626 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006627
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006628 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
6629 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
6630 target_ix = AscReadLramByte(iop_base,
6631 (ushort)(halt_q_addr +
6632 (ushort)ASC_SCSIQ_B_TARGET_IX));
6633 q_cntl =
6634 AscReadLramByte(iop_base,
6635 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
6636 tid_no = ASC_TIX_TO_TID(target_ix);
6637 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
6638 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6639 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
6640 } else {
6641 asyn_sdtr = 0;
6642 }
6643 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
6644 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6645 AscSetChipSDTR(iop_base, 0, tid_no);
6646 boardp->sdtr_data[tid_no] = 0;
6647 }
6648 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6649 return (0);
6650 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
6651 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6652 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6653 boardp->sdtr_data[tid_no] = asyn_sdtr;
6654 }
6655 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6656 return (0);
6657 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006658
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006659 AscMemWordCopyPtrFromLram(iop_base,
6660 ASCV_MSGIN_BEG,
6661 (uchar *)&ext_msg,
6662 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006663
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006664 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6665 ext_msg.msg_req == EXTENDED_SDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006666 ext_msg.msg_len == MS_SDTR_LEN) {
6667 sdtr_accept = TRUE;
6668 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006669
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006670 sdtr_accept = FALSE;
6671 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
6672 }
6673 if ((ext_msg.xfer_period <
6674 asc_dvc->sdtr_period_tbl[asc_dvc->
6675 host_init_sdtr_index])
6676 || (ext_msg.xfer_period >
6677 asc_dvc->sdtr_period_tbl[asc_dvc->
6678 max_sdtr_index])) {
6679 sdtr_accept = FALSE;
6680 ext_msg.xfer_period =
6681 asc_dvc->sdtr_period_tbl[asc_dvc->
6682 host_init_sdtr_index];
6683 }
6684 if (sdtr_accept) {
6685 sdtr_data =
6686 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
6687 ext_msg.req_ack_offset);
6688 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006689
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006690 q_cntl |= QC_MSG_OUT;
6691 asc_dvc->init_sdtr &= ~target_id;
6692 asc_dvc->sdtr_done &= ~target_id;
6693 AscSetChipSDTR(iop_base, asyn_sdtr,
6694 tid_no);
6695 boardp->sdtr_data[tid_no] = asyn_sdtr;
6696 }
6697 }
6698 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006699
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006700 q_cntl &= ~QC_MSG_OUT;
6701 asc_dvc->init_sdtr &= ~target_id;
6702 asc_dvc->sdtr_done &= ~target_id;
6703 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6704 } else {
6705 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006706
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006707 q_cntl &= ~QC_MSG_OUT;
6708 asc_dvc->sdtr_done |= target_id;
6709 asc_dvc->init_sdtr |= target_id;
6710 asc_dvc->pci_fix_asyn_xfer &=
6711 ~target_id;
6712 sdtr_data =
6713 AscCalSDTRData(asc_dvc,
6714 ext_msg.xfer_period,
6715 ext_msg.
6716 req_ack_offset);
6717 AscSetChipSDTR(iop_base, sdtr_data,
6718 tid_no);
6719 boardp->sdtr_data[tid_no] = sdtr_data;
6720 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006721
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006722 q_cntl |= QC_MSG_OUT;
6723 AscMsgOutSDTR(asc_dvc,
6724 ext_msg.xfer_period,
6725 ext_msg.req_ack_offset);
6726 asc_dvc->pci_fix_asyn_xfer &=
6727 ~target_id;
6728 sdtr_data =
6729 AscCalSDTRData(asc_dvc,
6730 ext_msg.xfer_period,
6731 ext_msg.
6732 req_ack_offset);
6733 AscSetChipSDTR(iop_base, sdtr_data,
6734 tid_no);
6735 boardp->sdtr_data[tid_no] = sdtr_data;
6736 asc_dvc->sdtr_done |= target_id;
6737 asc_dvc->init_sdtr |= target_id;
6738 }
6739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006741 AscWriteLramByte(iop_base,
6742 (ushort)(halt_q_addr +
6743 (ushort)ASC_SCSIQ_B_CNTL),
6744 q_cntl);
6745 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6746 return (0);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006747 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6748 ext_msg.msg_req == EXTENDED_WDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006749 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006750
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006751 ext_msg.wdtr_width = 0;
6752 AscMemWordCopyPtrToLram(iop_base,
6753 ASCV_MSGOUT_BEG,
6754 (uchar *)&ext_msg,
6755 sizeof(EXT_MSG) >> 1);
6756 q_cntl |= QC_MSG_OUT;
6757 AscWriteLramByte(iop_base,
6758 (ushort)(halt_q_addr +
6759 (ushort)ASC_SCSIQ_B_CNTL),
6760 q_cntl);
6761 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6762 return (0);
6763 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006764
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006765 ext_msg.msg_type = MESSAGE_REJECT;
6766 AscMemWordCopyPtrToLram(iop_base,
6767 ASCV_MSGOUT_BEG,
6768 (uchar *)&ext_msg,
6769 sizeof(EXT_MSG) >> 1);
6770 q_cntl |= QC_MSG_OUT;
6771 AscWriteLramByte(iop_base,
6772 (ushort)(halt_q_addr +
6773 (ushort)ASC_SCSIQ_B_CNTL),
6774 q_cntl);
6775 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6776 return (0);
6777 }
6778 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006779
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006780 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006781
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006782 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006783
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006784 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006786 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
6787 q_cntl |= QC_MSG_OUT;
6788 AscMsgOutSDTR(asc_dvc,
6789 asc_dvc->
6790 sdtr_period_tbl[(sdtr_data >> 4) &
6791 (uchar)(asc_dvc->
6792 max_sdtr_index -
6793 1)],
6794 (uchar)(sdtr_data & (uchar)
6795 ASC_SYN_MAX_OFFSET));
6796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006797
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006798 AscWriteLramByte(iop_base,
6799 (ushort)(halt_q_addr +
6800 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006802 tag_code = AscReadLramByte(iop_base,
6803 (ushort)(halt_q_addr + (ushort)
6804 ASC_SCSIQ_B_TAG_CODE));
6805 tag_code &= 0xDC;
6806 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
6807 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
6808 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006809
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006810 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
6811 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006813 }
6814 AscWriteLramByte(iop_base,
6815 (ushort)(halt_q_addr +
6816 (ushort)ASC_SCSIQ_B_TAG_CODE),
6817 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006818
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006819 q_status = AscReadLramByte(iop_base,
6820 (ushort)(halt_q_addr + (ushort)
6821 ASC_SCSIQ_B_STATUS));
6822 q_status |= (QS_READY | QS_BUSY);
6823 AscWriteLramByte(iop_base,
6824 (ushort)(halt_q_addr +
6825 (ushort)ASC_SCSIQ_B_STATUS),
6826 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006827
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006828 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
6829 scsi_busy &= ~target_id;
6830 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006831
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006832 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6833 return (0);
6834 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006835
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006836 AscMemWordCopyPtrFromLram(iop_base,
6837 ASCV_MSGOUT_BEG,
6838 (uchar *)&out_msg,
6839 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006840
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006841 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006842 (out_msg.msg_len == MS_SDTR_LEN) &&
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006843 (out_msg.msg_req == EXTENDED_SDTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006844
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006845 asc_dvc->init_sdtr &= ~target_id;
6846 asc_dvc->sdtr_done &= ~target_id;
6847 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6848 boardp->sdtr_data[tid_no] = asyn_sdtr;
6849 }
6850 q_cntl &= ~QC_MSG_OUT;
6851 AscWriteLramByte(iop_base,
6852 (ushort)(halt_q_addr +
6853 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
6854 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6855 return (0);
6856 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006858 scsi_status = AscReadLramByte(iop_base,
6859 (ushort)((ushort)halt_q_addr +
6860 (ushort)
6861 ASC_SCSIQ_SCSI_STATUS));
6862 cur_dvc_qng =
6863 AscReadLramByte(iop_base,
6864 (ushort)((ushort)ASC_QADR_BEG +
6865 (ushort)target_ix));
6866 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006868 scsi_busy = AscReadLramByte(iop_base,
6869 (ushort)ASCV_SCSIBUSY_B);
6870 scsi_busy |= target_id;
6871 AscWriteLramByte(iop_base,
6872 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
6873 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006875 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
6876 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
6877 cur_dvc_qng -= 1;
6878 asc_dvc->max_dvc_qng[tid_no] =
6879 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006881 AscWriteLramByte(iop_base,
6882 (ushort)((ushort)
6883 ASCV_MAX_DVC_QNG_BEG
6884 + (ushort)
6885 tid_no),
6886 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006888 /*
6889 * Set the device queue depth to the number of
6890 * active requests when the QUEUE FULL condition
6891 * was encountered.
6892 */
6893 boardp->queue_full |= target_id;
6894 boardp->queue_full_cnt[tid_no] =
6895 cur_dvc_qng;
6896 }
6897 }
6898 }
6899 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6900 return (0);
6901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006902#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006903 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
6904 uchar q_no;
6905 ushort q_addr;
6906 uchar sg_wk_q_no;
6907 uchar first_sg_wk_q_no;
6908 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
6909 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
6910 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
6911 ushort sg_list_dwords;
6912 ushort sg_entry_cnt;
6913 uchar next_qp;
6914 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006916 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
6917 if (q_no == ASC_QLINK_END) {
6918 return (0);
6919 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006920
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006921 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006922
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006923 /*
6924 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
6925 * structure pointer using a macro provided by the driver.
6926 * The ASC_SCSI_REQ pointer provides a pointer to the
6927 * host ASC_SG_HEAD structure.
6928 */
6929 /* Read request's SRB pointer. */
6930 scsiq = (ASC_SCSI_Q *)
6931 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
6932 (ushort)
6933 (q_addr +
6934 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006936 /*
6937 * Get request's first and working SG queue.
6938 */
6939 sg_wk_q_no = AscReadLramByte(iop_base,
6940 (ushort)(q_addr +
6941 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006942
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006943 first_sg_wk_q_no = AscReadLramByte(iop_base,
6944 (ushort)(q_addr +
6945 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006946
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006947 /*
6948 * Reset request's working SG queue back to the
6949 * first SG queue.
6950 */
6951 AscWriteLramByte(iop_base,
6952 (ushort)(q_addr +
6953 (ushort)ASC_SCSIQ_B_SG_WK_QP),
6954 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006955
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006956 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006958 /*
6959 * Set sg_entry_cnt to the number of SG elements
6960 * that will be completed on this interrupt.
6961 *
6962 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
6963 * SG elements. The data_cnt and data_addr fields which
6964 * add 1 to the SG element capacity are not used when
6965 * restarting SG handling after a halt.
6966 */
6967 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
6968 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006970 /*
6971 * Keep track of remaining number of SG elements that will
6972 * need to be handled on the next interrupt.
6973 */
6974 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
6975 } else {
6976 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
6977 scsiq->remain_sg_entry_cnt = 0;
6978 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006979
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006980 /*
6981 * Copy SG elements into the list of allocated SG queues.
6982 *
6983 * Last index completed is saved in scsiq->next_sg_index.
6984 */
6985 next_qp = first_sg_wk_q_no;
6986 q_addr = ASC_QNO_TO_QADDR(next_qp);
6987 scsi_sg_q.sg_head_qp = q_no;
6988 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
6989 for (i = 0; i < sg_head->queue_cnt; i++) {
6990 scsi_sg_q.seq_no = i + 1;
6991 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
6992 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
6993 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
6994 /*
6995 * After very first SG queue RISC FW uses next
6996 * SG queue first element then checks sg_list_cnt
6997 * against zero and then decrements, so set
6998 * sg_list_cnt 1 less than number of SG elements
6999 * in each SG queue.
7000 */
7001 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
7002 scsi_sg_q.sg_cur_list_cnt =
7003 ASC_SG_LIST_PER_Q - 1;
7004 } else {
7005 /*
7006 * This is the last SG queue in the list of
7007 * allocated SG queues. If there are more
7008 * SG elements than will fit in the allocated
7009 * queues, then set the QCSG_SG_XFER_MORE flag.
7010 */
7011 if (scsiq->remain_sg_entry_cnt != 0) {
7012 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
7013 } else {
7014 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
7015 }
7016 /* equals sg_entry_cnt * 2 */
7017 sg_list_dwords = sg_entry_cnt << 1;
7018 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
7019 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
7020 sg_entry_cnt = 0;
7021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007022
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007023 scsi_sg_q.q_no = next_qp;
7024 AscMemWordCopyPtrToLram(iop_base,
7025 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
7026 (uchar *)&scsi_sg_q,
7027 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007028
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007029 AscMemDWordCopyPtrToLram(iop_base,
7030 q_addr + ASC_SGQ_LIST_BEG,
7031 (uchar *)&sg_head->
7032 sg_list[scsiq->next_sg_index],
7033 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007035 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007036
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007037 /*
7038 * If the just completed SG queue contained the
7039 * last SG element, then no more SG queues need
7040 * to be written.
7041 */
7042 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
7043 break;
7044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007046 next_qp = AscReadLramByte(iop_base,
7047 (ushort)(q_addr +
7048 ASC_SCSIQ_B_FWD));
7049 q_addr = ASC_QNO_TO_QADDR(next_qp);
7050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007051
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007052 /*
7053 * Clear the halt condition so the RISC will be restarted
7054 * after the return.
7055 */
7056 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7057 return (0);
7058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007060 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007061}
7062
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007063static uchar
7064_AscCopyLramScsiDoneQ(PortAddr iop_base,
7065 ushort q_addr,
7066 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007067{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007068 ushort _val;
7069 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007071 DvcGetQinfo(iop_base,
7072 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
7073 (uchar *)scsiq,
7074 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007076 _val = AscReadLramWord(iop_base,
7077 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
7078 scsiq->q_status = (uchar)_val;
7079 scsiq->q_no = (uchar)(_val >> 8);
7080 _val = AscReadLramWord(iop_base,
7081 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
7082 scsiq->cntl = (uchar)_val;
7083 sg_queue_cnt = (uchar)(_val >> 8);
7084 _val = AscReadLramWord(iop_base,
7085 (ushort)(q_addr +
7086 (ushort)ASC_SCSIQ_B_SENSE_LEN));
7087 scsiq->sense_len = (uchar)_val;
7088 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007089
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007090 /*
7091 * Read high word of remain bytes from alternate location.
7092 */
7093 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
7094 (ushort)(q_addr +
7095 (ushort)
7096 ASC_SCSIQ_W_ALT_DC1)))
7097 << 16);
7098 /*
7099 * Read low word of remain bytes from original location.
7100 */
7101 scsiq->remain_bytes += AscReadLramWord(iop_base,
7102 (ushort)(q_addr + (ushort)
7103 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007105 scsiq->remain_bytes &= max_dma_count;
7106 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007107}
7108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007109static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007110{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007111 uchar next_qp;
7112 uchar n_q_used;
7113 uchar sg_list_qp;
7114 uchar sg_queue_cnt;
7115 uchar q_cnt;
7116 uchar done_q_tail;
7117 uchar tid_no;
7118 ASC_SCSI_BIT_ID_TYPE scsi_busy;
7119 ASC_SCSI_BIT_ID_TYPE target_id;
7120 PortAddr iop_base;
7121 ushort q_addr;
7122 ushort sg_q_addr;
7123 uchar cur_target_qng;
7124 ASC_QDONE_INFO scsiq_buf;
7125 ASC_QDONE_INFO *scsiq;
7126 int false_overrun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007127
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007128 iop_base = asc_dvc->iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007129 n_q_used = 1;
7130 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
7131 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
7132 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
7133 next_qp = AscReadLramByte(iop_base,
7134 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
7135 if (next_qp != ASC_QLINK_END) {
7136 AscPutVarDoneQTail(iop_base, next_qp);
7137 q_addr = ASC_QNO_TO_QADDR(next_qp);
7138 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
7139 asc_dvc->max_dma_count);
7140 AscWriteLramByte(iop_base,
7141 (ushort)(q_addr +
7142 (ushort)ASC_SCSIQ_B_STATUS),
7143 (uchar)(scsiq->
7144 q_status & (uchar)~(QS_READY |
7145 QS_ABORTED)));
7146 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
7147 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
7148 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
7149 sg_q_addr = q_addr;
7150 sg_list_qp = next_qp;
7151 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
7152 sg_list_qp = AscReadLramByte(iop_base,
7153 (ushort)(sg_q_addr
7154 + (ushort)
7155 ASC_SCSIQ_B_FWD));
7156 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
7157 if (sg_list_qp == ASC_QLINK_END) {
7158 AscSetLibErrorCode(asc_dvc,
7159 ASCQ_ERR_SG_Q_LINKS);
7160 scsiq->d3.done_stat = QD_WITH_ERROR;
7161 scsiq->d3.host_stat =
7162 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
7163 goto FATAL_ERR_QDONE;
7164 }
7165 AscWriteLramByte(iop_base,
7166 (ushort)(sg_q_addr + (ushort)
7167 ASC_SCSIQ_B_STATUS),
7168 QS_FREE);
7169 }
7170 n_q_used = sg_queue_cnt + 1;
7171 AscPutVarDoneQTail(iop_base, sg_list_qp);
7172 }
7173 if (asc_dvc->queue_full_or_busy & target_id) {
7174 cur_target_qng = AscReadLramByte(iop_base,
7175 (ushort)((ushort)
7176 ASC_QADR_BEG
7177 + (ushort)
7178 scsiq->d2.
7179 target_ix));
7180 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
7181 scsi_busy = AscReadLramByte(iop_base, (ushort)
7182 ASCV_SCSIBUSY_B);
7183 scsi_busy &= ~target_id;
7184 AscWriteLramByte(iop_base,
7185 (ushort)ASCV_SCSIBUSY_B,
7186 scsi_busy);
7187 asc_dvc->queue_full_or_busy &= ~target_id;
7188 }
7189 }
7190 if (asc_dvc->cur_total_qng >= n_q_used) {
7191 asc_dvc->cur_total_qng -= n_q_used;
7192 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
7193 asc_dvc->cur_dvc_qng[tid_no]--;
7194 }
7195 } else {
7196 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
7197 scsiq->d3.done_stat = QD_WITH_ERROR;
7198 goto FATAL_ERR_QDONE;
7199 }
7200 if ((scsiq->d2.srb_ptr == 0UL) ||
7201 ((scsiq->q_status & QS_ABORTED) != 0)) {
7202 return (0x11);
7203 } else if (scsiq->q_status == QS_DONE) {
7204 false_overrun = FALSE;
7205 if (scsiq->extra_bytes != 0) {
7206 scsiq->remain_bytes +=
7207 (ADV_DCNT)scsiq->extra_bytes;
7208 }
7209 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
7210 if (scsiq->d3.host_stat ==
7211 QHSTA_M_DATA_OVER_RUN) {
7212 if ((scsiq->
7213 cntl & (QC_DATA_IN | QC_DATA_OUT))
7214 == 0) {
7215 scsiq->d3.done_stat =
7216 QD_NO_ERROR;
7217 scsiq->d3.host_stat =
7218 QHSTA_NO_ERROR;
7219 } else if (false_overrun) {
7220 scsiq->d3.done_stat =
7221 QD_NO_ERROR;
7222 scsiq->d3.host_stat =
7223 QHSTA_NO_ERROR;
7224 }
7225 } else if (scsiq->d3.host_stat ==
7226 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
7227 AscStopChip(iop_base);
7228 AscSetChipControl(iop_base,
7229 (uchar)(CC_SCSI_RESET
7230 | CC_HALT));
7231 DvcDelayNanoSecond(asc_dvc, 60000);
7232 AscSetChipControl(iop_base, CC_HALT);
7233 AscSetChipStatus(iop_base,
7234 CIW_CLR_SCSI_RESET_INT);
7235 AscSetChipStatus(iop_base, 0);
7236 AscSetChipControl(iop_base, 0);
7237 }
7238 }
7239 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007240 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007241 } else {
7242 if ((AscReadLramByte(iop_base,
7243 (ushort)(q_addr + (ushort)
7244 ASC_SCSIQ_CDB_BEG))
7245 == START_STOP)) {
7246 asc_dvc->unit_not_ready &= ~target_id;
7247 if (scsiq->d3.done_stat != QD_NO_ERROR) {
7248 asc_dvc->start_motor &=
7249 ~target_id;
7250 }
7251 }
7252 }
7253 return (1);
7254 } else {
7255 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
7256 FATAL_ERR_QDONE:
7257 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007258 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007259 }
7260 return (0x80);
7261 }
7262 }
7263 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264}
7265
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007266static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007267{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007268 ASC_CS_TYPE chipstat;
7269 PortAddr iop_base;
7270 ushort saved_ram_addr;
7271 uchar ctrl_reg;
7272 uchar saved_ctrl_reg;
7273 int int_pending;
7274 int status;
7275 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007277 iop_base = asc_dvc->iop_base;
7278 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007280 if (AscIsIntPending(iop_base) == 0) {
7281 return int_pending;
7282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007283
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007284 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007285 return (ERR);
7286 }
7287 if (asc_dvc->in_critical_cnt != 0) {
7288 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
7289 return (ERR);
7290 }
7291 if (asc_dvc->is_in_int) {
7292 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
7293 return (ERR);
7294 }
7295 asc_dvc->is_in_int = TRUE;
7296 ctrl_reg = AscGetChipControl(iop_base);
7297 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
7298 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
7299 chipstat = AscGetChipStatus(iop_base);
7300 if (chipstat & CSW_SCSI_RESET_LATCH) {
7301 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
7302 int i = 10;
7303 int_pending = TRUE;
7304 asc_dvc->sdtr_done = 0;
7305 saved_ctrl_reg &= (uchar)(~CC_HALT);
7306 while ((AscGetChipStatus(iop_base) &
7307 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
7308 DvcSleepMilliSecond(100);
7309 }
7310 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
7311 AscSetChipControl(iop_base, CC_HALT);
7312 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
7313 AscSetChipStatus(iop_base, 0);
7314 chipstat = AscGetChipStatus(iop_base);
7315 }
7316 }
7317 saved_ram_addr = AscGetChipLramAddr(iop_base);
7318 host_flag = AscReadLramByte(iop_base,
7319 ASCV_HOST_FLAG_B) &
7320 (uchar)(~ASC_HOST_FLAG_IN_ISR);
7321 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7322 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
7323 if ((chipstat & CSW_INT_PENDING)
7324 || (int_pending)
7325 ) {
7326 AscAckInterrupt(iop_base);
7327 int_pending = TRUE;
7328 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
7329 if (AscIsrChipHalted(asc_dvc) == ERR) {
7330 goto ISR_REPORT_QDONE_FATAL_ERROR;
7331 } else {
7332 saved_ctrl_reg &= (uchar)(~CC_HALT);
7333 }
7334 } else {
7335 ISR_REPORT_QDONE_FATAL_ERROR:
7336 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
7337 while (((status =
7338 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
7339 }
7340 } else {
7341 do {
7342 if ((status =
7343 AscIsrQDone(asc_dvc)) == 1) {
7344 break;
7345 }
7346 } while (status == 0x11);
7347 }
7348 if ((status & 0x80) != 0)
7349 int_pending = ERR;
7350 }
7351 }
7352 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7353 AscSetChipLramAddr(iop_base, saved_ram_addr);
7354 AscSetChipControl(iop_base, saved_ctrl_reg);
7355 asc_dvc->is_in_int = FALSE;
7356 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007357}
7358
7359/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007360static uchar _asc_mcode_buf[] = {
7361 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007362 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
7367 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7368 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007369 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007370 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
7371 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
7372 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007373 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007374 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
7375 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
7376 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007377 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007378 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
7379 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
7380 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007381 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007382 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
7383 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
7384 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007385 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007386 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
7387 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
7388 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007389 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007390 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
7391 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
7392 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007393 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007394 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
7395 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
7396 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007397 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007398 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
7399 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
7400 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007401 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007402 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
7403 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
7404 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007405 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007406 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
7407 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
7408 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007409 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007410 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
7411 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
7412 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007413 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007414 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
7415 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
7416 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007417 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007418 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
7419 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
7420 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007421 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007422 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
7423 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
7424 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007425 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007426 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
7427 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
7428 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007429 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007430 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
7431 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
7432 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007433 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007434 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
7435 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
7436 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007437 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007438 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
7439 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
7440 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007441 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007442 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
7443 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
7444 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007445 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007446 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
7447 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
7448 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007449 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007450 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
7451 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
7452 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007453 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007454 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
7455 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
7456 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007457 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007458 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
7459 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
7460 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007461 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007462 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
7463 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
7464 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007465 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007466 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
7467 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
7468 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007469 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007470 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
7471 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
7472 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007473 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007474 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
7475 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
7476 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007477 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007478 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
7479 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
7480 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007481 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007482 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
7483 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
7484 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007485 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007486 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
7487 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
7488 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007489 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007490 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
7491 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
7492 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007493 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007494 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
7495 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
7496 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007497 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007498 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
7499 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
7500 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007501 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007502 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
7503 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
7504 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007505 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007506 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
7507 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
7508 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007509 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007510 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
7511 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
7512 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007513 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007514 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
7515 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
7516 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007517 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007518 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
7519 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
7520 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007521 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007522 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
7523 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
7524 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007525 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007526 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
7527 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
7528 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007529 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007530 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
7531 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
7532 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007533 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007534 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
7535 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
7536 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007537 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007538 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
7539 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
7540 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007541 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007542 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
7543 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
7544 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007545 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007546 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
7547 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
7548 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007549 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007550 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
7551 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
7552 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007553};
7554
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007555static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
7556static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007557
7558#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007559static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
7560 INQUIRY,
7561 REQUEST_SENSE,
7562 READ_CAPACITY,
7563 READ_TOC,
7564 MODE_SELECT,
7565 MODE_SENSE,
7566 MODE_SELECT_10,
7567 MODE_SENSE_10,
7568 0xFF,
7569 0xFF,
7570 0xFF,
7571 0xFF,
7572 0xFF,
7573 0xFF,
7574 0xFF,
7575 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07007576};
7577
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007578static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007579{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007580 PortAddr iop_base;
7581 ulong last_int_level;
7582 int sta;
7583 int n_q_required;
7584 int disable_syn_offset_one_fix;
7585 int i;
7586 ASC_PADDR addr;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007587 ushort sg_entry_cnt = 0;
7588 ushort sg_entry_cnt_minus_one = 0;
7589 uchar target_ix;
7590 uchar tid_no;
7591 uchar sdtr_data;
7592 uchar extra_bytes;
7593 uchar scsi_cmd;
7594 uchar disable_cmd;
7595 ASC_SG_HEAD *sg_head;
7596 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007598 iop_base = asc_dvc->iop_base;
7599 sg_head = scsiq->sg_head;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007600 if (asc_dvc->err_code != 0)
7601 return (ERR);
7602 if (scsiq == (ASC_SCSI_Q *)0L) {
7603 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
7604 return (ERR);
7605 }
7606 scsiq->q1.q_no = 0;
7607 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
7608 scsiq->q1.extra_bytes = 0;
7609 }
7610 sta = 0;
7611 target_ix = scsiq->q2.target_ix;
7612 tid_no = ASC_TIX_TO_TID(target_ix);
7613 n_q_required = 1;
7614 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
7615 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
7616 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
7617 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7618 AscMsgOutSDTR(asc_dvc,
7619 asc_dvc->
7620 sdtr_period_tbl[(sdtr_data >> 4) &
7621 (uchar)(asc_dvc->
7622 max_sdtr_index -
7623 1)],
7624 (uchar)(sdtr_data & (uchar)
7625 ASC_SYN_MAX_OFFSET));
7626 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
7627 }
7628 }
7629 last_int_level = DvcEnterCritical();
7630 if (asc_dvc->in_critical_cnt != 0) {
7631 DvcLeaveCritical(last_int_level);
7632 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
7633 return (ERR);
7634 }
7635 asc_dvc->in_critical_cnt++;
7636 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7637 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
7638 asc_dvc->in_critical_cnt--;
7639 DvcLeaveCritical(last_int_level);
7640 return (ERR);
7641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007642#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007643 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7644 asc_dvc->in_critical_cnt--;
7645 DvcLeaveCritical(last_int_level);
7646 return (ERR);
7647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007648#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007649 if (sg_entry_cnt == 1) {
7650 scsiq->q1.data_addr =
7651 (ADV_PADDR)sg_head->sg_list[0].addr;
7652 scsiq->q1.data_cnt =
7653 (ADV_DCNT)sg_head->sg_list[0].bytes;
7654 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
7655 }
7656 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
7657 }
7658 scsi_cmd = scsiq->cdbptr[0];
7659 disable_syn_offset_one_fix = FALSE;
7660 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
7661 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
7662 if (scsiq->q1.cntl & QC_SG_HEAD) {
7663 data_cnt = 0;
7664 for (i = 0; i < sg_entry_cnt; i++) {
7665 data_cnt +=
7666 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
7667 bytes);
7668 }
7669 } else {
7670 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
7671 }
7672 if (data_cnt != 0UL) {
7673 if (data_cnt < 512UL) {
7674 disable_syn_offset_one_fix = TRUE;
7675 } else {
7676 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
7677 i++) {
7678 disable_cmd =
7679 _syn_offset_one_disable_cmd[i];
7680 if (disable_cmd == 0xFF) {
7681 break;
7682 }
7683 if (scsi_cmd == disable_cmd) {
7684 disable_syn_offset_one_fix =
7685 TRUE;
7686 break;
7687 }
7688 }
7689 }
7690 }
7691 }
7692 if (disable_syn_offset_one_fix) {
7693 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7694 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
7695 ASC_TAG_FLAG_DISABLE_DISCONNECT);
7696 } else {
7697 scsiq->q2.tag_code &= 0x27;
7698 }
7699 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7700 if (asc_dvc->bug_fix_cntl) {
7701 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7702 if ((scsi_cmd == READ_6) ||
7703 (scsi_cmd == READ_10)) {
7704 addr =
7705 (ADV_PADDR)le32_to_cpu(sg_head->
7706 sg_list
7707 [sg_entry_cnt_minus_one].
7708 addr) +
7709 (ADV_DCNT)le32_to_cpu(sg_head->
7710 sg_list
7711 [sg_entry_cnt_minus_one].
7712 bytes);
7713 extra_bytes =
7714 (uchar)((ushort)addr & 0x0003);
7715 if ((extra_bytes != 0)
7716 &&
7717 ((scsiq->q2.
7718 tag_code &
7719 ASC_TAG_FLAG_EXTRA_BYTES)
7720 == 0)) {
7721 scsiq->q2.tag_code |=
7722 ASC_TAG_FLAG_EXTRA_BYTES;
7723 scsiq->q1.extra_bytes =
7724 extra_bytes;
7725 data_cnt =
7726 le32_to_cpu(sg_head->
7727 sg_list
7728 [sg_entry_cnt_minus_one].
7729 bytes);
7730 data_cnt -=
7731 (ASC_DCNT) extra_bytes;
7732 sg_head->
7733 sg_list
7734 [sg_entry_cnt_minus_one].
7735 bytes =
7736 cpu_to_le32(data_cnt);
7737 }
7738 }
7739 }
7740 }
7741 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007742#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007743 /*
7744 * Set the sg_entry_cnt to the maximum possible. The rest of
7745 * the SG elements will be copied when the RISC completes the
7746 * SG elements that fit and halts.
7747 */
7748 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7749 sg_entry_cnt = ASC_MAX_SG_LIST;
7750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007751#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007752 n_q_required = AscSgListToQueue(sg_entry_cnt);
7753 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
7754 (uint) n_q_required)
7755 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7756 if ((sta =
7757 AscSendScsiQueue(asc_dvc, scsiq,
7758 n_q_required)) == 1) {
7759 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007760 DvcLeaveCritical(last_int_level);
7761 return (sta);
7762 }
7763 }
7764 } else {
7765 if (asc_dvc->bug_fix_cntl) {
7766 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7767 if ((scsi_cmd == READ_6) ||
7768 (scsi_cmd == READ_10)) {
7769 addr =
7770 le32_to_cpu(scsiq->q1.data_addr) +
7771 le32_to_cpu(scsiq->q1.data_cnt);
7772 extra_bytes =
7773 (uchar)((ushort)addr & 0x0003);
7774 if ((extra_bytes != 0)
7775 &&
7776 ((scsiq->q2.
7777 tag_code &
7778 ASC_TAG_FLAG_EXTRA_BYTES)
7779 == 0)) {
7780 data_cnt =
7781 le32_to_cpu(scsiq->q1.
7782 data_cnt);
7783 if (((ushort)data_cnt & 0x01FF)
7784 == 0) {
7785 scsiq->q2.tag_code |=
7786 ASC_TAG_FLAG_EXTRA_BYTES;
7787 data_cnt -= (ASC_DCNT)
7788 extra_bytes;
7789 scsiq->q1.data_cnt =
7790 cpu_to_le32
7791 (data_cnt);
7792 scsiq->q1.extra_bytes =
7793 extra_bytes;
7794 }
7795 }
7796 }
7797 }
7798 }
7799 n_q_required = 1;
7800 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
7801 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7802 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
7803 n_q_required)) == 1) {
7804 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007805 DvcLeaveCritical(last_int_level);
7806 return (sta);
7807 }
7808 }
7809 }
7810 asc_dvc->in_critical_cnt--;
7811 DvcLeaveCritical(last_int_level);
7812 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007813}
7814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007815static int
7816AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007817{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007818 PortAddr iop_base;
7819 uchar free_q_head;
7820 uchar next_qp;
7821 uchar tid_no;
7822 uchar target_ix;
7823 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007824
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007825 iop_base = asc_dvc->iop_base;
7826 target_ix = scsiq->q2.target_ix;
7827 tid_no = ASC_TIX_TO_TID(target_ix);
7828 sta = 0;
7829 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
7830 if (n_q_required > 1) {
7831 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
7832 free_q_head, (uchar)
7833 (n_q_required)))
7834 != (uchar)ASC_QLINK_END) {
7835 asc_dvc->last_q_shortage = 0;
7836 scsiq->sg_head->queue_cnt = n_q_required - 1;
7837 scsiq->q1.q_no = free_q_head;
7838 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
7839 free_q_head)) == 1) {
7840 AscPutVarFreeQHead(iop_base, next_qp);
7841 asc_dvc->cur_total_qng += (uchar)(n_q_required);
7842 asc_dvc->cur_dvc_qng[tid_no]++;
7843 }
7844 return (sta);
7845 }
7846 } else if (n_q_required == 1) {
7847 if ((next_qp = AscAllocFreeQueue(iop_base,
7848 free_q_head)) !=
7849 ASC_QLINK_END) {
7850 scsiq->q1.q_no = free_q_head;
7851 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
7852 free_q_head)) == 1) {
7853 AscPutVarFreeQHead(iop_base, next_qp);
7854 asc_dvc->cur_total_qng++;
7855 asc_dvc->cur_dvc_qng[tid_no]++;
7856 }
7857 return (sta);
7858 }
7859 }
7860 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007861}
7862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007863static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007864{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007865 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007866
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007867 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
7868 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
7869 n_sg_list_qs++;
7870 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007871}
7872
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007873static uint
7874AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007875{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007876 uint cur_used_qs;
7877 uint cur_free_qs;
7878 ASC_SCSI_BIT_ID_TYPE target_id;
7879 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007881 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
7882 tid_no = ASC_TIX_TO_TID(target_ix);
7883 if ((asc_dvc->unit_not_ready & target_id) ||
7884 (asc_dvc->queue_full_or_busy & target_id)) {
7885 return (0);
7886 }
7887 if (n_qs == 1) {
7888 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7889 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
7890 } else {
7891 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7892 (uint) ASC_MIN_FREE_Q;
7893 }
7894 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
7895 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
7896 if (asc_dvc->cur_dvc_qng[tid_no] >=
7897 asc_dvc->max_dvc_qng[tid_no]) {
7898 return (0);
7899 }
7900 return (cur_free_qs);
7901 }
7902 if (n_qs > 1) {
7903 if ((n_qs > asc_dvc->last_q_shortage)
7904 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
7905 asc_dvc->last_q_shortage = n_qs;
7906 }
7907 }
7908 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007909}
7910
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007911static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007912{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007913 ushort q_addr;
7914 uchar tid_no;
7915 uchar sdtr_data;
7916 uchar syn_period_ix;
7917 uchar syn_offset;
7918 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007920 iop_base = asc_dvc->iop_base;
7921 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
7922 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
7923 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
7924 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7925 syn_period_ix =
7926 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
7927 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
7928 AscMsgOutSDTR(asc_dvc,
7929 asc_dvc->sdtr_period_tbl[syn_period_ix],
7930 syn_offset);
7931 scsiq->q1.cntl |= QC_MSG_OUT;
7932 }
7933 q_addr = ASC_QNO_TO_QADDR(q_no);
7934 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
7935 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7936 }
7937 scsiq->q1.status = QS_FREE;
7938 AscMemWordCopyPtrToLram(iop_base,
7939 q_addr + ASC_SCSIQ_CDB_BEG,
7940 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007942 DvcPutScsiQ(iop_base,
7943 q_addr + ASC_SCSIQ_CPY_BEG,
7944 (uchar *)&scsiq->q1.cntl,
7945 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
7946 AscWriteLramWord(iop_base,
7947 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
7948 (ushort)(((ushort)scsiq->q1.
7949 q_no << 8) | (ushort)QS_READY));
7950 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007951}
7952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007953static int
7954AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007955{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007956 int sta;
7957 int i;
7958 ASC_SG_HEAD *sg_head;
7959 ASC_SG_LIST_Q scsi_sg_q;
7960 ASC_DCNT saved_data_addr;
7961 ASC_DCNT saved_data_cnt;
7962 PortAddr iop_base;
7963 ushort sg_list_dwords;
7964 ushort sg_index;
7965 ushort sg_entry_cnt;
7966 ushort q_addr;
7967 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007969 iop_base = asc_dvc->iop_base;
7970 sg_head = scsiq->sg_head;
7971 saved_data_addr = scsiq->q1.data_addr;
7972 saved_data_cnt = scsiq->q1.data_cnt;
7973 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
7974 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007975#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007976 /*
7977 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
7978 * then not all SG elements will fit in the allocated queues.
7979 * The rest of the SG elements will be copied when the RISC
7980 * completes the SG elements that fit and halts.
7981 */
7982 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
7983 /*
7984 * Set sg_entry_cnt to be the number of SG elements that
7985 * will fit in the allocated SG queues. It is minus 1, because
7986 * the first SG element is handled above. ASC_MAX_SG_LIST is
7987 * already inflated by 1 to account for this. For example it
7988 * may be 50 which is 1 + 7 queues * 7 SG elements.
7989 */
7990 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007992 /*
7993 * Keep track of remaining number of SG elements that will
7994 * need to be handled from a_isr.c.
7995 */
7996 scsiq->remain_sg_entry_cnt =
7997 sg_head->entry_cnt - ASC_MAX_SG_LIST;
7998 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007999#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008000 /*
8001 * Set sg_entry_cnt to be the number of SG elements that
8002 * will fit in the allocated SG queues. It is minus 1, because
8003 * the first SG element is handled above.
8004 */
8005 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008006#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008008#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008009 if (sg_entry_cnt != 0) {
8010 scsiq->q1.cntl |= QC_SG_HEAD;
8011 q_addr = ASC_QNO_TO_QADDR(q_no);
8012 sg_index = 1;
8013 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
8014 scsi_sg_q.sg_head_qp = q_no;
8015 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
8016 for (i = 0; i < sg_head->queue_cnt; i++) {
8017 scsi_sg_q.seq_no = i + 1;
8018 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
8019 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
8020 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8021 if (i == 0) {
8022 scsi_sg_q.sg_list_cnt =
8023 ASC_SG_LIST_PER_Q;
8024 scsi_sg_q.sg_cur_list_cnt =
8025 ASC_SG_LIST_PER_Q;
8026 } else {
8027 scsi_sg_q.sg_list_cnt =
8028 ASC_SG_LIST_PER_Q - 1;
8029 scsi_sg_q.sg_cur_list_cnt =
8030 ASC_SG_LIST_PER_Q - 1;
8031 }
8032 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008033#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008034 /*
8035 * This is the last SG queue in the list of
8036 * allocated SG queues. If there are more
8037 * SG elements than will fit in the allocated
8038 * queues, then set the QCSG_SG_XFER_MORE flag.
8039 */
8040 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
8041 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8042 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008043#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008044 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008045#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008047#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008048 sg_list_dwords = sg_entry_cnt << 1;
8049 if (i == 0) {
8050 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
8051 scsi_sg_q.sg_cur_list_cnt =
8052 sg_entry_cnt;
8053 } else {
8054 scsi_sg_q.sg_list_cnt =
8055 sg_entry_cnt - 1;
8056 scsi_sg_q.sg_cur_list_cnt =
8057 sg_entry_cnt - 1;
8058 }
8059 sg_entry_cnt = 0;
8060 }
8061 next_qp = AscReadLramByte(iop_base,
8062 (ushort)(q_addr +
8063 ASC_SCSIQ_B_FWD));
8064 scsi_sg_q.q_no = next_qp;
8065 q_addr = ASC_QNO_TO_QADDR(next_qp);
8066 AscMemWordCopyPtrToLram(iop_base,
8067 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8068 (uchar *)&scsi_sg_q,
8069 sizeof(ASC_SG_LIST_Q) >> 1);
8070 AscMemDWordCopyPtrToLram(iop_base,
8071 q_addr + ASC_SGQ_LIST_BEG,
8072 (uchar *)&sg_head->
8073 sg_list[sg_index],
8074 sg_list_dwords);
8075 sg_index += ASC_SG_LIST_PER_Q;
8076 scsiq->next_sg_index = sg_index;
8077 }
8078 } else {
8079 scsiq->q1.cntl &= ~QC_SG_HEAD;
8080 }
8081 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
8082 scsiq->q1.data_addr = saved_data_addr;
8083 scsiq->q1.data_cnt = saved_data_cnt;
8084 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008085}
8086
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008087static int
8088AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008089{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008090 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008091
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008092 if (AscHostReqRiscHalt(iop_base)) {
8093 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8094 AscStartChip(iop_base);
8095 return (sta);
8096 }
8097 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008098}
8099
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008100static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008101{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008102 ASC_SCSI_BIT_ID_TYPE org_id;
8103 int i;
8104 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008106 AscSetBank(iop_base, 1);
8107 org_id = AscReadChipDvcID(iop_base);
8108 for (i = 0; i <= ASC_MAX_TID; i++) {
8109 if (org_id == (0x01 << i))
8110 break;
8111 }
8112 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8113 AscWriteChipDvcID(iop_base, id);
8114 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8115 AscSetBank(iop_base, 0);
8116 AscSetChipSyn(iop_base, sdtr_data);
8117 if (AscGetChipSyn(iop_base) != sdtr_data) {
8118 sta = FALSE;
8119 }
8120 } else {
8121 sta = FALSE;
8122 }
8123 AscSetBank(iop_base, 1);
8124 AscWriteChipDvcID(iop_base, org_id);
8125 AscSetBank(iop_base, 0);
8126 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008127}
8128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008129static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008130{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008131 uchar i;
8132 ushort s_addr;
8133 PortAddr iop_base;
8134 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008135
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008136 iop_base = asc_dvc->iop_base;
8137 warn_code = 0;
8138 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
8139 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
8140 64) >> 1)
8141 );
8142 i = ASC_MIN_ACTIVE_QNO;
8143 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
8144 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8145 (uchar)(i + 1));
8146 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8147 (uchar)(asc_dvc->max_total_qng));
8148 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8149 (uchar)i);
8150 i++;
8151 s_addr += ASC_QBLK_SIZE;
8152 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
8153 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8154 (uchar)(i + 1));
8155 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8156 (uchar)(i - 1));
8157 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8158 (uchar)i);
8159 }
8160 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8161 (uchar)ASC_QLINK_END);
8162 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8163 (uchar)(asc_dvc->max_total_qng - 1));
8164 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8165 (uchar)asc_dvc->max_total_qng);
8166 i++;
8167 s_addr += ASC_QBLK_SIZE;
8168 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
8169 i++, s_addr += ASC_QBLK_SIZE) {
8170 AscWriteLramByte(iop_base,
8171 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
8172 AscWriteLramByte(iop_base,
8173 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
8174 AscWriteLramByte(iop_base,
8175 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
8176 }
8177 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008178}
8179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008180static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008181{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008182 PortAddr iop_base;
8183 int i;
8184 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008185
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008186 iop_base = asc_dvc->iop_base;
8187 AscPutRiscVarFreeQHead(iop_base, 1);
8188 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8189 AscPutVarFreeQHead(iop_base, 1);
8190 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8191 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
8192 (uchar)((int)asc_dvc->max_total_qng + 1));
8193 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
8194 (uchar)((int)asc_dvc->max_total_qng + 2));
8195 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
8196 asc_dvc->max_total_qng);
8197 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
8198 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8199 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
8200 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
8201 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
8202 AscPutQDoneInProgress(iop_base, 0);
8203 lram_addr = ASC_QADR_BEG;
8204 for (i = 0; i < 32; i++, lram_addr += 2) {
8205 AscWriteLramWord(iop_base, lram_addr, 0);
8206 }
8207 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008208}
8209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008210static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008211{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008212 if (asc_dvc->err_code == 0) {
8213 asc_dvc->err_code = err_code;
8214 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8215 err_code);
8216 }
8217 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008218}
8219
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008220static uchar
8221AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008222{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008223 EXT_MSG sdtr_buf;
8224 uchar sdtr_period_index;
8225 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008226
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008227 iop_base = asc_dvc->iop_base;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008228 sdtr_buf.msg_type = EXTENDED_MESSAGE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008229 sdtr_buf.msg_len = MS_SDTR_LEN;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008230 sdtr_buf.msg_req = EXTENDED_SDTR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008231 sdtr_buf.xfer_period = sdtr_period;
8232 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8233 sdtr_buf.req_ack_offset = sdtr_offset;
8234 if ((sdtr_period_index =
8235 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
8236 asc_dvc->max_sdtr_index) {
8237 AscMemWordCopyPtrToLram(iop_base,
8238 ASCV_MSGOUT_BEG,
8239 (uchar *)&sdtr_buf,
8240 sizeof(EXT_MSG) >> 1);
8241 return ((sdtr_period_index << 4) | sdtr_offset);
8242 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008243
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008244 sdtr_buf.req_ack_offset = 0;
8245 AscMemWordCopyPtrToLram(iop_base,
8246 ASCV_MSGOUT_BEG,
8247 (uchar *)&sdtr_buf,
8248 sizeof(EXT_MSG) >> 1);
8249 return (0);
8250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008251}
8252
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008253static uchar
8254AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008255{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008256 uchar byte;
8257 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008259 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8260 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
8261 ) {
8262 return (0xFF);
8263 }
8264 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8265 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008266}
8267
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008268static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008269{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008270 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8271 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8272 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008273}
8274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008275static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008276{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008277 uchar *period_table;
8278 int max_index;
8279 int min_index;
8280 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008282 period_table = asc_dvc->sdtr_period_tbl;
8283 max_index = (int)asc_dvc->max_sdtr_index;
8284 min_index = (int)asc_dvc->host_init_sdtr_index;
8285 if ((syn_time <= period_table[max_index])) {
8286 for (i = min_index; i < (max_index - 1); i++) {
8287 if (syn_time <= period_table[i]) {
8288 return ((uchar)i);
8289 }
8290 }
8291 return ((uchar)max_index);
8292 } else {
8293 return ((uchar)(max_index + 1));
8294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008295}
8296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008297static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008298{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008299 ushort q_addr;
8300 uchar next_qp;
8301 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008303 q_addr = ASC_QNO_TO_QADDR(free_q_head);
8304 q_status = (uchar)AscReadLramByte(iop_base,
8305 (ushort)(q_addr +
8306 ASC_SCSIQ_B_STATUS));
8307 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
8308 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
8309 return (next_qp);
8310 }
8311 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008312}
8313
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008314static uchar
8315AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008316{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008317 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008318
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008319 for (i = 0; i < n_free_q; i++) {
8320 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
8321 == ASC_QLINK_END) {
8322 return (ASC_QLINK_END);
8323 }
8324 }
8325 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008326}
8327
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008328static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008329{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008330 int count = 0;
8331 int sta = 0;
8332 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008333
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008334 if (AscIsChipHalted(iop_base))
8335 return (1);
8336 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
8337 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8338 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
8339 do {
8340 if (AscIsChipHalted(iop_base)) {
8341 sta = 1;
8342 break;
8343 }
8344 DvcSleepMilliSecond(100);
8345 } while (count++ < 20);
8346 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
8347 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008348}
8349
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008350static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008351{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008352 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008353
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008354 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
8355 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8356 ASC_STOP_REQ_RISC_STOP);
8357 do {
8358 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
8359 ASC_STOP_ACK_RISC_STOP) {
8360 return (1);
8361 }
8362 DvcSleepMilliSecond(100);
8363 } while (count++ < 20);
8364 }
8365 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008366}
8367
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008368static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008369{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008370 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008371}
8372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008373static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008374{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008375 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008376}
8377
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008378static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008379{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008380 AscSetChipControl(iop_base, 0);
8381 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8382 return (0);
8383 }
8384 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008385}
8386
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008387static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008388{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008389 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008390
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008391 cc_val =
8392 AscGetChipControl(iop_base) &
8393 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
8394 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
8395 AscSetChipIH(iop_base, INS_HALT);
8396 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8397 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
8398 return (0);
8399 }
8400 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008401}
8402
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008403static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008404{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008405 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8406 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
8407 return (1);
8408 }
8409 }
8410 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008411}
8412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008413static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008414{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008415 AscSetBank(iop_base, 1);
8416 AscWriteChipIH(iop_base, ins_code);
8417 AscSetBank(iop_base, 0);
8418 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008419}
8420
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008421static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008422{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008423 uchar host_flag;
8424 uchar risc_flag;
8425 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008427 loop = 0;
8428 do {
8429 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8430 if (loop++ > 0x7FFF) {
8431 break;
8432 }
8433 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8434 host_flag =
8435 AscReadLramByte(iop_base,
8436 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8437 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8438 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8439 AscSetChipStatus(iop_base, CIW_INT_ACK);
8440 loop = 0;
8441 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8442 AscSetChipStatus(iop_base, CIW_INT_ACK);
8443 if (loop++ > 3) {
8444 break;
8445 }
8446 }
8447 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8448 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008449}
8450
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008451static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008452{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008453 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008454
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008455 cfg = AscGetChipCfgLsw(iop_base);
8456 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
8457 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008458}
8459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008460static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008461{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008462 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008463
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008464 cfg = AscGetChipCfgLsw(iop_base);
8465 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
8466 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008467}
8468
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008469static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008470{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008471 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008472
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008473 val = AscGetChipControl(iop_base) &
8474 (~
8475 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
8476 CC_CHIP_RESET));
8477 if (bank == 1) {
8478 val |= CC_BANK_ONE;
8479 } else if (bank == 2) {
8480 val |= CC_DIAG | CC_BANK_ONE;
8481 } else {
8482 val &= ~CC_BANK_ONE;
8483 }
8484 AscSetChipControl(iop_base, val);
8485 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008486}
8487
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008488static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008489{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008490 PortAddr iop_base;
8491 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008492
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008493 iop_base = asc_dvc->iop_base;
8494 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
8495 && (i-- > 0)) {
8496 DvcSleepMilliSecond(100);
8497 }
8498 AscStopChip(iop_base);
8499 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
8500 DvcDelayNanoSecond(asc_dvc, 60000);
8501 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8502 AscSetChipIH(iop_base, INS_HALT);
8503 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
8504 AscSetChipControl(iop_base, CC_HALT);
8505 DvcSleepMilliSecond(200);
8506 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
8507 AscSetChipStatus(iop_base, 0);
8508 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008509}
8510
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008511static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008512{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008513 if (bus_type & ASC_IS_ISA)
8514 return (ASC_MAX_ISA_DMA_COUNT);
8515 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
8516 return (ASC_MAX_VL_DMA_COUNT);
8517 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008518}
8519
8520#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008521static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008522{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008523 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008524
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008525 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
8526 if (channel == 0x03)
8527 return (0);
8528 else if (channel == 0x00)
8529 return (7);
8530 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008531}
8532
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008533static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008534{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008535 ushort cfg_lsw;
8536 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008537
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008538 if ((dma_channel >= 5) && (dma_channel <= 7)) {
8539 if (dma_channel == 7)
8540 value = 0x00;
8541 else
8542 value = dma_channel - 4;
8543 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
8544 cfg_lsw |= value;
8545 AscSetChipCfgLsw(iop_base, cfg_lsw);
8546 return (AscGetIsaDmaChannel(iop_base));
8547 }
8548 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008549}
8550
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008551static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008552{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008553 speed_value &= 0x07;
8554 AscSetBank(iop_base, 1);
8555 AscWriteChipDmaSpeed(iop_base, speed_value);
8556 AscSetBank(iop_base, 0);
8557 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008558}
8559
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008560static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008561{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008562 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008563
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008564 AscSetBank(iop_base, 1);
8565 speed_value = AscReadChipDmaSpeed(iop_base);
8566 speed_value &= 0x07;
8567 AscSetBank(iop_base, 0);
8568 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008569}
8570#endif /* CONFIG_ISA */
8571
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008572static int __devinit AscInitGetConfig(asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008573{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008574 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008575 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008577 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008578 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008579 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008580
Matthew Wilcox9649af32007-07-26 21:51:47 -06008581 if (AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008582 warn_code |= AscInitAscDvcVar(asc_dvc);
8583 warn_code |= AscInitFromEEP(asc_dvc);
8584 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06008585 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008586 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008587 } else {
8588 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8589 }
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008590
8591 switch (warn_code) {
8592 case 0: /* No error */
8593 break;
8594 case ASC_WARN_IO_PORT_ROTATE:
8595 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
8596 "modified\n", boardp->id);
8597 break;
8598 case ASC_WARN_AUTO_CONFIG:
8599 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
8600 "switch enabled\n", boardp->id);
8601 break;
8602 case ASC_WARN_EEPROM_CHKSUM:
8603 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
8604 "error\n", boardp->id);
8605 break;
8606 case ASC_WARN_IRQ_MODIFIED:
8607 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
8608 boardp->id);
8609 break;
8610 case ASC_WARN_CMD_QNG_CONFLICT:
8611 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
8612 "w/o disconnects\n", boardp->id);
8613 break;
8614 default:
8615 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
8616 "0x%x\n", boardp->id, warn_code);
8617 break;
8618 }
8619
8620 if (asc_dvc->err_code != 0) {
8621 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
8622 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8623 asc_dvc->err_code);
8624 }
8625
8626 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008627}
8628
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008629static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008630{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008631 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008632 PortAddr iop_base = asc_dvc->iop_base;
8633 unsigned short cfg_msw;
8634 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008636 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
8637 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008638 return asc_dvc->err_code;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008639 if (!AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008640 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008641 return asc_dvc->err_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008643
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008644 cfg_msw = AscGetChipCfgMsw(iop_base);
8645 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008646 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008647 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8648 AscSetChipCfgMsw(iop_base, cfg_msw);
8649 }
8650 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
8651 asc_dvc->cfg->cmd_qng_enabled) {
8652 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
8653 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
8654 }
8655 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8656 warn_code |= ASC_WARN_AUTO_CONFIG;
8657 }
8658 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
8659 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
8660 != asc_dvc->irq_no) {
8661 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
8662 }
8663 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008664#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008665 if (asc_dvc->bus_type & ASC_IS_PCI) {
8666 cfg_msw &= 0xFFC0;
8667 AscSetChipCfgMsw(iop_base, cfg_msw);
8668 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
8669 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -06008670 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
8671 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008672 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
8673 asc_dvc->bug_fix_cntl |=
8674 ASC_BUG_FIX_ASYN_USE_SYN;
8675 }
8676 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008677 } else
8678#endif /* CONFIG_PCI */
8679 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008680 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
8681 == ASC_CHIP_VER_ASYN_BUG) {
8682 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
8683 }
8684 }
8685 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
8686 asc_dvc->cfg->chip_scsi_id) {
8687 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
8688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008689#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008690 if (asc_dvc->bus_type & ASC_IS_ISA) {
8691 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
8692 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
8693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008694#endif /* CONFIG_ISA */
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008695
8696 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008697
8698 switch (warn_code) {
8699 case 0: /* No error. */
8700 break;
8701 case ASC_WARN_IO_PORT_ROTATE:
8702 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
8703 "modified\n", boardp->id);
8704 break;
8705 case ASC_WARN_AUTO_CONFIG:
8706 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
8707 "switch enabled\n", boardp->id);
8708 break;
8709 case ASC_WARN_EEPROM_CHKSUM:
8710 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
8711 "error\n", boardp->id);
8712 break;
8713 case ASC_WARN_IRQ_MODIFIED:
8714 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
8715 boardp->id);
8716 break;
8717 case ASC_WARN_CMD_QNG_CONFLICT:
8718 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
8719 "disconnects\n",
8720 boardp->id);
8721 break;
8722 default:
8723 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
8724 "0x%x\n", boardp->id, warn_code);
8725 break;
8726 }
8727
8728 if (asc_dvc->err_code != 0) {
8729 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
8730 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8731 asc_dvc->err_code);
8732 }
8733
8734 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008735}
8736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008737static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008738{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008739 ushort warn_code;
8740 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008742 iop_base = asc_dvc->iop_base;
8743 warn_code = 0;
8744 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
8745 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
8746 AscResetChipAndScsiBus(asc_dvc);
8747 DvcSleepMilliSecond((ASC_DCNT)
8748 ((ushort)asc_dvc->scsi_reset_wait * 1000));
8749 }
8750 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
8751 if (asc_dvc->err_code != 0)
8752 return (UW_ERR);
8753 if (!AscFindSignature(asc_dvc->iop_base)) {
8754 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8755 return (warn_code);
8756 }
8757 AscDisableInterrupt(iop_base);
8758 warn_code |= AscInitLram(asc_dvc);
8759 if (asc_dvc->err_code != 0)
8760 return (UW_ERR);
8761 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
8762 (ulong)_asc_mcode_chksum);
8763 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
8764 _asc_mcode_size) != _asc_mcode_chksum) {
8765 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
8766 return (warn_code);
8767 }
8768 warn_code |= AscInitMicroCodeVar(asc_dvc);
8769 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
8770 AscEnableInterrupt(iop_base);
8771 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008772}
8773
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008774static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008775{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008776 int i;
8777 PortAddr iop_base;
8778 ushort warn_code;
8779 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008781 iop_base = asc_dvc->iop_base;
8782 warn_code = 0;
8783 asc_dvc->err_code = 0;
8784 if ((asc_dvc->bus_type &
8785 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
8786 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
8787 }
8788 AscSetChipControl(iop_base, CC_HALT);
8789 AscSetChipStatus(iop_base, 0);
8790 asc_dvc->bug_fix_cntl = 0;
8791 asc_dvc->pci_fix_asyn_xfer = 0;
8792 asc_dvc->pci_fix_asyn_xfer_always = 0;
8793 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
8794 asc_dvc->sdtr_done = 0;
8795 asc_dvc->cur_total_qng = 0;
8796 asc_dvc->is_in_int = 0;
8797 asc_dvc->in_critical_cnt = 0;
8798 asc_dvc->last_q_shortage = 0;
8799 asc_dvc->use_tagged_qng = 0;
8800 asc_dvc->no_scam = 0;
8801 asc_dvc->unit_not_ready = 0;
8802 asc_dvc->queue_full_or_busy = 0;
8803 asc_dvc->redo_scam = 0;
8804 asc_dvc->res2 = 0;
8805 asc_dvc->host_init_sdtr_index = 0;
8806 asc_dvc->cfg->can_tagged_qng = 0;
8807 asc_dvc->cfg->cmd_qng_enabled = 0;
8808 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
8809 asc_dvc->init_sdtr = 0;
8810 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
8811 asc_dvc->scsi_reset_wait = 3;
8812 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
8813 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
8814 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
8815 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
8816 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
8817 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
8818 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
8819 ASC_LIB_VERSION_MINOR;
8820 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
8821 asc_dvc->cfg->chip_version = chip_version;
8822 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
8823 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
8824 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
8825 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
8826 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
8827 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
8828 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
8829 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
8830 asc_dvc->max_sdtr_index = 7;
8831 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
8832 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
8833 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
8834 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
8835 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
8836 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
8837 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
8838 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
8839 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
8840 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
8841 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
8842 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
8843 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
8844 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
8845 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
8846 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
8847 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
8848 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
8849 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
8850 asc_dvc->max_sdtr_index = 15;
8851 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
8852 AscSetExtraControl(iop_base,
8853 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8854 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
8855 AscSetExtraControl(iop_base,
8856 (SEC_ACTIVE_NEGATE |
8857 SEC_ENABLE_FILTER));
8858 }
8859 }
8860 if (asc_dvc->bus_type == ASC_IS_PCI) {
8861 AscSetExtraControl(iop_base,
8862 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008864
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008865 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008866#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008867 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
Matthew Wilcox59fcf842007-07-26 11:54:15 -04008868 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
8869 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
8870 asc_dvc->bus_type = ASC_IS_ISAPNP;
8871 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008872 asc_dvc->cfg->isa_dma_channel =
8873 (uchar)AscGetIsaDmaChannel(iop_base);
8874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008875#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008876 for (i = 0; i <= ASC_MAX_TID; i++) {
8877 asc_dvc->cur_dvc_qng[i] = 0;
8878 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
8879 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
8880 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
8881 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
8882 }
8883 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008884}
8885
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008886static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008887{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008888 ASCEEP_CONFIG eep_config_buf;
8889 ASCEEP_CONFIG *eep_config;
8890 PortAddr iop_base;
8891 ushort chksum;
8892 ushort warn_code;
8893 ushort cfg_msw, cfg_lsw;
8894 int i;
8895 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008896
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008897 iop_base = asc_dvc->iop_base;
8898 warn_code = 0;
8899 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
8900 AscStopQueueExe(iop_base);
8901 if ((AscStopChip(iop_base) == FALSE) ||
8902 (AscGetChipScsiCtrl(iop_base) != 0)) {
8903 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
8904 AscResetChipAndScsiBus(asc_dvc);
8905 DvcSleepMilliSecond((ASC_DCNT)
8906 ((ushort)asc_dvc->scsi_reset_wait * 1000));
8907 }
8908 if (AscIsChipHalted(iop_base) == FALSE) {
8909 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8910 return (warn_code);
8911 }
8912 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8913 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8914 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8915 return (warn_code);
8916 }
8917 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
8918 cfg_msw = AscGetChipCfgMsw(iop_base);
8919 cfg_lsw = AscGetChipCfgLsw(iop_base);
8920 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008921 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008922 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8923 AscSetChipCfgMsw(iop_base, cfg_msw);
8924 }
8925 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
8926 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
8927 if (chksum == 0) {
8928 chksum = 0xaa55;
8929 }
8930 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8931 warn_code |= ASC_WARN_AUTO_CONFIG;
8932 if (asc_dvc->cfg->chip_version == 3) {
8933 if (eep_config->cfg_lsw != cfg_lsw) {
8934 warn_code |= ASC_WARN_EEPROM_RECOVER;
8935 eep_config->cfg_lsw =
8936 AscGetChipCfgLsw(iop_base);
8937 }
8938 if (eep_config->cfg_msw != cfg_msw) {
8939 warn_code |= ASC_WARN_EEPROM_RECOVER;
8940 eep_config->cfg_msw =
8941 AscGetChipCfgMsw(iop_base);
8942 }
8943 }
8944 }
8945 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
8946 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
8947 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
8948 eep_config->chksum);
8949 if (chksum != eep_config->chksum) {
8950 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
8951 ASC_CHIP_VER_PCI_ULTRA_3050) {
8952 ASC_DBG(1,
8953 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
8954 eep_config->init_sdtr = 0xFF;
8955 eep_config->disc_enable = 0xFF;
8956 eep_config->start_motor = 0xFF;
8957 eep_config->use_cmd_qng = 0;
8958 eep_config->max_total_qng = 0xF0;
8959 eep_config->max_tag_qng = 0x20;
8960 eep_config->cntl = 0xBFFF;
8961 ASC_EEP_SET_CHIP_ID(eep_config, 7);
8962 eep_config->no_scam = 0;
8963 eep_config->adapter_info[0] = 0;
8964 eep_config->adapter_info[1] = 0;
8965 eep_config->adapter_info[2] = 0;
8966 eep_config->adapter_info[3] = 0;
8967 eep_config->adapter_info[4] = 0;
8968 /* Indicate EEPROM-less board. */
8969 eep_config->adapter_info[5] = 0xBB;
8970 } else {
8971 ASC_PRINT
8972 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
8973 write_eep = 1;
8974 warn_code |= ASC_WARN_EEPROM_CHKSUM;
8975 }
8976 }
8977 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
8978 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
8979 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
8980 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
8981 asc_dvc->start_motor = eep_config->start_motor;
8982 asc_dvc->dvc_cntl = eep_config->cntl;
8983 asc_dvc->no_scam = eep_config->no_scam;
8984 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
8985 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
8986 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
8987 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
8988 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
8989 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
8990 if (!AscTestExternalLram(asc_dvc)) {
8991 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
8992 ASC_IS_PCI_ULTRA)) {
8993 eep_config->max_total_qng =
8994 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
8995 eep_config->max_tag_qng =
8996 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
8997 } else {
8998 eep_config->cfg_msw |= 0x0800;
8999 cfg_msw |= 0x0800;
9000 AscSetChipCfgMsw(iop_base, cfg_msw);
9001 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
9002 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
9003 }
9004 } else {
9005 }
9006 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
9007 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
9008 }
9009 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
9010 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
9011 }
9012 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
9013 eep_config->max_tag_qng = eep_config->max_total_qng;
9014 }
9015 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
9016 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
9017 }
9018 asc_dvc->max_total_qng = eep_config->max_total_qng;
9019 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
9020 eep_config->use_cmd_qng) {
9021 eep_config->disc_enable = eep_config->use_cmd_qng;
9022 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
9023 }
9024 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
9025 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
9026 }
9027 ASC_EEP_SET_CHIP_ID(eep_config,
9028 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
9029 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
9030 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
9031 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
9032 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
9033 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009035 for (i = 0; i <= ASC_MAX_TID; i++) {
9036 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
9037 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
9038 asc_dvc->cfg->sdtr_period_offset[i] =
9039 (uchar)(ASC_DEF_SDTR_OFFSET |
9040 (asc_dvc->host_init_sdtr_index << 4));
9041 }
9042 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
9043 if (write_eep) {
9044 if ((i =
9045 AscSetEEPConfig(iop_base, eep_config,
9046 asc_dvc->bus_type)) != 0) {
9047 ASC_PRINT1
9048 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
9049 i);
9050 } else {
9051 ASC_PRINT
9052 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
9053 }
9054 }
9055 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009056}
9057
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009058static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009059{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009060 int i;
9061 ushort warn_code;
9062 PortAddr iop_base;
9063 ASC_PADDR phy_addr;
9064 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009066 iop_base = asc_dvc->iop_base;
9067 warn_code = 0;
9068 for (i = 0; i <= ASC_MAX_TID; i++) {
9069 AscPutMCodeInitSDTRAtID(iop_base, i,
9070 asc_dvc->cfg->sdtr_period_offset[i]
9071 );
9072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009074 AscInitQLinkVar(asc_dvc);
9075 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
9076 asc_dvc->cfg->disc_enable);
9077 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
9078 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009079
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009080 /* Align overrun buffer on an 8 byte boundary. */
9081 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
9082 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
9083 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
9084 (uchar *)&phy_addr, 1);
9085 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
9086 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
9087 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009089 asc_dvc->cfg->mcode_date =
9090 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
9091 asc_dvc->cfg->mcode_version =
9092 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009093
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009094 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
9095 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
9096 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
9097 return (warn_code);
9098 }
9099 if (AscStartChip(iop_base) != 1) {
9100 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
9101 return (warn_code);
9102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009104 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009105}
9106
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009107static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009108{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009109 PortAddr iop_base;
9110 ushort q_addr;
9111 ushort saved_word;
9112 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009113
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009114 iop_base = asc_dvc->iop_base;
9115 sta = 0;
9116 q_addr = ASC_QNO_TO_QADDR(241);
9117 saved_word = AscReadLramWord(iop_base, q_addr);
9118 AscSetChipLramAddr(iop_base, q_addr);
9119 AscSetChipLramData(iop_base, 0x55AA);
9120 DvcSleepMilliSecond(10);
9121 AscSetChipLramAddr(iop_base, q_addr);
9122 if (AscGetChipLramData(iop_base) == 0x55AA) {
9123 sta = 1;
9124 AscWriteLramWord(iop_base, q_addr, saved_word);
9125 }
9126 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009127}
9128
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009129static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009130{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009131 uchar read_back;
9132 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009133
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009134 retry = 0;
9135 while (TRUE) {
9136 AscSetChipEEPCmd(iop_base, cmd_reg);
9137 DvcSleepMilliSecond(1);
9138 read_back = AscGetChipEEPCmd(iop_base);
9139 if (read_back == cmd_reg) {
9140 return (1);
9141 }
9142 if (retry++ > ASC_EEP_MAX_RETRY) {
9143 return (0);
9144 }
9145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009146}
9147
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009148static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009149{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009150 ushort read_back;
9151 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009152
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009153 retry = 0;
9154 while (TRUE) {
9155 AscSetChipEEPData(iop_base, data_reg);
9156 DvcSleepMilliSecond(1);
9157 read_back = AscGetChipEEPData(iop_base);
9158 if (read_back == data_reg) {
9159 return (1);
9160 }
9161 if (retry++ > ASC_EEP_MAX_RETRY) {
9162 return (0);
9163 }
9164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009165}
9166
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009167static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009168{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009169 DvcSleepMilliSecond(1);
9170 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009171}
9172
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009173static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009174{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009175 DvcSleepMilliSecond(20);
9176 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009177}
9178
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009179static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009180{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009181 ushort read_wval;
9182 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009184 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9185 AscWaitEEPRead();
9186 cmd_reg = addr | ASC_EEP_CMD_READ;
9187 AscWriteEEPCmdReg(iop_base, cmd_reg);
9188 AscWaitEEPRead();
9189 read_wval = AscGetChipEEPData(iop_base);
9190 AscWaitEEPRead();
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 -04009195AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009196{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009197 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009199 read_wval = AscReadEEPWord(iop_base, addr);
9200 if (read_wval != word_val) {
9201 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
9202 AscWaitEEPRead();
9203 AscWriteEEPDataReg(iop_base, word_val);
9204 AscWaitEEPRead();
9205 AscWriteEEPCmdReg(iop_base,
9206 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
9207 AscWaitEEPWrite();
9208 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9209 AscWaitEEPRead();
9210 return (AscReadEEPWord(iop_base, addr));
9211 }
9212 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009213}
9214
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009215static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009216AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009217{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009218 ushort wval;
9219 ushort sum;
9220 ushort *wbuf;
9221 int cfg_beg;
9222 int cfg_end;
9223 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
9224 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009225
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009226 wbuf = (ushort *)cfg_buf;
9227 sum = 0;
9228 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
9229 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9230 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9231 sum += *wbuf;
9232 }
9233 if (bus_type & ASC_IS_VL) {
9234 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9235 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9236 } else {
9237 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9238 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9239 }
9240 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9241 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
9242 if (s_addr <= uchar_end_in_config) {
9243 /*
9244 * Swap all char fields - must unswap bytes already swapped
9245 * by AscReadEEPWord().
9246 */
9247 *wbuf = le16_to_cpu(wval);
9248 } else {
9249 /* Don't swap word field at the end - cntl field. */
9250 *wbuf = wval;
9251 }
9252 sum += wval; /* Checksum treats all EEPROM data as words. */
9253 }
9254 /*
9255 * Read the checksum word which will be compared against 'sum'
9256 * by the caller. Word field already swapped.
9257 */
9258 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9259 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009260}
9261
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009262static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009263AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009264{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009265 int n_error;
9266 ushort *wbuf;
9267 ushort word;
9268 ushort sum;
9269 int s_addr;
9270 int cfg_beg;
9271 int cfg_end;
9272 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009274 wbuf = (ushort *)cfg_buf;
9275 n_error = 0;
9276 sum = 0;
9277 /* Write two config words; AscWriteEEPWord() will swap bytes. */
9278 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9279 sum += *wbuf;
9280 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9281 n_error++;
9282 }
9283 }
9284 if (bus_type & ASC_IS_VL) {
9285 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9286 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9287 } else {
9288 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9289 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9290 }
9291 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9292 if (s_addr <= uchar_end_in_config) {
9293 /*
9294 * This is a char field. Swap char fields before they are
9295 * swapped again by AscWriteEEPWord().
9296 */
9297 word = cpu_to_le16(*wbuf);
9298 if (word !=
9299 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
9300 n_error++;
9301 }
9302 } else {
9303 /* Don't swap word field at the end - cntl field. */
9304 if (*wbuf !=
9305 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9306 n_error++;
9307 }
9308 }
9309 sum += *wbuf; /* Checksum calculated from word values. */
9310 }
9311 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
9312 *wbuf = sum;
9313 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
9314 n_error++;
9315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009316
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009317 /* Read EEPROM back again. */
9318 wbuf = (ushort *)cfg_buf;
9319 /*
9320 * Read two config words; Byte-swapping done by AscReadEEPWord().
9321 */
9322 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9323 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
9324 n_error++;
9325 }
9326 }
9327 if (bus_type & ASC_IS_VL) {
9328 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9329 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9330 } else {
9331 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9332 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9333 }
9334 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9335 if (s_addr <= uchar_end_in_config) {
9336 /*
9337 * Swap all char fields. Must unswap bytes already swapped
9338 * by AscReadEEPWord().
9339 */
9340 word =
9341 le16_to_cpu(AscReadEEPWord
9342 (iop_base, (uchar)s_addr));
9343 } else {
9344 /* Don't swap word field at the end - cntl field. */
9345 word = AscReadEEPWord(iop_base, (uchar)s_addr);
9346 }
9347 if (*wbuf != word) {
9348 n_error++;
9349 }
9350 }
9351 /* Read checksum; Byte swapping not needed. */
9352 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
9353 n_error++;
9354 }
9355 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009356}
9357
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009358static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009359AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009360{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009361 int retry;
9362 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009364 retry = 0;
9365 while (TRUE) {
9366 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
9367 bus_type)) == 0) {
9368 break;
9369 }
9370 if (++retry > ASC_EEP_MAX_RETRY) {
9371 break;
9372 }
9373 }
9374 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009375}
9376
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009377static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009378{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009379 char type = sdev->type;
9380 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009381
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009382 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
9383 if (!(asc_dvc->init_sdtr & tid_bits)) {
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009384 if ((type == TYPE_ROM) &&
9385 (strncmp(sdev->vendor, "HP ", 3) == 0)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009386 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9387 }
9388 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009389 if ((type == TYPE_PROCESSOR) ||
9390 (type == TYPE_SCANNER) || (type == TYPE_ROM) ||
9391 (type == TYPE_TAPE)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009392 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009394
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009395 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
9396 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009397 sdev->id,
9398 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009399 }
9400 }
9401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009402}
9403
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009404static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009405{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009406 uchar byte_data;
9407 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009408
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009409 if (isodd_word(addr)) {
9410 AscSetChipLramAddr(iop_base, addr - 1);
9411 word_data = AscGetChipLramData(iop_base);
9412 byte_data = (uchar)((word_data >> 8) & 0xFF);
9413 } else {
9414 AscSetChipLramAddr(iop_base, addr);
9415 word_data = AscGetChipLramData(iop_base);
9416 byte_data = (uchar)(word_data & 0xFF);
9417 }
9418 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009419}
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009421static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
9422{
9423 ushort word_data;
9424
9425 AscSetChipLramAddr(iop_base, addr);
9426 word_data = AscGetChipLramData(iop_base);
9427 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009428}
9429
9430#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009431static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009432{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009433 ushort val_low, val_high;
9434 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009435
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009436 AscSetChipLramAddr(iop_base, addr);
9437 val_low = AscGetChipLramData(iop_base);
9438 val_high = AscGetChipLramData(iop_base);
9439 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
9440 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009441}
9442#endif /* CC_VERY_LONG_SG_LIST */
9443
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009444static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009445{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009446 AscSetChipLramAddr(iop_base, addr);
9447 AscSetChipLramData(iop_base, word_val);
9448 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009449}
9450
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009451static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009452{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009453 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009454
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009455 if (isodd_word(addr)) {
9456 addr--;
9457 word_data = AscReadLramWord(iop_base, addr);
9458 word_data &= 0x00FF;
9459 word_data |= (((ushort)byte_val << 8) & 0xFF00);
9460 } else {
9461 word_data = AscReadLramWord(iop_base, addr);
9462 word_data &= 0xFF00;
9463 word_data |= ((ushort)byte_val & 0x00FF);
9464 }
9465 AscWriteLramWord(iop_base, addr, word_data);
9466 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009467}
9468
9469/*
9470 * Copy 2 bytes to LRAM.
9471 *
9472 * The source data is assumed to be in little-endian order in memory
9473 * and is maintained in little-endian order when written to LRAM.
9474 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009475static void
9476AscMemWordCopyPtrToLram(PortAddr iop_base,
9477 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009478{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009479 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009480
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009481 AscSetChipLramAddr(iop_base, s_addr);
9482 for (i = 0; i < 2 * words; i += 2) {
9483 /*
9484 * On a little-endian system the second argument below
9485 * produces a little-endian ushort which is written to
9486 * LRAM in little-endian order. On a big-endian system
9487 * the second argument produces a big-endian ushort which
9488 * is "transparently" byte-swapped by outpw() and written
9489 * in little-endian order to LRAM.
9490 */
9491 outpw(iop_base + IOP_RAM_DATA,
9492 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
9493 }
9494 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009495}
9496
9497/*
9498 * Copy 4 bytes to LRAM.
9499 *
9500 * The source data is assumed to be in little-endian order in memory
9501 * and is maintained in little-endian order when writen to LRAM.
9502 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009503static void
9504AscMemDWordCopyPtrToLram(PortAddr iop_base,
9505 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009506{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009507 int i;
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 < 4 * dwords; i += 4) {
9511 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
9512 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
9513 }
9514 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009515}
9516
9517/*
9518 * Copy 2 bytes from LRAM.
9519 *
9520 * The source data is assumed to be in little-endian order in LRAM
9521 * and is maintained in little-endian order when written to memory.
9522 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009523static void
9524AscMemWordCopyPtrFromLram(PortAddr iop_base,
9525 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009526{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009527 int i;
9528 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009529
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009530 AscSetChipLramAddr(iop_base, s_addr);
9531 for (i = 0; i < 2 * words; i += 2) {
9532 word = inpw(iop_base + IOP_RAM_DATA);
9533 d_buffer[i] = word & 0xff;
9534 d_buffer[i + 1] = (word >> 8) & 0xff;
9535 }
9536 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009537}
9538
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009539static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009540{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009541 ASC_DCNT sum;
9542 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009543
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009544 sum = 0L;
9545 for (i = 0; i < words; i++, s_addr += 2) {
9546 sum += AscReadLramWord(iop_base, s_addr);
9547 }
9548 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009549}
9550
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009551static void
9552AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009553{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009554 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009555
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009556 AscSetChipLramAddr(iop_base, s_addr);
9557 for (i = 0; i < words; i++) {
9558 AscSetChipLramData(iop_base, set_wval);
9559 }
9560 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009561}
9562
Linus Torvalds1da177e2005-04-16 15:20:36 -07009563/*
9564 * --- Adv Library Functions
9565 */
9566
9567/* a_mcode.h */
9568
9569/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009570static unsigned char _adv_asc3550_buf[] = {
9571 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009572 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
9573 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
9574 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009575 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009576 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
9577 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
9578 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009579 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009580 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
9581 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
9582 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009583 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009584 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
9585 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
9586 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009587 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009588 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
9589 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
9590 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009591 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009592 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
9593 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
9594 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009595 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009596 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
9597 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
9598 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009599 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009600 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
9601 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
9602 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009603 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009604 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
9605 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
9606 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009607 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009608 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
9609 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
9610 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009611 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009612 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
9613 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
9614 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009615 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009616 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
9617 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
9618 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009619 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009620 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
9621 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
9622 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009623 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009624 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
9625 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
9626 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009627 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009628 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
9629 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
9630 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009631 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009632 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
9633 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
9634 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009635 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009636 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
9637 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
9638 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009639 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009640 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
9641 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
9642 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009643 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009644 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
9645 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
9646 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009647 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009648 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
9649 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
9650 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009651 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009652 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
9653 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
9654 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009655 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009656 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
9657 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
9658 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009659 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009660 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
9661 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
9662 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009663 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009664 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
9665 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
9666 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009667 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009668 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
9669 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
9670 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009671 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009672 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
9673 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
9674 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009675 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009676 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
9677 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
9678 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009679 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009680 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
9681 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
9682 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009683 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009684 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
9685 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
9686 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009687 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009688 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
9689 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
9690 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009691 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009692 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
9693 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
9694 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009695 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009696 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
9697 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
9698 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009699 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009700 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
9701 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
9702 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009703 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009704 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
9705 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
9706 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009707 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009708 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
9709 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
9710 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009711 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009712 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
9713 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
9714 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009715 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009716 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
9717 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
9718 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009719 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009720 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
9721 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
9722 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009723 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009724 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
9725 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
9726 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009727 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009728 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
9729 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
9730 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009731 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009732 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
9733 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
9734 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009735 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009736 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
9737 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
9738 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009739 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009740 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
9741 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
9742 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009743 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009744 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
9745 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
9746 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009747 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009748 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
9749 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
9750 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009751 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009752 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
9753 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
9754 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009755 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009756 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
9757 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
9758 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009759 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009760 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
9761 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
9762 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009763 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009764 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
9765 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
9766 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009767 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009768 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
9769 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
9770 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009771 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009772 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
9773 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
9774 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009775 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009776 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
9777 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
9778 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009779 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009780 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
9781 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
9782 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009783 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009784 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
9785 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
9786 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009787 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009788 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
9789 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
9790 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009791 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009792 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
9793 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
9794 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009795 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009796 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
9797 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
9798 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009799 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009800 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
9801 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
9802 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009803 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009804 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
9805 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
9806 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009807 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009808 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
9809 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
9810 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009811 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009812 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
9813 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
9814 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009815 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009816 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
9817 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
9818 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009819 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009820 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
9821 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
9822 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009823 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009824 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
9825 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
9826 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009827 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009828 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
9829 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
9830 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009831 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009832 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
9833 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
9834 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009835 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009836 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
9837 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
9838 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009839 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009840 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
9841 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
9842 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009843 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009844 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
9845 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
9846 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009847 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009848 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
9849 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
9850 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009851 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009852 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
9853 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
9854 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009855 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009856 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
9857 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
9858 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009859 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009860 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
9861 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
9862 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009863 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009864 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
9865 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
9866 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009867 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009868 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
9869 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
9870 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009871 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009872 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
9873 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
9874 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009875 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009876 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
9877 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
9878 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009879 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009880 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
9881 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
9882 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009883 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009884 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
9885 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
9886 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009887 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009888 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
9889 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
9890 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009891 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009892 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
9893 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
9894 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009895 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009896 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
9897 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
9898 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009899 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009900 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
9901 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
9902 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009903 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009904 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
9905 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
9906 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009907 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009908 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
9909 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
9910 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009911 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009912 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
9913 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
9914 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009915 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009916 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
9917 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
9918 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009919 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009920 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
9921 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
9922 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009923 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009924 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
9925 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
9926 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009927 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009928 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
9929 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
9930 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009931 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009932 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
9933 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
9934 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009935 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009936 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
9937 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
9938 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009939 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009940 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
9941 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
9942 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009943 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009944 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
9945 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
9946 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009947 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009948 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
9949 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
9950 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009951 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009952 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
9953 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
9954 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009955 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009956 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
9957 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
9958 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009959 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009960 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
9961 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
9962 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009963 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009964 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
9965 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
9966 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009967 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009968 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
9969 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
9970 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009971 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009972 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
9973 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
9974 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009975 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009976 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
9977 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
9978 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009979 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009980 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
9981 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
9982 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009983 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009984 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
9985 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
9986 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009987 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009988 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
9989 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009990};
9991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009992static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
9993static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009994
9995/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009996static unsigned char _adv_asc38C0800_buf[] = {
9997 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009998 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
9999 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
10000 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010001 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010002 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
10003 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
10004 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010005 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010006 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
10007 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
10008 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010009 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010010 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
10011 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
10012 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010013 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010014 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
10015 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
10016 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010017 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010018 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
10019 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
10020 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010021 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010022 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
10023 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
10024 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010025 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010026 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
10027 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
10028 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010029 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010030 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
10031 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
10032 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010033 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010034 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
10035 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
10036 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010037 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010038 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
10039 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
10040 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010041 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010042 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
10043 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10044 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010045 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010046 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
10047 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
10048 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010049 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010050 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
10051 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
10052 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010053 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010054 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
10055 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
10056 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010057 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010058 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
10059 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
10060 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010061 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010062 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
10063 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
10064 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010065 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010066 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
10067 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
10068 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010069 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010070 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
10071 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
10072 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010073 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010074 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
10075 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
10076 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010077 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010078 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
10079 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
10080 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010081 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010082 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
10083 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
10084 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010085 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010086 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
10087 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
10088 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010089 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010090 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
10091 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
10092 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010093 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010094 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
10095 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
10096 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010097 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010098 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
10099 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
10100 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010101 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010102 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
10103 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
10104 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010105 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010106 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
10107 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
10108 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010109 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010110 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
10111 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
10112 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010113 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010114 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
10115 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
10116 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010117 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010118 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
10119 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
10120 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010121 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010122 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
10123 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
10124 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010125 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010126 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
10127 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
10128 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010129 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010130 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
10131 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
10132 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010133 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010134 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
10135 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
10136 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010137 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010138 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
10139 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
10140 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010141 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010142 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
10143 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
10144 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010145 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010146 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
10147 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
10148 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010149 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010150 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
10151 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
10152 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010153 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010154 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
10155 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
10156 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010157 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010158 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
10159 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
10160 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010161 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010162 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
10163 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
10164 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010165 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010166 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
10167 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
10168 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010169 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010170 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
10171 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
10172 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010173 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010174 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
10175 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
10176 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010177 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010178 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
10179 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
10180 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010181 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010182 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
10183 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
10184 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010185 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010186 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
10187 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
10188 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010189 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010190 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
10191 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
10192 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010193 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010194 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
10195 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
10196 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010197 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010198 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
10199 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
10200 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010201 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010202 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
10203 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
10204 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010205 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010206 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
10207 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
10208 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010209 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010210 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
10211 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
10212 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010213 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010214 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
10215 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
10216 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010217 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010218 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
10219 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
10220 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010221 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010222 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
10223 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
10224 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010225 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010226 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
10227 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
10228 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010229 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010230 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
10231 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
10232 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010233 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010234 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
10235 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
10236 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010237 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010238 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
10239 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
10240 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010241 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010242 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
10243 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
10244 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010245 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010246 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
10247 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
10248 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010249 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010250 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
10251 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
10252 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010253 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010254 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
10255 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
10256 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010257 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010258 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
10259 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
10260 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010261 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010262 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
10263 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
10264 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010265 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010266 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
10267 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
10268 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010269 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010270 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
10271 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
10272 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010273 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010274 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
10275 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
10276 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010277 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010278 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
10279 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
10280 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010281 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010282 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
10283 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
10284 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010285 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010286 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
10287 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
10288 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010289 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010290 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
10291 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
10292 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010293 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010294 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
10295 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
10296 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010297 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010298 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
10299 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
10300 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010301 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010302 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
10303 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
10304 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010305 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010306 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
10307 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
10308 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010309 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010310 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
10311 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
10312 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010313 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010314 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
10315 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
10316 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010317 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010318 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
10319 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
10320 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010321 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010322 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
10323 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
10324 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010325 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010326 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
10327 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
10328 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010329 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010330 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
10331 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
10332 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010333 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010334 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
10335 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
10336 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010337 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010338 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
10339 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
10340 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010341 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010342 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
10343 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10344 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010345 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010346 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10347 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
10348 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010349 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010350 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
10351 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
10352 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010353 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010354 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
10355 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
10356 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010357 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010358 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
10359 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
10360 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010361 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010362 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
10363 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
10364 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010365 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010366 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
10367 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
10368 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010369 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010370 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
10371 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
10372 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010373 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010374 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
10375 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
10376 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010377 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010378 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
10379 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
10380 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010381 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010382 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
10383 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
10384 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010385 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010386 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
10387 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
10388 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010389 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010390 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
10391 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
10392 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010393 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010394 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
10395 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
10396 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010397 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010398 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
10399 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
10400 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010401 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010402 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
10403 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
10404 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010405 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010406 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
10407 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
10408 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010409 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010410 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
10411 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
10412 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010413 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010414 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
10415 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
10416 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010417 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010418 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
10419 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
10420 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010421 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010422 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
10423 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
10424 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010425 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010426 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
10427 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
10428 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010429 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010430 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
10431 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
10432 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010433 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010434 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
10435 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
10436 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010437 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010438 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
10439 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
10440 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010441 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010442};
10443
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010444static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
10445static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010446
10447/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010448static unsigned char _adv_asc38C1600_buf[] = {
10449 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010450 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
10451 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
10452 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010453 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010454 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
10455 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
10456 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010457 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010458 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
10459 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
10460 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010461 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010462 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
10463 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
10464 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010465 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010466 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
10467 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
10468 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010469 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010470 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
10471 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
10472 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010473 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010474 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
10475 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
10476 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010477 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010478 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
10479 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
10480 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010481 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010482 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
10483 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
10484 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010485 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010486 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
10487 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
10488 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010489 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010490 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
10491 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
10492 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010493 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010494 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
10495 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10496 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010497 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010498 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
10499 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
10500 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010501 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010502 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
10503 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
10504 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010505 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010506 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
10507 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
10508 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010509 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010510 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
10511 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
10512 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010513 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010514 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
10515 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
10516 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010517 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010518 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
10519 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
10520 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010521 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010522 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
10523 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
10524 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010525 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010526 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
10527 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
10528 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010529 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010530 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
10531 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
10532 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010533 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010534 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
10535 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
10536 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010537 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010538 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
10539 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
10540 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010541 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010542 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
10543 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
10544 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010545 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010546 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
10547 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
10548 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010549 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010550 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
10551 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
10552 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010553 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010554 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
10555 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
10556 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010557 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010558 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
10559 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
10560 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010561 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010562 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
10563 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
10564 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010565 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010566 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
10567 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
10568 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010569 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010570 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
10571 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
10572 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010573 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010574 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
10575 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
10576 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010577 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010578 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
10579 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
10580 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010581 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010582 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
10583 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
10584 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010585 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010586 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
10587 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
10588 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010589 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010590 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
10591 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
10592 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010593 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010594 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
10595 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
10596 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010597 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010598 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
10599 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
10600 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010601 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010602 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
10603 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
10604 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010605 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010606 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
10607 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
10608 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010609 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010610 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
10611 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
10612 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010613 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010614 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
10615 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
10616 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010617 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010618 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
10619 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
10620 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010621 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010622 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
10623 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
10624 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010625 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010626 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
10627 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
10628 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010629 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010630 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
10631 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
10632 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010633 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010634 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
10635 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
10636 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010637 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010638 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
10639 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
10640 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010641 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010642 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
10643 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
10644 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010645 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010646 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
10647 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
10648 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010649 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010650 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
10651 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
10652 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010653 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010654 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
10655 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
10656 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010657 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010658 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
10659 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
10660 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010661 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010662 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
10663 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
10664 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010665 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010666 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
10667 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
10668 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010669 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010670 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
10671 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
10672 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010673 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010674 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
10675 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
10676 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010677 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010678 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
10679 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
10680 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010681 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010682 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
10683 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
10684 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010685 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010686 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
10687 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
10688 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010689 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010690 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
10691 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
10692 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010693 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010694 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
10695 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
10696 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010697 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010698 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
10699 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
10700 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010701 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010702 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
10703 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
10704 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010705 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010706 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
10707 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
10708 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010709 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010710 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
10711 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
10712 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010713 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010714 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
10715 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
10716 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010717 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010718 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
10719 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
10720 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010721 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010722 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
10723 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
10724 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010725 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010726 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
10727 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
10728 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010729 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010730 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
10731 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
10732 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010733 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010734 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
10735 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
10736 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010737 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010738 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
10739 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
10740 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010741 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010742 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
10743 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
10744 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010745 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010746 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
10747 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
10748 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010749 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010750 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
10751 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
10752 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010753 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010754 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
10755 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
10756 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010757 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010758 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
10759 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
10760 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010761 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010762 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
10763 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
10764 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010765 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010766 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
10767 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
10768 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010769 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010770 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
10771 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
10772 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010773 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010774 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
10775 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
10776 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010777 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010778 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
10779 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
10780 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010781 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010782 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
10783 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
10784 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010785 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010786 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
10787 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
10788 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010789 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010790 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
10791 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
10792 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010793 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010794 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
10795 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
10796 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010797 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010798 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
10799 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
10800 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010801 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010802 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
10803 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
10804 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010805 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010806 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
10807 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
10808 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010809 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010810 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
10811 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
10812 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010813 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010814 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
10815 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
10816 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010817 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010818 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
10819 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
10820 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010821 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010822 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
10823 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
10824 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010825 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010826 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
10827 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
10828 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010829 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010830 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
10831 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
10832 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010833 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010834 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
10835 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
10836 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010837 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010838 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
10839 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
10840 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010841 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010842 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
10843 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
10844 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010845 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010846 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
10847 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
10848 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010849 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010850 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
10851 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
10852 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010853 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010854 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
10855 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
10856 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010857 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010858 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
10859 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
10860 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010861 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010862 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
10863 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
10864 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010865 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010866 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
10867 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
10868 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010869 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010870 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
10871 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
10872 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010873 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010874 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
10875 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
10876 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010877 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010878 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
10879 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
10880 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010881 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010882 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
10883 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
10884 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010885 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010886 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
10887 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
10888 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010889 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010890 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
10891 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
10892 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010893 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010894 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
10895 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
10896 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010897 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010898 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
10899 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
10900 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010901 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010902 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
10903 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
10904 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010905 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010906 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
10907 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
10908 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010909 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010910 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
10911 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
10912 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010913 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010914 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
10915 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
10916 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010917 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010918 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
10919 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
10920 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010921 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010922 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
10923 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
10924 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010925 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010926 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
10927 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
10928 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010929 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010930 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
10931 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
10932 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010933 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010934 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
10935 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
10936 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010937 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010938 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
10939 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
10940 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010941 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010942 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
10943 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
10944 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010945 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010946 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
10947 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
10948 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010949 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010950 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
10951 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
10952 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010953 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010954 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
10955 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
10956 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010957 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010958 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
10959 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
10960 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010961 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010962 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
10963 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
10964 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010965 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010966 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
10967 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
10968 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010969 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010970 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
10971 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
10972 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010973 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010974 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
10975 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
10976 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010977};
10978
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010979static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
10980static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010981
Linus Torvalds1da177e2005-04-16 15:20:36 -070010982/*
10983 * EEPROM Configuration.
10984 *
10985 * All drivers should use this structure to set the default EEPROM
10986 * configuration. The BIOS now uses this structure when it is built.
10987 * Additional structure information can be found in a_condor.h where
10988 * the structure is defined.
10989 *
10990 * The *_Field_IsChar structs are needed to correct for endianness.
10991 * These values are read from the board 16 bits at a time directly
10992 * into the structs. Because some fields are char, the values will be
10993 * in the wrong order. The *_Field_IsChar tells when to flip the
10994 * bytes. Data read and written to PCI memory is automatically swapped
10995 * on big-endian platforms so char fields read as words are actually being
10996 * unswapped on big-endian platforms.
10997 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010998static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010999 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
11000 0x0000, /* cfg_msw */
11001 0xFFFF, /* disc_enable */
11002 0xFFFF, /* wdtr_able */
11003 0xFFFF, /* sdtr_able */
11004 0xFFFF, /* start_motor */
11005 0xFFFF, /* tagqng_able */
11006 0xFFFF, /* bios_scan */
11007 0, /* scam_tolerant */
11008 7, /* adapter_scsi_id */
11009 0, /* bios_boot_delay */
11010 3, /* scsi_reset_delay */
11011 0, /* bios_id_lun */
11012 0, /* termination */
11013 0, /* reserved1 */
11014 0xFFE7, /* bios_ctrl */
11015 0xFFFF, /* ultra_able */
11016 0, /* reserved2 */
11017 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
11018 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11019 0, /* dvc_cntl */
11020 0, /* bug_fix */
11021 0, /* serial_number_word1 */
11022 0, /* serial_number_word2 */
11023 0, /* serial_number_word3 */
11024 0, /* check_sum */
11025 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11026 , /* oem_name[16] */
11027 0, /* dvc_err_code */
11028 0, /* adv_err_code */
11029 0, /* adv_err_addr */
11030 0, /* saved_dvc_err_code */
11031 0, /* saved_adv_err_code */
11032 0, /* saved_adv_err_addr */
11033 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011034};
11035
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011036static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011037 0, /* cfg_lsw */
11038 0, /* cfg_msw */
11039 0, /* -disc_enable */
11040 0, /* wdtr_able */
11041 0, /* sdtr_able */
11042 0, /* start_motor */
11043 0, /* tagqng_able */
11044 0, /* bios_scan */
11045 0, /* scam_tolerant */
11046 1, /* adapter_scsi_id */
11047 1, /* bios_boot_delay */
11048 1, /* scsi_reset_delay */
11049 1, /* bios_id_lun */
11050 1, /* termination */
11051 1, /* reserved1 */
11052 0, /* bios_ctrl */
11053 0, /* ultra_able */
11054 0, /* reserved2 */
11055 1, /* max_host_qng */
11056 1, /* max_dvc_qng */
11057 0, /* dvc_cntl */
11058 0, /* bug_fix */
11059 0, /* serial_number_word1 */
11060 0, /* serial_number_word2 */
11061 0, /* serial_number_word3 */
11062 0, /* check_sum */
11063 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11064 , /* oem_name[16] */
11065 0, /* dvc_err_code */
11066 0, /* adv_err_code */
11067 0, /* adv_err_addr */
11068 0, /* saved_dvc_err_code */
11069 0, /* saved_adv_err_code */
11070 0, /* saved_adv_err_addr */
11071 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011072};
11073
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011074static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011075 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11076 0x0000, /* 01 cfg_msw */
11077 0xFFFF, /* 02 disc_enable */
11078 0xFFFF, /* 03 wdtr_able */
11079 0x4444, /* 04 sdtr_speed1 */
11080 0xFFFF, /* 05 start_motor */
11081 0xFFFF, /* 06 tagqng_able */
11082 0xFFFF, /* 07 bios_scan */
11083 0, /* 08 scam_tolerant */
11084 7, /* 09 adapter_scsi_id */
11085 0, /* bios_boot_delay */
11086 3, /* 10 scsi_reset_delay */
11087 0, /* bios_id_lun */
11088 0, /* 11 termination_se */
11089 0, /* termination_lvd */
11090 0xFFE7, /* 12 bios_ctrl */
11091 0x4444, /* 13 sdtr_speed2 */
11092 0x4444, /* 14 sdtr_speed3 */
11093 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11094 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11095 0, /* 16 dvc_cntl */
11096 0x4444, /* 17 sdtr_speed4 */
11097 0, /* 18 serial_number_word1 */
11098 0, /* 19 serial_number_word2 */
11099 0, /* 20 serial_number_word3 */
11100 0, /* 21 check_sum */
11101 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11102 , /* 22-29 oem_name[16] */
11103 0, /* 30 dvc_err_code */
11104 0, /* 31 adv_err_code */
11105 0, /* 32 adv_err_addr */
11106 0, /* 33 saved_dvc_err_code */
11107 0, /* 34 saved_adv_err_code */
11108 0, /* 35 saved_adv_err_addr */
11109 0, /* 36 reserved */
11110 0, /* 37 reserved */
11111 0, /* 38 reserved */
11112 0, /* 39 reserved */
11113 0, /* 40 reserved */
11114 0, /* 41 reserved */
11115 0, /* 42 reserved */
11116 0, /* 43 reserved */
11117 0, /* 44 reserved */
11118 0, /* 45 reserved */
11119 0, /* 46 reserved */
11120 0, /* 47 reserved */
11121 0, /* 48 reserved */
11122 0, /* 49 reserved */
11123 0, /* 50 reserved */
11124 0, /* 51 reserved */
11125 0, /* 52 reserved */
11126 0, /* 53 reserved */
11127 0, /* 54 reserved */
11128 0, /* 55 reserved */
11129 0, /* 56 cisptr_lsw */
11130 0, /* 57 cisprt_msw */
11131 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11132 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
11133 0, /* 60 reserved */
11134 0, /* 61 reserved */
11135 0, /* 62 reserved */
11136 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011137};
11138
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011139static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011140 0, /* 00 cfg_lsw */
11141 0, /* 01 cfg_msw */
11142 0, /* 02 disc_enable */
11143 0, /* 03 wdtr_able */
11144 0, /* 04 sdtr_speed1 */
11145 0, /* 05 start_motor */
11146 0, /* 06 tagqng_able */
11147 0, /* 07 bios_scan */
11148 0, /* 08 scam_tolerant */
11149 1, /* 09 adapter_scsi_id */
11150 1, /* bios_boot_delay */
11151 1, /* 10 scsi_reset_delay */
11152 1, /* bios_id_lun */
11153 1, /* 11 termination_se */
11154 1, /* termination_lvd */
11155 0, /* 12 bios_ctrl */
11156 0, /* 13 sdtr_speed2 */
11157 0, /* 14 sdtr_speed3 */
11158 1, /* 15 max_host_qng */
11159 1, /* max_dvc_qng */
11160 0, /* 16 dvc_cntl */
11161 0, /* 17 sdtr_speed4 */
11162 0, /* 18 serial_number_word1 */
11163 0, /* 19 serial_number_word2 */
11164 0, /* 20 serial_number_word3 */
11165 0, /* 21 check_sum */
11166 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11167 , /* 22-29 oem_name[16] */
11168 0, /* 30 dvc_err_code */
11169 0, /* 31 adv_err_code */
11170 0, /* 32 adv_err_addr */
11171 0, /* 33 saved_dvc_err_code */
11172 0, /* 34 saved_adv_err_code */
11173 0, /* 35 saved_adv_err_addr */
11174 0, /* 36 reserved */
11175 0, /* 37 reserved */
11176 0, /* 38 reserved */
11177 0, /* 39 reserved */
11178 0, /* 40 reserved */
11179 0, /* 41 reserved */
11180 0, /* 42 reserved */
11181 0, /* 43 reserved */
11182 0, /* 44 reserved */
11183 0, /* 45 reserved */
11184 0, /* 46 reserved */
11185 0, /* 47 reserved */
11186 0, /* 48 reserved */
11187 0, /* 49 reserved */
11188 0, /* 50 reserved */
11189 0, /* 51 reserved */
11190 0, /* 52 reserved */
11191 0, /* 53 reserved */
11192 0, /* 54 reserved */
11193 0, /* 55 reserved */
11194 0, /* 56 cisptr_lsw */
11195 0, /* 57 cisprt_msw */
11196 0, /* 58 subsysvid */
11197 0, /* 59 subsysid */
11198 0, /* 60 reserved */
11199 0, /* 61 reserved */
11200 0, /* 62 reserved */
11201 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011202};
11203
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011204static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011205 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11206 0x0000, /* 01 cfg_msw */
11207 0xFFFF, /* 02 disc_enable */
11208 0xFFFF, /* 03 wdtr_able */
11209 0x5555, /* 04 sdtr_speed1 */
11210 0xFFFF, /* 05 start_motor */
11211 0xFFFF, /* 06 tagqng_able */
11212 0xFFFF, /* 07 bios_scan */
11213 0, /* 08 scam_tolerant */
11214 7, /* 09 adapter_scsi_id */
11215 0, /* bios_boot_delay */
11216 3, /* 10 scsi_reset_delay */
11217 0, /* bios_id_lun */
11218 0, /* 11 termination_se */
11219 0, /* termination_lvd */
11220 0xFFE7, /* 12 bios_ctrl */
11221 0x5555, /* 13 sdtr_speed2 */
11222 0x5555, /* 14 sdtr_speed3 */
11223 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11224 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11225 0, /* 16 dvc_cntl */
11226 0x5555, /* 17 sdtr_speed4 */
11227 0, /* 18 serial_number_word1 */
11228 0, /* 19 serial_number_word2 */
11229 0, /* 20 serial_number_word3 */
11230 0, /* 21 check_sum */
11231 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11232 , /* 22-29 oem_name[16] */
11233 0, /* 30 dvc_err_code */
11234 0, /* 31 adv_err_code */
11235 0, /* 32 adv_err_addr */
11236 0, /* 33 saved_dvc_err_code */
11237 0, /* 34 saved_adv_err_code */
11238 0, /* 35 saved_adv_err_addr */
11239 0, /* 36 reserved */
11240 0, /* 37 reserved */
11241 0, /* 38 reserved */
11242 0, /* 39 reserved */
11243 0, /* 40 reserved */
11244 0, /* 41 reserved */
11245 0, /* 42 reserved */
11246 0, /* 43 reserved */
11247 0, /* 44 reserved */
11248 0, /* 45 reserved */
11249 0, /* 46 reserved */
11250 0, /* 47 reserved */
11251 0, /* 48 reserved */
11252 0, /* 49 reserved */
11253 0, /* 50 reserved */
11254 0, /* 51 reserved */
11255 0, /* 52 reserved */
11256 0, /* 53 reserved */
11257 0, /* 54 reserved */
11258 0, /* 55 reserved */
11259 0, /* 56 cisptr_lsw */
11260 0, /* 57 cisprt_msw */
11261 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11262 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
11263 0, /* 60 reserved */
11264 0, /* 61 reserved */
11265 0, /* 62 reserved */
11266 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011267};
11268
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011269static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011270 0, /* 00 cfg_lsw */
11271 0, /* 01 cfg_msw */
11272 0, /* 02 disc_enable */
11273 0, /* 03 wdtr_able */
11274 0, /* 04 sdtr_speed1 */
11275 0, /* 05 start_motor */
11276 0, /* 06 tagqng_able */
11277 0, /* 07 bios_scan */
11278 0, /* 08 scam_tolerant */
11279 1, /* 09 adapter_scsi_id */
11280 1, /* bios_boot_delay */
11281 1, /* 10 scsi_reset_delay */
11282 1, /* bios_id_lun */
11283 1, /* 11 termination_se */
11284 1, /* termination_lvd */
11285 0, /* 12 bios_ctrl */
11286 0, /* 13 sdtr_speed2 */
11287 0, /* 14 sdtr_speed3 */
11288 1, /* 15 max_host_qng */
11289 1, /* max_dvc_qng */
11290 0, /* 16 dvc_cntl */
11291 0, /* 17 sdtr_speed4 */
11292 0, /* 18 serial_number_word1 */
11293 0, /* 19 serial_number_word2 */
11294 0, /* 20 serial_number_word3 */
11295 0, /* 21 check_sum */
11296 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11297 , /* 22-29 oem_name[16] */
11298 0, /* 30 dvc_err_code */
11299 0, /* 31 adv_err_code */
11300 0, /* 32 adv_err_addr */
11301 0, /* 33 saved_dvc_err_code */
11302 0, /* 34 saved_adv_err_code */
11303 0, /* 35 saved_adv_err_addr */
11304 0, /* 36 reserved */
11305 0, /* 37 reserved */
11306 0, /* 38 reserved */
11307 0, /* 39 reserved */
11308 0, /* 40 reserved */
11309 0, /* 41 reserved */
11310 0, /* 42 reserved */
11311 0, /* 43 reserved */
11312 0, /* 44 reserved */
11313 0, /* 45 reserved */
11314 0, /* 46 reserved */
11315 0, /* 47 reserved */
11316 0, /* 48 reserved */
11317 0, /* 49 reserved */
11318 0, /* 50 reserved */
11319 0, /* 51 reserved */
11320 0, /* 52 reserved */
11321 0, /* 53 reserved */
11322 0, /* 54 reserved */
11323 0, /* 55 reserved */
11324 0, /* 56 cisptr_lsw */
11325 0, /* 57 cisprt_msw */
11326 0, /* 58 subsysvid */
11327 0, /* 59 subsysid */
11328 0, /* 60 reserved */
11329 0, /* 61 reserved */
11330 0, /* 62 reserved */
11331 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011332};
11333
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011334#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -070011335/*
11336 * Initialize the ADV_DVC_VAR structure.
11337 *
11338 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11339 *
11340 * For a non-fatal error return a warning code. If there are no warnings
11341 * then 0 is returned.
11342 */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040011343static int __devinit
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011344AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011345{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011346 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011347 unsigned short warn_code = 0;
11348 AdvPortAddr iop_base = asc_dvc->iop_base;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011349 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011350 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011351
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011352 asc_dvc->err_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011353
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011354 /*
11355 * Save the state of the PCI Configuration Command Register
11356 * "Parity Error Response Control" Bit. If the bit is clear (0),
11357 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
11358 * DMA parity errors.
11359 */
11360 asc_dvc->cfg->control_flag = 0;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011361 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
11362 if ((cmd & PCI_COMMAND_PARITY) == 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011363 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011364
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011365 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
11366 ADV_LIB_VERSION_MINOR;
11367 asc_dvc->cfg->chip_version =
11368 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011369
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011370 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
11371 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
11372 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011374 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
11375 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
11376 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011377
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011378 /*
11379 * Reset the chip to start and allow register writes.
11380 */
11381 if (AdvFindSignature(iop_base) == 0) {
11382 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11383 return ADV_ERROR;
11384 } else {
11385 /*
11386 * The caller must set 'chip_type' to a valid setting.
11387 */
11388 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
11389 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
11390 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
11391 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
11392 return ADV_ERROR;
11393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011394
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011395 /*
11396 * Reset Chip.
11397 */
11398 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11399 ADV_CTRL_REG_CMD_RESET);
11400 DvcSleepMilliSecond(100);
11401 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11402 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011403
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011404 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011405 status = AdvInitFrom38C1600EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011406 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011407 status = AdvInitFrom38C0800EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011408 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011409 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011410 }
11411 warn_code |= status;
11412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011413
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011414 if (warn_code != 0) {
11415 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
11416 boardp->id, warn_code);
11417 }
11418
11419 if (asc_dvc->err_code) {
11420 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
11421 boardp->id, asc_dvc->err_code);
11422 }
11423
11424 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011425}
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011426#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070011427
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011428static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
11429{
11430 ADV_CARR_T *carrp;
11431 ADV_SDCNT buf_size;
11432 ADV_PADDR carr_paddr;
11433
11434 BUG_ON(!asc_dvc->carrier_buf);
11435
11436 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
11437 asc_dvc->carr_freelist = NULL;
11438 if (carrp == asc_dvc->carrier_buf) {
11439 buf_size = ADV_CARRIER_BUFSIZE;
11440 } else {
11441 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
11442 }
11443
11444 do {
11445 /* Get physical address of the carrier 'carrp'. */
11446 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
11447 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
11448 (uchar *)carrp,
11449 (ADV_SDCNT *)&contig_len,
11450 ADV_IS_CARRIER_FLAG));
11451
11452 buf_size -= sizeof(ADV_CARR_T);
11453
11454 /*
11455 * If the current carrier is not physically contiguous, then
11456 * maybe there was a page crossing. Try the next carrier
11457 * aligned start address.
11458 */
11459 if (contig_len < sizeof(ADV_CARR_T)) {
11460 carrp++;
11461 continue;
11462 }
11463
11464 carrp->carr_pa = carr_paddr;
11465 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
11466
11467 /*
11468 * Insert the carrier at the beginning of the freelist.
11469 */
11470 carrp->next_vpa =
11471 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
11472 asc_dvc->carr_freelist = carrp;
11473
11474 carrp++;
11475 } while (buf_size > 0);
11476}
11477
Linus Torvalds1da177e2005-04-16 15:20:36 -070011478/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011479 * Load the Microcode
11480 *
11481 * Write the microcode image to RISC memory starting at address 0.
11482 *
11483 * The microcode is stored compressed in the following format:
11484 *
11485 * 254 word (508 byte) table indexed by byte code followed
11486 * by the following byte codes:
11487 *
11488 * 1-Byte Code:
11489 * 00: Emit word 0 in table.
11490 * 01: Emit word 1 in table.
11491 * .
11492 * FD: Emit word 253 in table.
11493 *
11494 * Multi-Byte Code:
11495 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
11496 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
11497 *
11498 * Returns 0 or an error if the checksum doesn't match
11499 */
11500static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
11501 int memsize, int chksum)
11502{
11503 int i, j, end, len = 0;
11504 ADV_DCNT sum;
11505
11506 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11507
11508 for (i = 253 * 2; i < size; i++) {
11509 if (buf[i] == 0xff) {
11510 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
11511 for (j = 0; j < buf[i + 1]; j++) {
11512 AdvWriteWordAutoIncLram(iop_base, word);
11513 len += 2;
11514 }
11515 i += 3;
11516 } else if (buf[i] == 0xfe) {
11517 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
11518 AdvWriteWordAutoIncLram(iop_base, word);
11519 i += 2;
11520 len += 2;
11521 } else {
11522 unsigned char off = buf[i] * 2;
11523 unsigned short word = (buf[off + 1] << 8) | buf[off];
11524 AdvWriteWordAutoIncLram(iop_base, word);
11525 len += 2;
11526 }
11527 }
11528
11529 end = len;
11530
11531 while (len < memsize) {
11532 AdvWriteWordAutoIncLram(iop_base, 0);
11533 len += 2;
11534 }
11535
11536 /* Verify the microcode checksum. */
11537 sum = 0;
11538 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11539
11540 for (len = 0; len < end; len += 2) {
11541 sum += AdvReadWordAutoIncLram(iop_base);
11542 }
11543
11544 if (sum != chksum)
11545 return ASC_IERR_MCODE_CHKSUM;
11546
11547 return 0;
11548}
11549
11550/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070011551 * Initialize the ASC-3550.
11552 *
11553 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11554 *
11555 * For a non-fatal error return a warning code. If there are no warnings
11556 * then 0 is returned.
11557 *
11558 * Needed after initialization for error recovery.
11559 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011560static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011561{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011562 AdvPortAddr iop_base;
11563 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011564 int begin_addr;
11565 int end_addr;
11566 ushort code_sum;
11567 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011568 int i;
11569 ushort scsi_cfg1;
11570 uchar tid;
11571 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
11572 ushort wdtr_able = 0, sdtr_able, tagqng_able;
11573 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070011574
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011575 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011576 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011577 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011578
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011579 /*
11580 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
11581 */
11582 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011583 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011584 return ADV_ERROR;
11585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011586
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011587 warn_code = 0;
11588 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011589
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011590 /*
11591 * Save the RISC memory BIOS region before writing the microcode.
11592 * The BIOS may already be loaded and using its RISC LRAM region
11593 * so its region must be saved and restored.
11594 *
11595 * Note: This code makes the assumption, which is currently true,
11596 * that a chip reset does not clear RISC LRAM.
11597 */
11598 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11599 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11600 bios_mem[i]);
11601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011602
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011603 /*
11604 * Save current per TID negotiated values.
11605 */
11606 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
11607 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011608
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011609 bios_version =
11610 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
11611 major = (bios_version >> 12) & 0xF;
11612 minor = (bios_version >> 8) & 0xF;
11613 if (major < 3 || (major == 3 && minor == 1)) {
11614 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
11615 AdvReadWordLram(iop_base, 0x120, wdtr_able);
11616 } else {
11617 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11618 }
11619 }
11620 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11621 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
11622 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11623 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
11624 max_cmd[tid]);
11625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011626
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011627 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
11628 _adv_asc3550_size, ADV_3550_MEMSIZE,
11629 _adv_asc3550_chksum);
11630 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011631 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011632
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011633 /*
11634 * Restore the RISC memory BIOS region.
11635 */
11636 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11637 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11638 bios_mem[i]);
11639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011641 /*
11642 * Calculate and write the microcode code checksum to the microcode
11643 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
11644 */
11645 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
11646 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
11647 code_sum = 0;
11648 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
11649 for (word = begin_addr; word < end_addr; word += 2) {
11650 code_sum += AdvReadWordAutoIncLram(iop_base);
11651 }
11652 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011653
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011654 /*
11655 * Read and save microcode version and date.
11656 */
11657 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
11658 asc_dvc->cfg->mcode_date);
11659 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
11660 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011661
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011662 /*
11663 * Set the chip type to indicate the ASC3550.
11664 */
11665 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011666
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011667 /*
11668 * If the PCI Configuration Command Register "Parity Error Response
11669 * Control" Bit was clear (0), then set the microcode variable
11670 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
11671 * to ignore DMA parity errors.
11672 */
11673 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
11674 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11675 word |= CONTROL_FLAG_IGNORE_PERR;
11676 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011678
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011679 /*
11680 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
11681 * threshold of 128 bytes. This register is only accessible to the host.
11682 */
11683 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
11684 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011685
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011686 /*
11687 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040011688 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011689 * device reports it is capable of in Inquiry byte 7.
11690 *
11691 * If SCSI Bus Resets have been disabled, then directly set
11692 * SDTR and WDTR from the EEPROM configuration. This will allow
11693 * the BIOS and warm boot to work without a SCSI bus hang on
11694 * the Inquiry caused by host and target mismatched DTR values.
11695 * Without the SCSI Bus Reset, before an Inquiry a device can't
11696 * be assumed to be in Asynchronous, Narrow mode.
11697 */
11698 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
11699 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
11700 asc_dvc->wdtr_able);
11701 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
11702 asc_dvc->sdtr_able);
11703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011704
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011705 /*
11706 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
11707 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
11708 * bitmask. These values determine the maximum SDTR speed negotiated
11709 * with a device.
11710 *
11711 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
11712 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
11713 * without determining here whether the device supports SDTR.
11714 *
11715 * 4-bit speed SDTR speed name
11716 * =========== ===============
11717 * 0000b (0x0) SDTR disabled
11718 * 0001b (0x1) 5 Mhz
11719 * 0010b (0x2) 10 Mhz
11720 * 0011b (0x3) 20 Mhz (Ultra)
11721 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
11722 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
11723 * 0110b (0x6) Undefined
11724 * .
11725 * 1111b (0xF) Undefined
11726 */
11727 word = 0;
11728 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11729 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
11730 /* Set Ultra speed for TID 'tid'. */
11731 word |= (0x3 << (4 * (tid % 4)));
11732 } else {
11733 /* Set Fast speed for TID 'tid'. */
11734 word |= (0x2 << (4 * (tid % 4)));
11735 }
11736 if (tid == 3) { /* Check if done with sdtr_speed1. */
11737 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
11738 word = 0;
11739 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
11740 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
11741 word = 0;
11742 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
11743 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
11744 word = 0;
11745 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
11746 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
11747 /* End of loop. */
11748 }
11749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011750
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011751 /*
11752 * Set microcode operating variable for the disconnect per TID bitmask.
11753 */
11754 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
11755 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011756
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011757 /*
11758 * Set SCSI_CFG0 Microcode Default Value.
11759 *
11760 * The microcode will set the SCSI_CFG0 register using this value
11761 * after it is started below.
11762 */
11763 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
11764 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
11765 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011766
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011767 /*
11768 * Determine SCSI_CFG1 Microcode Default Value.
11769 *
11770 * The microcode will set the SCSI_CFG1 register using this value
11771 * after it is started below.
11772 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011773
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011774 /* Read current SCSI_CFG1 Register value. */
11775 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011776
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011777 /*
11778 * If all three connectors are in use, return an error.
11779 */
11780 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
11781 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
11782 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
11783 return ADV_ERROR;
11784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011785
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011786 /*
11787 * If the internal narrow cable is reversed all of the SCSI_CTRL
11788 * register signals will be set. Check for and return an error if
11789 * this condition is found.
11790 */
11791 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
11792 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
11793 return ADV_ERROR;
11794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011795
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011796 /*
11797 * If this is a differential board and a single-ended device
11798 * is attached to one of the connectors, return an error.
11799 */
11800 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
11801 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
11802 return ADV_ERROR;
11803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011804
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011805 /*
11806 * If automatic termination control is enabled, then set the
11807 * termination value based on a table listed in a_condor.h.
11808 *
11809 * If manual termination was specified with an EEPROM setting
11810 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
11811 * is ready to be 'ored' into SCSI_CFG1.
11812 */
11813 if (asc_dvc->cfg->termination == 0) {
11814 /*
11815 * The software always controls termination by setting TERM_CTL_SEL.
11816 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
11817 */
11818 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011819
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011820 switch (scsi_cfg1 & CABLE_DETECT) {
11821 /* TERM_CTL_H: on, TERM_CTL_L: on */
11822 case 0x3:
11823 case 0x7:
11824 case 0xB:
11825 case 0xD:
11826 case 0xE:
11827 case 0xF:
11828 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
11829 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011831 /* TERM_CTL_H: on, TERM_CTL_L: off */
11832 case 0x1:
11833 case 0x5:
11834 case 0x9:
11835 case 0xA:
11836 case 0xC:
11837 asc_dvc->cfg->termination |= TERM_CTL_H;
11838 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011839
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011840 /* TERM_CTL_H: off, TERM_CTL_L: off */
11841 case 0x2:
11842 case 0x6:
11843 break;
11844 }
11845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011847 /*
11848 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
11849 */
11850 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011851
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011852 /*
11853 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
11854 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
11855 * referenced, because the hardware internally inverts
11856 * the Termination High and Low bits if TERM_POL is set.
11857 */
11858 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011859
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011860 /*
11861 * Set SCSI_CFG1 Microcode Default Value
11862 *
11863 * Set filter value and possibly modified termination control
11864 * bits in the Microcode SCSI_CFG1 Register Value.
11865 *
11866 * The microcode will set the SCSI_CFG1 register using this value
11867 * after it is started below.
11868 */
11869 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
11870 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011871
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011872 /*
11873 * Set MEM_CFG Microcode Default Value
11874 *
11875 * The microcode will set the MEM_CFG register using this value
11876 * after it is started below.
11877 *
11878 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
11879 * are defined.
11880 *
11881 * ASC-3550 has 8KB internal memory.
11882 */
11883 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
11884 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011885
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011886 /*
11887 * Set SEL_MASK Microcode Default Value
11888 *
11889 * The microcode will set the SEL_MASK register using this value
11890 * after it is started below.
11891 */
11892 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
11893 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011894
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011895 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011897 /*
11898 * Set-up the Host->RISC Initiator Command Queue (ICQ).
11899 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011900
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011901 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
11902 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11903 return ADV_ERROR;
11904 }
11905 asc_dvc->carr_freelist = (ADV_CARR_T *)
11906 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011907
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011908 /*
11909 * The first command issued will be placed in the stopper carrier.
11910 */
11911 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011912
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011913 /*
11914 * Set RISC ICQ physical address start value.
11915 */
11916 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011917
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011918 /*
11919 * Set-up the RISC->Host Initiator Response Queue (IRQ).
11920 */
11921 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
11922 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11923 return ADV_ERROR;
11924 }
11925 asc_dvc->carr_freelist = (ADV_CARR_T *)
11926 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011927
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011928 /*
11929 * The first command completed by the RISC will be placed in
11930 * the stopper.
11931 *
11932 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
11933 * completed the RISC will set the ASC_RQ_STOPPER bit.
11934 */
11935 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011936
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011937 /*
11938 * Set RISC IRQ physical address start value.
11939 */
11940 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
11941 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011942
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011943 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
11944 (ADV_INTR_ENABLE_HOST_INTR |
11945 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011946
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011947 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
11948 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011949
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011950 /* finally, finally, gentlemen, start your engine */
11951 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011952
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011953 /*
11954 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
11955 * Resets should be performed. The RISC has to be running
11956 * to issue a SCSI Bus Reset.
11957 */
11958 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
11959 /*
11960 * If the BIOS Signature is present in memory, restore the
11961 * BIOS Handshake Configuration Table and do not perform
11962 * a SCSI Bus Reset.
11963 */
11964 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
11965 0x55AA) {
11966 /*
11967 * Restore per TID negotiated values.
11968 */
11969 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11970 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11971 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
11972 tagqng_able);
11973 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11974 AdvWriteByteLram(iop_base,
11975 ASC_MC_NUMBER_OF_MAX_CMD + tid,
11976 max_cmd[tid]);
11977 }
11978 } else {
11979 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
11980 warn_code = ASC_WARN_BUSRESET_ERROR;
11981 }
11982 }
11983 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011984
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011985 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011986}
11987
11988/*
11989 * Initialize the ASC-38C0800.
11990 *
11991 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11992 *
11993 * For a non-fatal error return a warning code. If there are no warnings
11994 * then 0 is returned.
11995 *
11996 * Needed after initialization for error recovery.
11997 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011998static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011999{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012000 AdvPortAddr iop_base;
12001 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012002 int begin_addr;
12003 int end_addr;
12004 ushort code_sum;
12005 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012006 int i;
12007 ushort scsi_cfg1;
12008 uchar byte;
12009 uchar tid;
12010 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12011 ushort wdtr_able, sdtr_able, tagqng_able;
12012 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012013
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012014 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012015 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012016 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012017
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012018 /*
12019 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
12020 */
12021 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
12022 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12023 return ADV_ERROR;
12024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012025
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012026 warn_code = 0;
12027 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012028
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012029 /*
12030 * Save the RISC memory BIOS region before writing the microcode.
12031 * The BIOS may already be loaded and using its RISC LRAM region
12032 * so its region must be saved and restored.
12033 *
12034 * Note: This code makes the assumption, which is currently true,
12035 * that a chip reset does not clear RISC LRAM.
12036 */
12037 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12038 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12039 bios_mem[i]);
12040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012041
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012042 /*
12043 * Save current per TID negotiated values.
12044 */
12045 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12046 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12047 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12048 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12049 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12050 max_cmd[tid]);
12051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012052
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012053 /*
12054 * RAM BIST (RAM Built-In Self Test)
12055 *
12056 * Address : I/O base + offset 0x38h register (byte).
12057 * Function: Bit 7-6(RW) : RAM mode
12058 * Normal Mode : 0x00
12059 * Pre-test Mode : 0x40
12060 * RAM Test Mode : 0x80
12061 * Bit 5 : unused
12062 * Bit 4(RO) : Done bit
12063 * Bit 3-0(RO) : Status
12064 * Host Error : 0x08
12065 * Int_RAM Error : 0x04
12066 * RISC Error : 0x02
12067 * SCSI Error : 0x01
12068 * No Error : 0x00
12069 *
12070 * Note: RAM BIST code should be put right here, before loading the
12071 * microcode and after saving the RISC memory BIOS region.
12072 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012073
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012074 /*
12075 * LRAM Pre-test
12076 *
12077 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12078 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12079 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12080 * to NORMAL_MODE, return an error too.
12081 */
12082 for (i = 0; i < 2; i++) {
12083 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12084 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12085 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12086 if ((byte & RAM_TEST_DONE) == 0
12087 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012088 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012089 return ADV_ERROR;
12090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012091
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012092 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12093 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12094 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12095 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012096 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012097 return ADV_ERROR;
12098 }
12099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012100
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012101 /*
12102 * LRAM Test - It takes about 1.5 ms to run through the test.
12103 *
12104 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12105 * If Done bit not set or Status not 0, save register byte, set the
12106 * err_code, and return an error.
12107 */
12108 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12109 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012111 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12112 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12113 /* Get here if Done bit not set or Status not 0. */
12114 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012115 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012116 return ADV_ERROR;
12117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012118
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012119 /* We need to reset back to normal mode after LRAM test passes. */
12120 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012121
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012122 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
12123 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
12124 _adv_asc38C0800_chksum);
12125 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012126 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012127
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012128 /*
12129 * Restore the RISC memory BIOS region.
12130 */
12131 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12132 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12133 bios_mem[i]);
12134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012135
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012136 /*
12137 * Calculate and write the microcode code checksum to the microcode
12138 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12139 */
12140 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12141 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12142 code_sum = 0;
12143 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12144 for (word = begin_addr; word < end_addr; word += 2) {
12145 code_sum += AdvReadWordAutoIncLram(iop_base);
12146 }
12147 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012148
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012149 /*
12150 * Read microcode version and date.
12151 */
12152 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12153 asc_dvc->cfg->mcode_date);
12154 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12155 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012156
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012157 /*
12158 * Set the chip type to indicate the ASC38C0800.
12159 */
12160 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012161
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012162 /*
12163 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12164 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12165 * cable detection and then we are able to read C_DET[3:0].
12166 *
12167 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12168 * Microcode Default Value' section below.
12169 */
12170 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12171 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12172 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012173
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012174 /*
12175 * If the PCI Configuration Command Register "Parity Error Response
12176 * Control" Bit was clear (0), then set the microcode variable
12177 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12178 * to ignore DMA parity errors.
12179 */
12180 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12181 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12182 word |= CONTROL_FLAG_IGNORE_PERR;
12183 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12184 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012185
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012186 /*
12187 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
12188 * bits for the default FIFO threshold.
12189 *
12190 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
12191 *
12192 * For DMA Errata #4 set the BC_THRESH_ENB bit.
12193 */
12194 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12195 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
12196 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012197
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012198 /*
12199 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012200 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012201 * device reports it is capable of in Inquiry byte 7.
12202 *
12203 * If SCSI Bus Resets have been disabled, then directly set
12204 * SDTR and WDTR from the EEPROM configuration. This will allow
12205 * the BIOS and warm boot to work without a SCSI bus hang on
12206 * the Inquiry caused by host and target mismatched DTR values.
12207 * Without the SCSI Bus Reset, before an Inquiry a device can't
12208 * be assumed to be in Asynchronous, Narrow mode.
12209 */
12210 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12211 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12212 asc_dvc->wdtr_able);
12213 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12214 asc_dvc->sdtr_able);
12215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012216
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012217 /*
12218 * Set microcode operating variables for DISC and SDTR_SPEED1,
12219 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12220 * configuration values.
12221 *
12222 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12223 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12224 * without determining here whether the device supports SDTR.
12225 */
12226 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12227 asc_dvc->cfg->disc_enable);
12228 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12229 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12230 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12231 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012232
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012233 /*
12234 * Set SCSI_CFG0 Microcode Default Value.
12235 *
12236 * The microcode will set the SCSI_CFG0 register using this value
12237 * after it is started below.
12238 */
12239 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12240 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12241 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012242
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012243 /*
12244 * Determine SCSI_CFG1 Microcode Default Value.
12245 *
12246 * The microcode will set the SCSI_CFG1 register using this value
12247 * after it is started below.
12248 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012249
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012250 /* Read current SCSI_CFG1 Register value. */
12251 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012252
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012253 /*
12254 * If the internal narrow cable is reversed all of the SCSI_CTRL
12255 * register signals will be set. Check for and return an error if
12256 * this condition is found.
12257 */
12258 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12259 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12260 return ADV_ERROR;
12261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012262
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012263 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012264 * All kind of combinations of devices attached to one of four
12265 * connectors are acceptable except HVD device attached. For example,
12266 * LVD device can be attached to SE connector while SE device attached
12267 * to LVD connector. If LVD device attached to SE connector, it only
12268 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012269 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012270 * If an HVD device is attached to one of LVD connectors, return an
12271 * error. However, there is no way to detect HVD device attached to
12272 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012273 */
12274 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012275 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012276 return ADV_ERROR;
12277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012278
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012279 /*
12280 * If either SE or LVD automatic termination control is enabled, then
12281 * set the termination value based on a table listed in a_condor.h.
12282 *
12283 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012284 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
12285 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012286 */
12287 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
12288 /* SE automatic termination control is enabled. */
12289 switch (scsi_cfg1 & C_DET_SE) {
12290 /* TERM_SE_HI: on, TERM_SE_LO: on */
12291 case 0x1:
12292 case 0x2:
12293 case 0x3:
12294 asc_dvc->cfg->termination |= TERM_SE;
12295 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012296
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012297 /* TERM_SE_HI: on, TERM_SE_LO: off */
12298 case 0x0:
12299 asc_dvc->cfg->termination |= TERM_SE_HI;
12300 break;
12301 }
12302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012303
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012304 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
12305 /* LVD automatic termination control is enabled. */
12306 switch (scsi_cfg1 & C_DET_LVD) {
12307 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
12308 case 0x4:
12309 case 0x8:
12310 case 0xC:
12311 asc_dvc->cfg->termination |= TERM_LVD;
12312 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012313
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012314 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
12315 case 0x0:
12316 break;
12317 }
12318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012319
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012320 /*
12321 * Clear any set TERM_SE and TERM_LVD bits.
12322 */
12323 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012324
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012325 /*
12326 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
12327 */
12328 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012329
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012330 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012331 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
12332 * bits and set possibly modified termination control bits in the
12333 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012334 */
12335 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012336
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012337 /*
12338 * Set SCSI_CFG1 Microcode Default Value
12339 *
12340 * Set possibly modified termination control and reset DIS_TERM_DRV
12341 * bits in the Microcode SCSI_CFG1 Register Value.
12342 *
12343 * The microcode will set the SCSI_CFG1 register using this value
12344 * after it is started below.
12345 */
12346 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012347
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012348 /*
12349 * Set MEM_CFG Microcode Default Value
12350 *
12351 * The microcode will set the MEM_CFG register using this value
12352 * after it is started below.
12353 *
12354 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12355 * are defined.
12356 *
12357 * ASC-38C0800 has 16KB internal memory.
12358 */
12359 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12360 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012362 /*
12363 * Set SEL_MASK Microcode Default Value
12364 *
12365 * The microcode will set the SEL_MASK register using this value
12366 * after it is started below.
12367 */
12368 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12369 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012370
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012371 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012372
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012373 /*
12374 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12375 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012376
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012377 if ((asc_dvc->icq_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->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012383
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012384 /*
12385 * The first command issued will be placed in the stopper carrier.
12386 */
12387 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012388
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012389 /*
12390 * Set RISC ICQ physical address start value.
12391 * carr_pa is LE, must be native before write
12392 */
12393 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012394
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012395 /*
12396 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12397 */
12398 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12399 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12400 return ADV_ERROR;
12401 }
12402 asc_dvc->carr_freelist = (ADV_CARR_T *)
12403 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012404
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012405 /*
12406 * The first command completed by the RISC will be placed in
12407 * the stopper.
12408 *
12409 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12410 * completed the RISC will set the ASC_RQ_STOPPER bit.
12411 */
12412 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012413
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012414 /*
12415 * Set RISC IRQ physical address start value.
12416 *
12417 * carr_pa is LE, must be native before write *
12418 */
12419 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12420 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012421
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012422 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12423 (ADV_INTR_ENABLE_HOST_INTR |
12424 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012425
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012426 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12427 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012428
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012429 /* finally, finally, gentlemen, start your engine */
12430 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012431
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012432 /*
12433 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12434 * Resets should be performed. The RISC has to be running
12435 * to issue a SCSI Bus Reset.
12436 */
12437 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12438 /*
12439 * If the BIOS Signature is present in memory, restore the
12440 * BIOS Handshake Configuration Table and do not perform
12441 * a SCSI Bus Reset.
12442 */
12443 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12444 0x55AA) {
12445 /*
12446 * Restore per TID negotiated values.
12447 */
12448 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12449 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12450 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12451 tagqng_able);
12452 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12453 AdvWriteByteLram(iop_base,
12454 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12455 max_cmd[tid]);
12456 }
12457 } else {
12458 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12459 warn_code = ASC_WARN_BUSRESET_ERROR;
12460 }
12461 }
12462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012463
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012464 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012465}
12466
12467/*
12468 * Initialize the ASC-38C1600.
12469 *
12470 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
12471 *
12472 * For a non-fatal error return a warning code. If there are no warnings
12473 * then 0 is returned.
12474 *
12475 * Needed after initialization for error recovery.
12476 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012477static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012478{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012479 AdvPortAddr iop_base;
12480 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012481 int begin_addr;
12482 int end_addr;
12483 ushort code_sum;
12484 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012485 int i;
12486 ushort scsi_cfg1;
12487 uchar byte;
12488 uchar tid;
12489 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12490 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
12491 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012492
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012493 /* If there is already an error, don't continue. */
12494 if (asc_dvc->err_code != 0) {
12495 return ADV_ERROR;
12496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012497
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012498 /*
12499 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
12500 */
12501 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
12502 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12503 return ADV_ERROR;
12504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012505
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012506 warn_code = 0;
12507 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012508
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012509 /*
12510 * Save the RISC memory BIOS region before writing the microcode.
12511 * The BIOS may already be loaded and using its RISC LRAM region
12512 * so its region must be saved and restored.
12513 *
12514 * Note: This code makes the assumption, which is currently true,
12515 * that a chip reset does not clear RISC LRAM.
12516 */
12517 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12518 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12519 bios_mem[i]);
12520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012521
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012522 /*
12523 * Save current per TID negotiated values.
12524 */
12525 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12526 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12527 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12528 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12529 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12530 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12531 max_cmd[tid]);
12532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012533
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012534 /*
12535 * RAM BIST (Built-In Self Test)
12536 *
12537 * Address : I/O base + offset 0x38h register (byte).
12538 * Function: Bit 7-6(RW) : RAM mode
12539 * Normal Mode : 0x00
12540 * Pre-test Mode : 0x40
12541 * RAM Test Mode : 0x80
12542 * Bit 5 : unused
12543 * Bit 4(RO) : Done bit
12544 * Bit 3-0(RO) : Status
12545 * Host Error : 0x08
12546 * Int_RAM Error : 0x04
12547 * RISC Error : 0x02
12548 * SCSI Error : 0x01
12549 * No Error : 0x00
12550 *
12551 * Note: RAM BIST code should be put right here, before loading the
12552 * microcode and after saving the RISC memory BIOS region.
12553 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012554
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012555 /*
12556 * LRAM Pre-test
12557 *
12558 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12559 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12560 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12561 * to NORMAL_MODE, return an error too.
12562 */
12563 for (i = 0; i < 2; i++) {
12564 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12565 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12566 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12567 if ((byte & RAM_TEST_DONE) == 0
12568 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012569 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012570 return ADV_ERROR;
12571 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012572
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012573 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12574 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12575 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12576 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012577 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012578 return ADV_ERROR;
12579 }
12580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012581
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012582 /*
12583 * LRAM Test - It takes about 1.5 ms to run through the test.
12584 *
12585 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12586 * If Done bit not set or Status not 0, save register byte, set the
12587 * err_code, and return an error.
12588 */
12589 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12590 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012591
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012592 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12593 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12594 /* Get here if Done bit not set or Status not 0. */
12595 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012596 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012597 return ADV_ERROR;
12598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012599
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012600 /* We need to reset back to normal mode after LRAM test passes. */
12601 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012602
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012603 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
12604 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
12605 _adv_asc38C1600_chksum);
12606 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012607 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012608
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012609 /*
12610 * Restore the RISC memory BIOS region.
12611 */
12612 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12613 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12614 bios_mem[i]);
12615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012616
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012617 /*
12618 * Calculate and write the microcode code checksum to the microcode
12619 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12620 */
12621 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12622 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12623 code_sum = 0;
12624 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12625 for (word = begin_addr; word < end_addr; word += 2) {
12626 code_sum += AdvReadWordAutoIncLram(iop_base);
12627 }
12628 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012629
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012630 /*
12631 * Read microcode version and date.
12632 */
12633 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12634 asc_dvc->cfg->mcode_date);
12635 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12636 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012637
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012638 /*
12639 * Set the chip type to indicate the ASC38C1600.
12640 */
12641 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012642
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012643 /*
12644 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12645 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12646 * cable detection and then we are able to read C_DET[3:0].
12647 *
12648 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12649 * Microcode Default Value' section below.
12650 */
12651 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12652 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12653 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012654
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012655 /*
12656 * If the PCI Configuration Command Register "Parity Error Response
12657 * Control" Bit was clear (0), then set the microcode variable
12658 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12659 * to ignore DMA parity errors.
12660 */
12661 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12662 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12663 word |= CONTROL_FLAG_IGNORE_PERR;
12664 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012666
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012667 /*
12668 * If the BIOS control flag AIPP (Asynchronous Information
12669 * Phase Protection) disable bit is not set, then set the firmware
12670 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
12671 * AIPP checking and encoding.
12672 */
12673 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
12674 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12675 word |= CONTROL_FLAG_ENABLE_AIPP;
12676 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012678
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012679 /*
12680 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
12681 * and START_CTL_TH [3:2].
12682 */
12683 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12684 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012685
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012686 /*
12687 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012688 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012689 * device reports it is capable of in Inquiry byte 7.
12690 *
12691 * If SCSI Bus Resets have been disabled, then directly set
12692 * SDTR and WDTR from the EEPROM configuration. This will allow
12693 * the BIOS and warm boot to work without a SCSI bus hang on
12694 * the Inquiry caused by host and target mismatched DTR values.
12695 * Without the SCSI Bus Reset, before an Inquiry a device can't
12696 * be assumed to be in Asynchronous, Narrow mode.
12697 */
12698 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12699 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12700 asc_dvc->wdtr_able);
12701 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12702 asc_dvc->sdtr_able);
12703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012704
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012705 /*
12706 * Set microcode operating variables for DISC and SDTR_SPEED1,
12707 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12708 * configuration values.
12709 *
12710 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12711 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12712 * without determining here whether the device supports SDTR.
12713 */
12714 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12715 asc_dvc->cfg->disc_enable);
12716 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12717 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12718 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12719 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012720
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012721 /*
12722 * Set SCSI_CFG0 Microcode Default Value.
12723 *
12724 * The microcode will set the SCSI_CFG0 register using this value
12725 * after it is started below.
12726 */
12727 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12728 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12729 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012730
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012731 /*
12732 * Calculate SCSI_CFG1 Microcode Default Value.
12733 *
12734 * The microcode will set the SCSI_CFG1 register using this value
12735 * after it is started below.
12736 *
12737 * Each ASC-38C1600 function has only two cable detect bits.
12738 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
12739 */
12740 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012741
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012742 /*
12743 * If the cable is reversed all of the SCSI_CTRL register signals
12744 * will be set. Check for and return an error if this condition is
12745 * found.
12746 */
12747 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12748 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12749 return ADV_ERROR;
12750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012751
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012752 /*
12753 * Each ASC-38C1600 function has two connectors. Only an HVD device
12754 * can not be connected to either connector. An LVD device or SE device
12755 * may be connected to either connecor. If an SE device is connected,
12756 * then at most Ultra speed (20 Mhz) can be used on both connectors.
12757 *
12758 * If an HVD device is attached, return an error.
12759 */
12760 if (scsi_cfg1 & HVD) {
12761 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
12762 return ADV_ERROR;
12763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012764
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012765 /*
12766 * Each function in the ASC-38C1600 uses only the SE cable detect and
12767 * termination because there are two connectors for each function. Each
12768 * function may use either LVD or SE mode. Corresponding the SE automatic
12769 * termination control EEPROM bits are used for each function. Each
12770 * function has its own EEPROM. If SE automatic control is enabled for
12771 * the function, then set the termination value based on a table listed
12772 * in a_condor.h.
12773 *
12774 * If manual termination is specified in the EEPROM for the function,
12775 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
12776 * ready to be 'ored' into SCSI_CFG1.
12777 */
12778 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012779 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012780 /* SE automatic termination control is enabled. */
12781 switch (scsi_cfg1 & C_DET_SE) {
12782 /* TERM_SE_HI: on, TERM_SE_LO: on */
12783 case 0x1:
12784 case 0x2:
12785 case 0x3:
12786 asc_dvc->cfg->termination |= TERM_SE;
12787 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012788
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012789 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012790 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012791 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
12792 } else {
12793 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
12794 asc_dvc->cfg->termination |= TERM_SE_HI;
12795 }
12796 break;
12797 }
12798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012799
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012800 /*
12801 * Clear any set TERM_SE bits.
12802 */
12803 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012804
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012805 /*
12806 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
12807 */
12808 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012809
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012810 /*
12811 * Clear Big Endian and Terminator Polarity bits and set possibly
12812 * modified termination control bits in the Microcode SCSI_CFG1
12813 * Register Value.
12814 *
12815 * Big Endian bit is not used even on big endian machines.
12816 */
12817 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012818
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012819 /*
12820 * Set SCSI_CFG1 Microcode Default Value
12821 *
12822 * Set possibly modified termination control bits in the Microcode
12823 * SCSI_CFG1 Register Value.
12824 *
12825 * The microcode will set the SCSI_CFG1 register using this value
12826 * after it is started below.
12827 */
12828 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012829
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012830 /*
12831 * Set MEM_CFG Microcode Default Value
12832 *
12833 * The microcode will set the MEM_CFG register using this value
12834 * after it is started below.
12835 *
12836 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12837 * are defined.
12838 *
12839 * ASC-38C1600 has 32KB internal memory.
12840 *
12841 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
12842 * out a special 16K Adv Library and Microcode version. After the issue
12843 * resolved, we should turn back to the 32K support. Both a_condor.h and
12844 * mcode.sas files also need to be updated.
12845 *
12846 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12847 * BIOS_EN | RAM_SZ_32KB);
12848 */
12849 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12850 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012851
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012852 /*
12853 * Set SEL_MASK Microcode Default Value
12854 *
12855 * The microcode will set the SEL_MASK register using this value
12856 * after it is started below.
12857 */
12858 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12859 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012860
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012861 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012862
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012863 /*
12864 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12865 */
12866 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12867 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12868 return ADV_ERROR;
12869 }
12870 asc_dvc->carr_freelist = (ADV_CARR_T *)
12871 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012872
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012873 /*
12874 * The first command issued will be placed in the stopper carrier.
12875 */
12876 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012877
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012878 /*
12879 * Set RISC ICQ physical address start value. Initialize the
12880 * COMMA register to the same value otherwise the RISC will
12881 * prematurely detect a command is available.
12882 */
12883 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
12884 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
12885 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012886
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012887 /*
12888 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12889 */
12890 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12891 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12892 return ADV_ERROR;
12893 }
12894 asc_dvc->carr_freelist = (ADV_CARR_T *)
12895 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012897 /*
12898 * The first command completed by the RISC will be placed in
12899 * the stopper.
12900 *
12901 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12902 * completed the RISC will set the ASC_RQ_STOPPER bit.
12903 */
12904 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012905
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012906 /*
12907 * Set RISC IRQ physical address start value.
12908 */
12909 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12910 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012911
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012912 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12913 (ADV_INTR_ENABLE_HOST_INTR |
12914 ADV_INTR_ENABLE_GLOBAL_INTR));
12915 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12916 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012917
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012918 /* finally, finally, gentlemen, start your engine */
12919 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012920
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012921 /*
12922 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12923 * Resets should be performed. The RISC has to be running
12924 * to issue a SCSI Bus Reset.
12925 */
12926 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12927 /*
12928 * If the BIOS Signature is present in memory, restore the
12929 * per TID microcode operating variables.
12930 */
12931 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12932 0x55AA) {
12933 /*
12934 * Restore per TID negotiated values.
12935 */
12936 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12937 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12938 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12939 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12940 tagqng_able);
12941 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12942 AdvWriteByteLram(iop_base,
12943 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12944 max_cmd[tid]);
12945 }
12946 } else {
12947 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12948 warn_code = ASC_WARN_BUSRESET_ERROR;
12949 }
12950 }
12951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012952
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012953 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012954}
12955
12956/*
12957 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12958 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12959 * all of this is done.
12960 *
12961 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12962 *
12963 * For a non-fatal error return a warning code. If there are no warnings
12964 * then 0 is returned.
12965 *
12966 * Note: Chip is stopped on entry.
12967 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012968static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012969{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012970 AdvPortAddr iop_base;
12971 ushort warn_code;
12972 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012973
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012974 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012975
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012976 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012977
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012978 /*
12979 * Read the board's EEPROM configuration.
12980 *
12981 * Set default values if a bad checksum is found.
12982 */
12983 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12984 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012985
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012986 /*
12987 * Set EEPROM default values.
12988 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012989 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12990 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012991
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012992 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012993 * Assume the 6 byte board serial number that was read from
12994 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012995 */
12996 eep_config.serial_number_word3 =
12997 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012998
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012999 eep_config.serial_number_word2 =
13000 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013001
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013002 eep_config.serial_number_word1 =
13003 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013004
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013005 AdvSet3550EEPConfig(iop_base, &eep_config);
13006 }
13007 /*
13008 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13009 * EEPROM configuration that was read.
13010 *
13011 * This is the mapping of EEPROM fields to Adv Library fields.
13012 */
13013 asc_dvc->wdtr_able = eep_config.wdtr_able;
13014 asc_dvc->sdtr_able = eep_config.sdtr_able;
13015 asc_dvc->ultra_able = eep_config.ultra_able;
13016 asc_dvc->tagqng_able = eep_config.tagqng_able;
13017 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13018 asc_dvc->max_host_qng = eep_config.max_host_qng;
13019 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13020 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13021 asc_dvc->start_motor = eep_config.start_motor;
13022 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13023 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13024 asc_dvc->no_scam = eep_config.scam_tolerant;
13025 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13026 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13027 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013028
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013029 /*
13030 * Set the host maximum queuing (max. 253, min. 16) and the per device
13031 * maximum queuing (max. 63, min. 4).
13032 */
13033 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13034 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13035 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13036 /* If the value is zero, assume it is uninitialized. */
13037 if (eep_config.max_host_qng == 0) {
13038 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13039 } else {
13040 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13041 }
13042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013043
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013044 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13045 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13046 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13047 /* If the value is zero, assume it is uninitialized. */
13048 if (eep_config.max_dvc_qng == 0) {
13049 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13050 } else {
13051 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13052 }
13053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013054
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013055 /*
13056 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13057 * set 'max_dvc_qng' to 'max_host_qng'.
13058 */
13059 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13060 eep_config.max_dvc_qng = eep_config.max_host_qng;
13061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013062
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013063 /*
13064 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13065 * values based on possibly adjusted EEPROM values.
13066 */
13067 asc_dvc->max_host_qng = eep_config.max_host_qng;
13068 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013069
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013070 /*
13071 * If the EEPROM 'termination' field is set to automatic (0), then set
13072 * the ADV_DVC_CFG 'termination' field to automatic also.
13073 *
13074 * If the termination is specified with a non-zero 'termination'
13075 * value check that a legal value is set and set the ADV_DVC_CFG
13076 * 'termination' field appropriately.
13077 */
13078 if (eep_config.termination == 0) {
13079 asc_dvc->cfg->termination = 0; /* auto termination */
13080 } else {
13081 /* Enable manual control with low off / high off. */
13082 if (eep_config.termination == 1) {
13083 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013084
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013085 /* Enable manual control with low off / high on. */
13086 } else if (eep_config.termination == 2) {
13087 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013088
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013089 /* Enable manual control with low on / high on. */
13090 } else if (eep_config.termination == 3) {
13091 asc_dvc->cfg->termination =
13092 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
13093 } else {
13094 /*
13095 * The EEPROM 'termination' field contains a bad value. Use
13096 * automatic termination instead.
13097 */
13098 asc_dvc->cfg->termination = 0;
13099 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13100 }
13101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013102
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013103 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013104}
13105
13106/*
13107 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13108 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13109 * all of this is done.
13110 *
13111 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13112 *
13113 * For a non-fatal error return a warning code. If there are no warnings
13114 * then 0 is returned.
13115 *
13116 * Note: Chip is stopped on entry.
13117 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013118static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013119{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013120 AdvPortAddr iop_base;
13121 ushort warn_code;
13122 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013123 uchar tid, termination;
13124 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013125
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013126 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013127
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013128 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013129
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013130 /*
13131 * Read the board's EEPROM configuration.
13132 *
13133 * Set default values if a bad checksum is found.
13134 */
13135 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13136 eep_config.check_sum) {
13137 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013138
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013139 /*
13140 * Set EEPROM default values.
13141 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013142 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13143 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013144
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013145 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013146 * Assume the 6 byte board serial number that was read from
13147 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013148 */
13149 eep_config.serial_number_word3 =
13150 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013151
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013152 eep_config.serial_number_word2 =
13153 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013154
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013155 eep_config.serial_number_word1 =
13156 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013157
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013158 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13159 }
13160 /*
13161 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13162 * EEPROM configuration that was read.
13163 *
13164 * This is the mapping of EEPROM fields to Adv Library fields.
13165 */
13166 asc_dvc->wdtr_able = eep_config.wdtr_able;
13167 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13168 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13169 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13170 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13171 asc_dvc->tagqng_able = eep_config.tagqng_able;
13172 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13173 asc_dvc->max_host_qng = eep_config.max_host_qng;
13174 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13175 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13176 asc_dvc->start_motor = eep_config.start_motor;
13177 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13178 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13179 asc_dvc->no_scam = eep_config.scam_tolerant;
13180 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13181 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13182 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013183
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013184 /*
13185 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13186 * are set, then set an 'sdtr_able' bit for it.
13187 */
13188 asc_dvc->sdtr_able = 0;
13189 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13190 if (tid == 0) {
13191 sdtr_speed = asc_dvc->sdtr_speed1;
13192 } else if (tid == 4) {
13193 sdtr_speed = asc_dvc->sdtr_speed2;
13194 } else if (tid == 8) {
13195 sdtr_speed = asc_dvc->sdtr_speed3;
13196 } else if (tid == 12) {
13197 sdtr_speed = asc_dvc->sdtr_speed4;
13198 }
13199 if (sdtr_speed & ADV_MAX_TID) {
13200 asc_dvc->sdtr_able |= (1 << tid);
13201 }
13202 sdtr_speed >>= 4;
13203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013204
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013205 /*
13206 * Set the host maximum queuing (max. 253, min. 16) and the per device
13207 * maximum queuing (max. 63, min. 4).
13208 */
13209 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13210 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13211 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13212 /* If the value is zero, assume it is uninitialized. */
13213 if (eep_config.max_host_qng == 0) {
13214 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13215 } else {
13216 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13217 }
13218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013219
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013220 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13221 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13222 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13223 /* If the value is zero, assume it is uninitialized. */
13224 if (eep_config.max_dvc_qng == 0) {
13225 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13226 } else {
13227 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13228 }
13229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013230
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013231 /*
13232 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13233 * set 'max_dvc_qng' to 'max_host_qng'.
13234 */
13235 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13236 eep_config.max_dvc_qng = eep_config.max_host_qng;
13237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013238
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013239 /*
13240 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13241 * values based on possibly adjusted EEPROM values.
13242 */
13243 asc_dvc->max_host_qng = eep_config.max_host_qng;
13244 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013245
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013246 /*
13247 * If the EEPROM 'termination' field is set to automatic (0), then set
13248 * the ADV_DVC_CFG 'termination' field to automatic also.
13249 *
13250 * If the termination is specified with a non-zero 'termination'
13251 * value check that a legal value is set and set the ADV_DVC_CFG
13252 * 'termination' field appropriately.
13253 */
13254 if (eep_config.termination_se == 0) {
13255 termination = 0; /* auto termination for SE */
13256 } else {
13257 /* Enable manual control with low off / high off. */
13258 if (eep_config.termination_se == 1) {
13259 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013260
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013261 /* Enable manual control with low off / high on. */
13262 } else if (eep_config.termination_se == 2) {
13263 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013264
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013265 /* Enable manual control with low on / high on. */
13266 } else if (eep_config.termination_se == 3) {
13267 termination = TERM_SE;
13268 } else {
13269 /*
13270 * The EEPROM 'termination_se' field contains a bad value.
13271 * Use automatic termination instead.
13272 */
13273 termination = 0;
13274 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13275 }
13276 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013277
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013278 if (eep_config.termination_lvd == 0) {
13279 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13280 } else {
13281 /* Enable manual control with low off / high off. */
13282 if (eep_config.termination_lvd == 1) {
13283 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013284
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013285 /* Enable manual control with low off / high on. */
13286 } else if (eep_config.termination_lvd == 2) {
13287 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013288
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013289 /* Enable manual control with low on / high on. */
13290 } else if (eep_config.termination_lvd == 3) {
13291 asc_dvc->cfg->termination = termination | TERM_LVD;
13292 } else {
13293 /*
13294 * The EEPROM 'termination_lvd' field contains a bad value.
13295 * Use automatic termination instead.
13296 */
13297 asc_dvc->cfg->termination = termination;
13298 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13299 }
13300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013301
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013302 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013303}
13304
13305/*
13306 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13307 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13308 * all of this is done.
13309 *
13310 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13311 *
13312 * For a non-fatal error return a warning code. If there are no warnings
13313 * then 0 is returned.
13314 *
13315 * Note: Chip is stopped on entry.
13316 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013317static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013318{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013319 AdvPortAddr iop_base;
13320 ushort warn_code;
13321 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013322 uchar tid, termination;
13323 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013324
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013325 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013326
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013327 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013328
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013329 /*
13330 * Read the board's EEPROM configuration.
13331 *
13332 * Set default values if a bad checksum is found.
13333 */
13334 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13335 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013336 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013337 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013338
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013339 /*
13340 * Set EEPROM default values.
13341 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013342 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13343 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013344
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013345 if (PCI_FUNC(pdev->devfn) != 0) {
13346 u8 ints;
13347 /*
13348 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13349 * and old Mac system booting problem. The Expansion
13350 * ROM must be disabled in Function 1 for these systems
13351 */
13352 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13353 /*
13354 * Clear the INTAB (bit 11) if the GPIO 0 input
13355 * indicates the Function 1 interrupt line is wired
13356 * to INTB.
13357 *
13358 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13359 * 1 - Function 1 interrupt line wired to INT A.
13360 * 0 - Function 1 interrupt line wired to INT B.
13361 *
13362 * Note: Function 0 is always wired to INTA.
13363 * Put all 5 GPIO bits in input mode and then read
13364 * their input values.
13365 */
13366 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13367 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13368 if ((ints & 0x01) == 0)
13369 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013371
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013372 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013373 * Assume the 6 byte board serial number that was read from
13374 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013375 */
13376 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013377 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013378 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013379 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013380 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013381 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013382
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013383 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013385
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013386 /*
13387 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13388 * EEPROM configuration that was read.
13389 *
13390 * This is the mapping of EEPROM fields to Adv Library fields.
13391 */
13392 asc_dvc->wdtr_able = eep_config.wdtr_able;
13393 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13394 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13395 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13396 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13397 asc_dvc->ppr_able = 0;
13398 asc_dvc->tagqng_able = eep_config.tagqng_able;
13399 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13400 asc_dvc->max_host_qng = eep_config.max_host_qng;
13401 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13402 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13403 asc_dvc->start_motor = eep_config.start_motor;
13404 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13405 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13406 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013407
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013408 /*
13409 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13410 * are set, then set an 'sdtr_able' bit for it.
13411 */
13412 asc_dvc->sdtr_able = 0;
13413 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13414 if (tid == 0) {
13415 sdtr_speed = asc_dvc->sdtr_speed1;
13416 } else if (tid == 4) {
13417 sdtr_speed = asc_dvc->sdtr_speed2;
13418 } else if (tid == 8) {
13419 sdtr_speed = asc_dvc->sdtr_speed3;
13420 } else if (tid == 12) {
13421 sdtr_speed = asc_dvc->sdtr_speed4;
13422 }
13423 if (sdtr_speed & ASC_MAX_TID) {
13424 asc_dvc->sdtr_able |= (1 << tid);
13425 }
13426 sdtr_speed >>= 4;
13427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013428
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013429 /*
13430 * Set the host maximum queuing (max. 253, min. 16) and the per device
13431 * maximum queuing (max. 63, min. 4).
13432 */
13433 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13434 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13435 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13436 /* If the value is zero, assume it is uninitialized. */
13437 if (eep_config.max_host_qng == 0) {
13438 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13439 } else {
13440 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13441 }
13442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013443
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013444 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13445 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13446 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13447 /* If the value is zero, assume it is uninitialized. */
13448 if (eep_config.max_dvc_qng == 0) {
13449 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13450 } else {
13451 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13452 }
13453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013454
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013455 /*
13456 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13457 * set 'max_dvc_qng' to 'max_host_qng'.
13458 */
13459 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13460 eep_config.max_dvc_qng = eep_config.max_host_qng;
13461 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013462
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013463 /*
13464 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13465 * values based on possibly adjusted EEPROM values.
13466 */
13467 asc_dvc->max_host_qng = eep_config.max_host_qng;
13468 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013469
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013470 /*
13471 * If the EEPROM 'termination' field is set to automatic (0), then set
13472 * the ASC_DVC_CFG 'termination' field to automatic also.
13473 *
13474 * If the termination is specified with a non-zero 'termination'
13475 * value check that a legal value is set and set the ASC_DVC_CFG
13476 * 'termination' field appropriately.
13477 */
13478 if (eep_config.termination_se == 0) {
13479 termination = 0; /* auto termination for SE */
13480 } else {
13481 /* Enable manual control with low off / high off. */
13482 if (eep_config.termination_se == 1) {
13483 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013484
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013485 /* Enable manual control with low off / high on. */
13486 } else if (eep_config.termination_se == 2) {
13487 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013488
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013489 /* Enable manual control with low on / high on. */
13490 } else if (eep_config.termination_se == 3) {
13491 termination = TERM_SE;
13492 } else {
13493 /*
13494 * The EEPROM 'termination_se' field contains a bad value.
13495 * Use automatic termination instead.
13496 */
13497 termination = 0;
13498 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13499 }
13500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013501
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013502 if (eep_config.termination_lvd == 0) {
13503 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13504 } else {
13505 /* Enable manual control with low off / high off. */
13506 if (eep_config.termination_lvd == 1) {
13507 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013508
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013509 /* Enable manual control with low off / high on. */
13510 } else if (eep_config.termination_lvd == 2) {
13511 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013512
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013513 /* Enable manual control with low on / high on. */
13514 } else if (eep_config.termination_lvd == 3) {
13515 asc_dvc->cfg->termination = termination | TERM_LVD;
13516 } else {
13517 /*
13518 * The EEPROM 'termination_lvd' field contains a bad value.
13519 * Use automatic termination instead.
13520 */
13521 asc_dvc->cfg->termination = termination;
13522 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13523 }
13524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013525
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013526 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013527}
13528
13529/*
13530 * Read EEPROM configuration into the specified buffer.
13531 *
13532 * Return a checksum based on the EEPROM configuration read.
13533 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013534static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013535AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13536{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013537 ushort wval, chksum;
13538 ushort *wbuf;
13539 int eep_addr;
13540 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013541
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013542 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13543 wbuf = (ushort *)cfg_buf;
13544 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013545
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013546 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13547 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13548 wval = AdvReadEEPWord(iop_base, eep_addr);
13549 chksum += wval; /* Checksum is calculated from word values. */
13550 if (*charfields++) {
13551 *wbuf = le16_to_cpu(wval);
13552 } else {
13553 *wbuf = wval;
13554 }
13555 }
13556 /* Read checksum word. */
13557 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13558 wbuf++;
13559 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013560
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013561 /* Read rest of EEPROM not covered by the checksum. */
13562 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13563 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13564 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13565 if (*charfields++) {
13566 *wbuf = le16_to_cpu(*wbuf);
13567 }
13568 }
13569 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013570}
13571
13572/*
13573 * Read EEPROM configuration into the specified buffer.
13574 *
13575 * Return a checksum based on the EEPROM configuration read.
13576 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013577static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013578AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013579{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013580 ushort wval, chksum;
13581 ushort *wbuf;
13582 int eep_addr;
13583 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013584
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013585 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13586 wbuf = (ushort *)cfg_buf;
13587 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013588
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013589 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13590 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13591 wval = AdvReadEEPWord(iop_base, eep_addr);
13592 chksum += wval; /* Checksum is calculated from word values. */
13593 if (*charfields++) {
13594 *wbuf = le16_to_cpu(wval);
13595 } else {
13596 *wbuf = wval;
13597 }
13598 }
13599 /* Read checksum word. */
13600 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13601 wbuf++;
13602 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013603
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013604 /* Read rest of EEPROM not covered by the checksum. */
13605 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13606 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13607 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13608 if (*charfields++) {
13609 *wbuf = le16_to_cpu(*wbuf);
13610 }
13611 }
13612 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013613}
13614
13615/*
13616 * Read EEPROM configuration into the specified buffer.
13617 *
13618 * Return a checksum based on the EEPROM configuration read.
13619 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013620static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013621AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013622{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013623 ushort wval, chksum;
13624 ushort *wbuf;
13625 int eep_addr;
13626 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013627
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013628 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13629 wbuf = (ushort *)cfg_buf;
13630 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013631
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013632 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13633 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13634 wval = AdvReadEEPWord(iop_base, eep_addr);
13635 chksum += wval; /* Checksum is calculated from word values. */
13636 if (*charfields++) {
13637 *wbuf = le16_to_cpu(wval);
13638 } else {
13639 *wbuf = wval;
13640 }
13641 }
13642 /* Read checksum word. */
13643 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13644 wbuf++;
13645 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013646
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013647 /* Read rest of EEPROM not covered by the checksum. */
13648 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13649 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13650 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13651 if (*charfields++) {
13652 *wbuf = le16_to_cpu(*wbuf);
13653 }
13654 }
13655 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013656}
13657
13658/*
13659 * Read the EEPROM from specified location
13660 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013661static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013662{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013663 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13664 ASC_EEP_CMD_READ | eep_word_addr);
13665 AdvWaitEEPCmd(iop_base);
13666 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013667}
13668
13669/*
13670 * Wait for EEPROM command to complete
13671 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013672static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013673{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013674 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013675
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013676 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
13677 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
13678 ASC_EEP_CMD_DONE) {
13679 break;
13680 }
13681 DvcSleepMilliSecond(1);
13682 }
13683 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
13684 0) {
13685 ASC_ASSERT(0);
13686 }
13687 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013688}
13689
13690/*
13691 * Write the EEPROM from 'cfg_buf'.
13692 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013693void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013694AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13695{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013696 ushort *wbuf;
13697 ushort addr, chksum;
13698 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013699
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013700 wbuf = (ushort *)cfg_buf;
13701 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13702 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013703
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013704 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13705 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013706
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013707 /*
13708 * Write EEPROM from word 0 to word 20.
13709 */
13710 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13711 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13712 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013713
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013714 if (*charfields++) {
13715 word = cpu_to_le16(*wbuf);
13716 } else {
13717 word = *wbuf;
13718 }
13719 chksum += *wbuf; /* Checksum is calculated from word values. */
13720 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13721 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13722 ASC_EEP_CMD_WRITE | addr);
13723 AdvWaitEEPCmd(iop_base);
13724 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013726
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013727 /*
13728 * Write EEPROM checksum at word 21.
13729 */
13730 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13731 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13732 AdvWaitEEPCmd(iop_base);
13733 wbuf++;
13734 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013735
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013736 /*
13737 * Write EEPROM OEM name at words 22 to 29.
13738 */
13739 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13740 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13741 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013742
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013743 if (*charfields++) {
13744 word = cpu_to_le16(*wbuf);
13745 } else {
13746 word = *wbuf;
13747 }
13748 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13749 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13750 ASC_EEP_CMD_WRITE | addr);
13751 AdvWaitEEPCmd(iop_base);
13752 }
13753 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13754 AdvWaitEEPCmd(iop_base);
13755 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013756}
13757
13758/*
13759 * Write the EEPROM from 'cfg_buf'.
13760 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013761void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013762AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013763{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013764 ushort *wbuf;
13765 ushort *charfields;
13766 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013767
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013768 wbuf = (ushort *)cfg_buf;
13769 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13770 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013772 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13773 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013774
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013775 /*
13776 * Write EEPROM from word 0 to word 20.
13777 */
13778 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13779 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13780 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013781
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013782 if (*charfields++) {
13783 word = cpu_to_le16(*wbuf);
13784 } else {
13785 word = *wbuf;
13786 }
13787 chksum += *wbuf; /* Checksum is calculated from word values. */
13788 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13789 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13790 ASC_EEP_CMD_WRITE | addr);
13791 AdvWaitEEPCmd(iop_base);
13792 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013794
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013795 /*
13796 * Write EEPROM checksum at word 21.
13797 */
13798 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13799 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13800 AdvWaitEEPCmd(iop_base);
13801 wbuf++;
13802 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013803
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013804 /*
13805 * Write EEPROM OEM name at words 22 to 29.
13806 */
13807 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13808 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13809 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013810
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013811 if (*charfields++) {
13812 word = cpu_to_le16(*wbuf);
13813 } else {
13814 word = *wbuf;
13815 }
13816 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13817 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13818 ASC_EEP_CMD_WRITE | addr);
13819 AdvWaitEEPCmd(iop_base);
13820 }
13821 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13822 AdvWaitEEPCmd(iop_base);
13823 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013824}
13825
13826/*
13827 * Write the EEPROM from 'cfg_buf'.
13828 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013829void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013830AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013831{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013832 ushort *wbuf;
13833 ushort *charfields;
13834 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013835
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013836 wbuf = (ushort *)cfg_buf;
13837 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13838 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013839
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013840 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13841 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013842
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013843 /*
13844 * Write EEPROM from word 0 to word 20.
13845 */
13846 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13847 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13848 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013849
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013850 if (*charfields++) {
13851 word = cpu_to_le16(*wbuf);
13852 } else {
13853 word = *wbuf;
13854 }
13855 chksum += *wbuf; /* Checksum is calculated from word values. */
13856 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13857 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13858 ASC_EEP_CMD_WRITE | addr);
13859 AdvWaitEEPCmd(iop_base);
13860 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
13861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013862
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013863 /*
13864 * Write EEPROM checksum at word 21.
13865 */
13866 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13867 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13868 AdvWaitEEPCmd(iop_base);
13869 wbuf++;
13870 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013871
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013872 /*
13873 * Write EEPROM OEM name at words 22 to 29.
13874 */
13875 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13876 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13877 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013878
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013879 if (*charfields++) {
13880 word = cpu_to_le16(*wbuf);
13881 } else {
13882 word = *wbuf;
13883 }
13884 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13885 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13886 ASC_EEP_CMD_WRITE | addr);
13887 AdvWaitEEPCmd(iop_base);
13888 }
13889 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13890 AdvWaitEEPCmd(iop_base);
13891 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013892}
13893
13894/* a_advlib.c */
13895/*
13896 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
13897 *
13898 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
13899 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
13900 * RISC to notify it a new command is ready to be executed.
13901 *
13902 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
13903 * set to SCSI_MAX_RETRY.
13904 *
13905 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
13906 * for DMA addresses or math operations are byte swapped to little-endian
13907 * order.
13908 *
13909 * Return:
13910 * ADV_SUCCESS(1) - The request was successfully queued.
13911 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
13912 * request completes.
13913 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
13914 * host IC error.
13915 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013916static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013917{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013918 ulong last_int_level;
13919 AdvPortAddr iop_base;
13920 ADV_DCNT req_size;
13921 ADV_PADDR req_paddr;
13922 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013923
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013924 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013925
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013926 /*
13927 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
13928 */
13929 if (scsiq->target_id > ADV_MAX_TID) {
13930 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
13931 scsiq->done_status = QD_WITH_ERROR;
13932 return ADV_ERROR;
13933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013934
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013935 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013936
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013937 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070013938
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013939 /*
13940 * Allocate a carrier ensuring at least one carrier always
13941 * remains on the freelist and initialize fields.
13942 */
13943 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
13944 DvcLeaveCritical(last_int_level);
13945 return ADV_BUSY;
13946 }
13947 asc_dvc->carr_freelist = (ADV_CARR_T *)
13948 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
13949 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013950
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013951 /*
13952 * Set the carrier to be a stopper by setting 'next_vpa'
13953 * to the stopper value. The current stopper will be changed
13954 * below to point to the new stopper.
13955 */
13956 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013957
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013958 /*
13959 * Clear the ADV_SCSI_REQ_Q done flag.
13960 */
13961 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013962
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013963 req_size = sizeof(ADV_SCSI_REQ_Q);
13964 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
13965 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013966
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013967 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
13968 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013969
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013970 /* Wait for assertion before making little-endian */
13971 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013972
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013973 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
13974 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
13975 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013976
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013977 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
13978 /*
13979 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
13980 * order during initialization.
13981 */
13982 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013983
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013984 /*
13985 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
13986 * the microcode. The newly allocated stopper will become the new
13987 * stopper.
13988 */
13989 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013991 /*
13992 * Set the 'next_vpa' pointer for the old stopper to be the
13993 * physical address of the new stopper. The RISC can only
13994 * follow physical addresses.
13995 */
13996 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013997
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013998 /*
13999 * Set the host adapter stopper pointer to point to the new carrier.
14000 */
14001 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014002
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014003 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14004 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14005 /*
14006 * Tickle the RISC to tell it to read its Command Queue Head pointer.
14007 */
14008 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
14009 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14010 /*
14011 * Clear the tickle value. In the ASC-3550 the RISC flag
14012 * command 'clr_tickle_a' does not work unless the host
14013 * value is cleared.
14014 */
14015 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14016 ADV_TICKLE_NOP);
14017 }
14018 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14019 /*
14020 * Notify the RISC a carrier is ready by writing the physical
14021 * address of the new carrier stopper to the COMMA register.
14022 */
14023 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
14024 le32_to_cpu(new_carrp->carr_pa));
14025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014026
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014027 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014028
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014029 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014030}
14031
14032/*
14033 * Reset SCSI Bus and purge all outstanding requests.
14034 *
14035 * Return Value:
14036 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
14037 * ADV_FALSE(0) - Microcode command failed.
14038 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
14039 * may be hung which requires driver recovery.
14040 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014041static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014042{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014043 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014044
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014045 /*
14046 * Send the SCSI Bus Reset idle start idle command which asserts
14047 * the SCSI Bus Reset signal.
14048 */
14049 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
14050 if (status != ADV_TRUE) {
14051 return status;
14052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014053
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014054 /*
14055 * Delay for the specified SCSI Bus Reset hold time.
14056 *
14057 * The hold time delay is done on the host because the RISC has no
14058 * microsecond accurate timer.
14059 */
14060 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014061
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014062 /*
14063 * Send the SCSI Bus Reset end idle command which de-asserts
14064 * the SCSI Bus Reset signal and purges any pending requests.
14065 */
14066 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
14067 if (status != ADV_TRUE) {
14068 return status;
14069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014071 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014072
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014073 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014074}
14075
14076/*
14077 * Reset chip and SCSI Bus.
14078 *
14079 * Return Value:
14080 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
14081 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
14082 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014083static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014084{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014085 int status;
14086 ushort wdtr_able, sdtr_able, tagqng_able;
14087 ushort ppr_able = 0;
14088 uchar tid, max_cmd[ADV_MAX_TID + 1];
14089 AdvPortAddr iop_base;
14090 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014091
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014092 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014093
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014094 /*
14095 * Save current per TID negotiated values.
14096 */
14097 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14098 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14099 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14100 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14101 }
14102 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14103 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14104 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14105 max_cmd[tid]);
14106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014107
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014108 /*
14109 * Force the AdvInitAsc3550/38C0800Driver() function to
14110 * perform a SCSI Bus Reset by clearing the BIOS signature word.
14111 * The initialization functions assumes a SCSI Bus Reset is not
14112 * needed if the BIOS signature word is present.
14113 */
14114 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
14115 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014116
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014117 /*
14118 * Stop chip and reset it.
14119 */
14120 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
14121 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14122 DvcSleepMilliSecond(100);
14123 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
14124 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014125
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014126 /*
14127 * Reset Adv Library error code, if any, and try
14128 * re-initializing the chip.
14129 */
14130 asc_dvc->err_code = 0;
14131 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14132 status = AdvInitAsc38C1600Driver(asc_dvc);
14133 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14134 status = AdvInitAsc38C0800Driver(asc_dvc);
14135 } else {
14136 status = AdvInitAsc3550Driver(asc_dvc);
14137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014138
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014139 /* Translate initialization return value to status value. */
14140 if (status == 0) {
14141 status = ADV_TRUE;
14142 } else {
14143 status = ADV_FALSE;
14144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014145
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014146 /*
14147 * Restore the BIOS signature word.
14148 */
14149 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014150
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014151 /*
14152 * Restore per TID negotiated values.
14153 */
14154 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14155 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14156 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14157 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14158 }
14159 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14160 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14161 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14162 max_cmd[tid]);
14163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014164
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014165 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014166}
14167
14168/*
14169 * Adv Library Interrupt Service Routine
14170 *
14171 * This function is called by a driver's interrupt service routine.
14172 * The function disables and re-enables interrupts.
14173 *
14174 * When a microcode idle command is completed, the ADV_DVC_VAR
14175 * 'idle_cmd_done' field is set to ADV_TRUE.
14176 *
14177 * Note: AdvISR() can be called when interrupts are disabled or even
14178 * when there is no hardware interrupt condition present. It will
14179 * always check for completed idle commands and microcode requests.
14180 * This is an important feature that shouldn't be changed because it
14181 * allows commands to be completed from polling mode loops.
14182 *
14183 * Return:
14184 * ADV_TRUE(1) - interrupt was pending
14185 * ADV_FALSE(0) - no interrupt was pending
14186 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014187static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014188{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189 AdvPortAddr iop_base;
14190 uchar int_stat;
14191 ushort target_bit;
14192 ADV_CARR_T *free_carrp;
14193 ADV_VADDR irq_next_vpa;
14194 int flags;
14195 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014197 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014198
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014199 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014200
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014201 /* Reading the register clears the interrupt. */
14202 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014203
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014204 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
14205 ADV_INTR_STATUS_INTRC)) == 0) {
14206 DvcLeaveCritical(flags);
14207 return ADV_FALSE;
14208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014209
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014210 /*
14211 * Notify the driver of an asynchronous microcode condition by
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014212 * calling the adv_async_callback function. The function
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014213 * is passed the microcode ASC_MC_INTRB_CODE byte value.
14214 */
14215 if (int_stat & ADV_INTR_STATUS_INTRB) {
14216 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014217
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014218 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014219
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014220 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14221 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14222 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
14223 asc_dvc->carr_pending_cnt != 0) {
14224 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14225 ADV_TICKLE_A);
14226 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14227 AdvWriteByteRegister(iop_base,
14228 IOPB_TICKLE,
14229 ADV_TICKLE_NOP);
14230 }
14231 }
14232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014233
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014234 adv_async_callback(asc_dvc, intrb_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014235 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014236
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014237 /*
14238 * Check if the IRQ stopper carrier contains a completed request.
14239 */
14240 while (((irq_next_vpa =
14241 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
14242 /*
14243 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
14244 * The RISC will have set 'areq_vpa' to a virtual address.
14245 *
14246 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
14247 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
14248 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
14249 * in AdvExeScsiQueue().
14250 */
14251 scsiq = (ADV_SCSI_REQ_Q *)
14252 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014254 /*
14255 * Request finished with good status and the queue was not
14256 * DMAed to host memory by the firmware. Set all status fields
14257 * to indicate good status.
14258 */
14259 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
14260 scsiq->done_status = QD_NO_ERROR;
14261 scsiq->host_status = scsiq->scsi_status = 0;
14262 scsiq->data_cnt = 0L;
14263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014264
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014265 /*
14266 * Advance the stopper pointer to the next carrier
14267 * ignoring the lower four bits. Free the previous
14268 * stopper carrier.
14269 */
14270 free_carrp = asc_dvc->irq_sp;
14271 asc_dvc->irq_sp = (ADV_CARR_T *)
14272 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014273
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014274 free_carrp->next_vpa =
14275 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14276 asc_dvc->carr_freelist = free_carrp;
14277 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014278
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014279 ASC_ASSERT(scsiq != NULL);
14280 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014281
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014282 /*
14283 * Clear request microcode control flag.
14284 */
14285 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014286
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014287 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014288 * Notify the driver of the completed request by passing
14289 * the ADV_SCSI_REQ_Q pointer to its callback function.
14290 */
14291 scsiq->a_flag |= ADV_SCSIQ_DONE;
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014292 adv_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014293 /*
14294 * Note: After the driver callback function is called, 'scsiq'
14295 * can no longer be referenced.
14296 *
14297 * Fall through and continue processing other completed
14298 * requests...
14299 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014300
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014301 /*
14302 * Disable interrupts again in case the driver inadvertently
14303 * enabled interrupts in its callback function.
14304 *
14305 * The DvcEnterCritical() return value is ignored, because
14306 * the 'flags' saved when AdvISR() was first entered will be
14307 * used to restore the interrupt flag on exit.
14308 */
14309 (void)DvcEnterCritical();
14310 }
14311 DvcLeaveCritical(flags);
14312 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014313}
14314
14315/*
14316 * Send an idle command to the chip and wait for completion.
14317 *
14318 * Command completion is polled for once per microsecond.
14319 *
14320 * The function can be called from anywhere including an interrupt handler.
14321 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
14322 * functions to prevent reentrancy.
14323 *
14324 * Return Values:
14325 * ADV_TRUE - command completed successfully
14326 * ADV_FALSE - command failed
14327 * ADV_ERROR - command timed out
14328 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014329static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070014330AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014331 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014332{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014333 ulong last_int_level;
14334 int result;
14335 ADV_DCNT i, j;
14336 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014337
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014338 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014339
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014340 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014341
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014342 /*
14343 * Clear the idle command status which is set by the microcode
14344 * to a non-zero value to indicate when the command is completed.
14345 * The non-zero result is one of the IDLE_CMD_STATUS_* values
14346 * defined in a_advlib.h.
14347 */
14348 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014349
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014350 /*
14351 * Write the idle command value after the idle command parameter
14352 * has been written to avoid a race condition. If the order is not
14353 * followed, the microcode may process the idle command before the
14354 * parameters have been written to LRAM.
14355 */
14356 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
14357 cpu_to_le32(idle_cmd_parameter));
14358 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014359
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014360 /*
14361 * Tickle the RISC to tell it to process the idle command.
14362 */
14363 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
14364 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14365 /*
14366 * Clear the tickle value. In the ASC-3550 the RISC flag
14367 * command 'clr_tickle_b' does not work unless the host
14368 * value is cleared.
14369 */
14370 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
14371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014372
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014373 /* Wait for up to 100 millisecond for the idle command to timeout. */
14374 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
14375 /* Poll once each microsecond for command completion. */
14376 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
14377 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
14378 result);
14379 if (result != 0) {
14380 DvcLeaveCritical(last_int_level);
14381 return result;
14382 }
14383 DvcDelayMicroSecond(asc_dvc, (ushort)1);
14384 }
14385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014386
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014387 ASC_ASSERT(0); /* The idle command should never timeout. */
14388 DvcLeaveCritical(last_int_level);
14389 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014390}
14391
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014392static int __devinit
14393advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
14394{
14395 int req_cnt = 0;
14396 adv_req_t *reqp = NULL;
14397 int sg_cnt = 0;
14398 adv_sgblk_t *sgp;
14399 int warn_code, err_code;
14400
14401 /*
14402 * Allocate buffer carrier structures. The total size
14403 * is about 4 KB, so allocate all at once.
14404 */
14405 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
14406 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
14407
14408 if (!boardp->carrp)
14409 goto kmalloc_failed;
14410
14411 /*
14412 * Allocate up to 'max_host_qng' request structures for the Wide
14413 * board. The total size is about 16 KB, so allocate all at once.
14414 * If the allocation fails decrement and try again.
14415 */
14416 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
14417 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
14418
14419 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
14420 "bytes %lu\n", reqp, req_cnt,
14421 (ulong)sizeof(adv_req_t) * req_cnt);
14422
14423 if (reqp)
14424 break;
14425 }
14426
14427 if (!reqp)
14428 goto kmalloc_failed;
14429
14430 boardp->orig_reqp = reqp;
14431
14432 /*
14433 * Allocate up to ADV_TOT_SG_BLOCK request structures for
14434 * the Wide board. Each structure is about 136 bytes.
14435 */
14436 boardp->adv_sgblkp = NULL;
14437 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
14438 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
14439
14440 if (!sgp)
14441 break;
14442
14443 sgp->next_sgblkp = boardp->adv_sgblkp;
14444 boardp->adv_sgblkp = sgp;
14445
14446 }
14447
14448 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
14449 sg_cnt, sizeof(adv_sgblk_t),
14450 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
14451
14452 if (!boardp->adv_sgblkp)
14453 goto kmalloc_failed;
14454
14455 adv_dvc_varp->carrier_buf = boardp->carrp;
14456
14457 /*
14458 * Point 'adv_reqp' to the request structures and
14459 * link them together.
14460 */
14461 req_cnt--;
14462 reqp[req_cnt].next_reqp = NULL;
14463 for (; req_cnt > 0; req_cnt--) {
14464 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
14465 }
14466 boardp->adv_reqp = &reqp[0];
14467
14468 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14469 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
14470 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
14471 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14472 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
14473 "\n");
14474 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
14475 } else {
14476 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
14477 "\n");
14478 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
14479 }
14480 err_code = adv_dvc_varp->err_code;
14481
14482 if (warn_code || err_code) {
14483 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
14484 " error 0x%x\n", boardp->id, warn_code, err_code);
14485 }
14486
14487 goto exit;
14488
14489 kmalloc_failed:
14490 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
14491 "failed\n", boardp->id);
14492 err_code = ADV_ERROR;
14493 exit:
14494 return err_code;
14495}
14496
14497static void advansys_wide_free_mem(asc_board_t *boardp)
14498{
14499 kfree(boardp->carrp);
14500 boardp->carrp = NULL;
14501 kfree(boardp->orig_reqp);
14502 boardp->orig_reqp = boardp->adv_reqp = NULL;
14503 while (boardp->adv_sgblkp) {
14504 adv_sgblk_t *sgp = boardp->adv_sgblkp;
14505 boardp->adv_sgblkp = sgp->next_sgblkp;
14506 kfree(sgp);
14507 }
14508}
14509
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014510static struct Scsi_Host *__devinit
14511advansys_board_found(int iop, struct device *dev, int bus_type)
14512{
14513 struct Scsi_Host *shost;
14514 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
14515 asc_board_t *boardp;
14516 ASC_DVC_VAR *asc_dvc_varp = NULL;
14517 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014518 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014519 int warn_code, err_code;
14520 int ret;
14521
14522 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014523 * Register the adapter, get its configuration, and
14524 * initialize it.
14525 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014526 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
14527 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014528 if (!shost)
14529 return NULL;
14530
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014531 /* Initialize private per board data */
14532 boardp = ASC_BOARDP(shost);
14533 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014534 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014535 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014536 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014537
14538 /*
14539 * Handle both narrow and wide boards.
14540 *
14541 * If a Wide board was detected, set the board structure
14542 * wide board flag. Set-up the board structure based on
14543 * the board type.
14544 */
14545#ifdef CONFIG_PCI
14546 if (bus_type == ASC_IS_PCI &&
14547 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14548 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14549 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
14550 boardp->flags |= ASC_IS_WIDE_BOARD;
14551 }
14552#endif /* CONFIG_PCI */
14553
14554 if (ASC_NARROW_BOARD(boardp)) {
14555 ASC_DBG(1, "advansys_board_found: narrow board\n");
14556 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
14557 asc_dvc_varp->bus_type = bus_type;
14558 asc_dvc_varp->drv_ptr = boardp;
14559 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
14560 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
14561 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014562 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014563#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014564 ASC_DBG(1, "advansys_board_found: wide board\n");
14565 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
14566 adv_dvc_varp->drv_ptr = boardp;
14567 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014568 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
14569 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
14570 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
14571 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
14572 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
14573 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
14574 } else {
14575 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
14576 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
14577 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014578
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014579 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
14580 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
14581 boardp->asc_n_io_port);
14582 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014583 ASC_PRINT3
14584 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014585 boardp->id, pci_resource_start(pdev, 1),
14586 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014587 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014588 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014589 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060014590 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014591 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014592
14593 /*
14594 * Even though it isn't used to access wide boards, other
14595 * than for the debug line below, save I/O Port address so
14596 * that it can be reported.
14597 */
14598 boardp->ioport = iop;
14599
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014600 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
14601 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
14602 (ushort)inpw(iop));
14603#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014604 }
14605
14606#ifdef CONFIG_PROC_FS
14607 /*
14608 * Allocate buffer for printing information from
14609 * /proc/scsi/advansys/[0...].
14610 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014611 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
14612 if (!boardp->prtbuf) {
14613 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
14614 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
14615 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014616 }
14617#endif /* CONFIG_PROC_FS */
14618
14619 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014620 /*
14621 * Set the board bus type and PCI IRQ before
14622 * calling AscInitGetConfig().
14623 */
14624 switch (asc_dvc_varp->bus_type) {
14625#ifdef CONFIG_ISA
14626 case ASC_IS_ISA:
14627 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014628 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014629 break;
14630 case ASC_IS_VL:
14631 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014632 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014633 break;
14634 case ASC_IS_EISA:
14635 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014636 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014637 break;
14638#endif /* CONFIG_ISA */
14639#ifdef CONFIG_PCI
14640 case ASC_IS_PCI:
14641 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014642 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014643 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014644 break;
14645#endif /* CONFIG_PCI */
14646 default:
14647 ASC_PRINT2
14648 ("advansys_board_found: board %d: unknown adapter type: %d\n",
14649 boardp->id, asc_dvc_varp->bus_type);
14650 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014651 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014652 break;
14653 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014654
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014655 /*
14656 * NOTE: AscInitGetConfig() may change the board's
14657 * bus_type value. The bus_type value should no
14658 * longer be used. If the bus_type field must be
14659 * referenced only use the bit-wise AND operator "&".
14660 */
14661 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014662 err_code = AscInitGetConfig(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014663 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014664#ifdef CONFIG_PCI
14665 /*
14666 * For Wide boards set PCI information before calling
14667 * AdvInitGetConfig().
14668 */
14669 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
14670 shost->unchecked_isa_dma = FALSE;
14671 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014672 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014673
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014674 err_code = AdvInitGetConfig(pdev, boardp);
14675#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014676 }
14677
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014678 if (err_code != 0)
14679 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014680
14681 /*
14682 * Save the EEPROM configuration so that it can be displayed
14683 * from /proc/scsi/advansys/[0...].
14684 */
14685 if (ASC_NARROW_BOARD(boardp)) {
14686
14687 ASCEEP_CONFIG *ep;
14688
14689 /*
14690 * Set the adapter's target id bit in the 'init_tidmask' field.
14691 */
14692 boardp->init_tidmask |=
14693 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
14694
14695 /*
14696 * Save EEPROM settings for the board.
14697 */
14698 ep = &boardp->eep_config.asc_eep;
14699
14700 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
14701 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
14702 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
14703 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
14704 ep->start_motor = asc_dvc_varp->start_motor;
14705 ep->cntl = asc_dvc_varp->dvc_cntl;
14706 ep->no_scam = asc_dvc_varp->no_scam;
14707 ep->max_total_qng = asc_dvc_varp->max_total_qng;
14708 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
14709 /* 'max_tag_qng' is set to the same value for every device. */
14710 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
14711 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
14712 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
14713 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
14714 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
14715 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
14716 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
14717
14718 /*
14719 * Modify board configuration.
14720 */
14721 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014722 err_code = AscInitSetConfig(pdev, boardp);
14723 if (err_code)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014724 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014725
14726 /*
14727 * Finish initializing the 'Scsi_Host' structure.
14728 */
14729 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
14730 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
14731 shost->irq = asc_dvc_varp->irq_no;
14732 }
14733 } else {
14734 ADVEEP_3550_CONFIG *ep_3550;
14735 ADVEEP_38C0800_CONFIG *ep_38C0800;
14736 ADVEEP_38C1600_CONFIG *ep_38C1600;
14737
14738 /*
14739 * Save Wide EEP Configuration Information.
14740 */
14741 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14742 ep_3550 = &boardp->eep_config.adv_3550_eep;
14743
14744 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
14745 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
14746 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14747 ep_3550->termination = adv_dvc_varp->cfg->termination;
14748 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
14749 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
14750 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
14751 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
14752 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
14753 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
14754 ep_3550->start_motor = adv_dvc_varp->start_motor;
14755 ep_3550->scsi_reset_delay =
14756 adv_dvc_varp->scsi_reset_wait;
14757 ep_3550->serial_number_word1 =
14758 adv_dvc_varp->cfg->serial1;
14759 ep_3550->serial_number_word2 =
14760 adv_dvc_varp->cfg->serial2;
14761 ep_3550->serial_number_word3 =
14762 adv_dvc_varp->cfg->serial3;
14763 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14764 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
14765
14766 ep_38C0800->adapter_scsi_id =
14767 adv_dvc_varp->chip_scsi_id;
14768 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
14769 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14770 ep_38C0800->termination_lvd =
14771 adv_dvc_varp->cfg->termination;
14772 ep_38C0800->disc_enable =
14773 adv_dvc_varp->cfg->disc_enable;
14774 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
14775 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
14776 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14777 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14778 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14779 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14780 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14781 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14782 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
14783 ep_38C0800->scsi_reset_delay =
14784 adv_dvc_varp->scsi_reset_wait;
14785 ep_38C0800->serial_number_word1 =
14786 adv_dvc_varp->cfg->serial1;
14787 ep_38C0800->serial_number_word2 =
14788 adv_dvc_varp->cfg->serial2;
14789 ep_38C0800->serial_number_word3 =
14790 adv_dvc_varp->cfg->serial3;
14791 } else {
14792 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
14793
14794 ep_38C1600->adapter_scsi_id =
14795 adv_dvc_varp->chip_scsi_id;
14796 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
14797 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14798 ep_38C1600->termination_lvd =
14799 adv_dvc_varp->cfg->termination;
14800 ep_38C1600->disc_enable =
14801 adv_dvc_varp->cfg->disc_enable;
14802 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
14803 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
14804 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14805 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14806 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14807 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14808 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14809 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14810 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
14811 ep_38C1600->scsi_reset_delay =
14812 adv_dvc_varp->scsi_reset_wait;
14813 ep_38C1600->serial_number_word1 =
14814 adv_dvc_varp->cfg->serial1;
14815 ep_38C1600->serial_number_word2 =
14816 adv_dvc_varp->cfg->serial2;
14817 ep_38C1600->serial_number_word3 =
14818 adv_dvc_varp->cfg->serial3;
14819 }
14820
14821 /*
14822 * Set the adapter's target id bit in the 'init_tidmask' field.
14823 */
14824 boardp->init_tidmask |=
14825 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014826 }
14827
14828 /*
14829 * Channels are numbered beginning with 0. For AdvanSys one host
14830 * structure supports one channel. Multi-channel boards have a
14831 * separate host structure for each channel.
14832 */
14833 shost->max_channel = 0;
14834 if (ASC_NARROW_BOARD(boardp)) {
14835 shost->max_id = ASC_MAX_TID + 1;
14836 shost->max_lun = ASC_MAX_LUN + 1;
14837
14838 shost->io_port = asc_dvc_varp->iop_base;
14839 boardp->asc_n_io_port = ASC_IOADR_GAP;
14840 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
14841
14842 /* Set maximum number of queues the adapter can handle. */
14843 shost->can_queue = asc_dvc_varp->max_total_qng;
14844 } else {
14845 shost->max_id = ADV_MAX_TID + 1;
14846 shost->max_lun = ADV_MAX_LUN + 1;
14847
14848 /*
14849 * Save the I/O Port address and length even though
14850 * I/O ports are not used to access Wide boards.
14851 * Instead the Wide boards are accessed with
14852 * PCI Memory Mapped I/O.
14853 */
14854 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014855
14856 shost->this_id = adv_dvc_varp->chip_scsi_id;
14857
14858 /* Set maximum number of queues the adapter can handle. */
14859 shost->can_queue = adv_dvc_varp->max_host_qng;
14860 }
14861
14862 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014863 * Following v1.3.89, 'cmd_per_lun' is no longer needed
14864 * and should be set to zero.
14865 *
14866 * But because of a bug introduced in v1.3.89 if the driver is
14867 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
14868 * SCSI function 'allocate_device' will panic. To allow the driver
14869 * to work as a module in these kernels set 'cmd_per_lun' to 1.
14870 *
14871 * Note: This is wrong. cmd_per_lun should be set to the depth
14872 * you want on untagged devices always.
14873 #ifdef MODULE
14874 */
14875 shost->cmd_per_lun = 1;
14876/* #else
14877 shost->cmd_per_lun = 0;
14878#endif */
14879
14880 /*
14881 * Set the maximum number of scatter-gather elements the
14882 * adapter can handle.
14883 */
14884 if (ASC_NARROW_BOARD(boardp)) {
14885 /*
14886 * Allow two commands with 'sg_tablesize' scatter-gather
14887 * elements to be executed simultaneously. This value is
14888 * the theoretical hardware limit. It may be decreased
14889 * below.
14890 */
14891 shost->sg_tablesize =
14892 (((asc_dvc_varp->max_total_qng - 2) / 2) *
14893 ASC_SG_LIST_PER_Q) + 1;
14894 } else {
14895 shost->sg_tablesize = ADV_MAX_SG_LIST;
14896 }
14897
14898 /*
14899 * The value of 'sg_tablesize' can not exceed the SCSI
14900 * mid-level driver definition of SG_ALL. SG_ALL also
14901 * must not be exceeded, because it is used to define the
14902 * size of the scatter-gather table in 'struct asc_sg_head'.
14903 */
14904 if (shost->sg_tablesize > SG_ALL) {
14905 shost->sg_tablesize = SG_ALL;
14906 }
14907
14908 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
14909
14910 /* BIOS start address. */
14911 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014912 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
14913 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014914 } else {
14915 /*
14916 * Fill-in BIOS board variables. The Wide BIOS saves
14917 * information in LRAM that is used by the driver.
14918 */
14919 AdvReadWordLram(adv_dvc_varp->iop_base,
14920 BIOS_SIGNATURE, boardp->bios_signature);
14921 AdvReadWordLram(adv_dvc_varp->iop_base,
14922 BIOS_VERSION, boardp->bios_version);
14923 AdvReadWordLram(adv_dvc_varp->iop_base,
14924 BIOS_CODESEG, boardp->bios_codeseg);
14925 AdvReadWordLram(adv_dvc_varp->iop_base,
14926 BIOS_CODELEN, boardp->bios_codelen);
14927
14928 ASC_DBG2(1,
14929 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
14930 boardp->bios_signature, boardp->bios_version);
14931
14932 ASC_DBG2(1,
14933 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
14934 boardp->bios_codeseg, boardp->bios_codelen);
14935
14936 /*
14937 * If the BIOS saved a valid signature, then fill in
14938 * the BIOS code segment base address.
14939 */
14940 if (boardp->bios_signature == 0x55AA) {
14941 /*
14942 * Convert x86 realmode code segment to a linear
14943 * address by shifting left 4.
14944 */
14945 shost->base = ((ulong)boardp->bios_codeseg << 4);
14946 } else {
14947 shost->base = 0;
14948 }
14949 }
14950
14951 /*
14952 * Register Board Resources - I/O Port, DMA, IRQ
14953 */
14954
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014955 /* Register DMA Channel for Narrow boards. */
14956 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14957#ifdef CONFIG_ISA
14958 if (ASC_NARROW_BOARD(boardp)) {
14959 /* Register DMA channel for ISA bus. */
14960 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14961 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014962 ret = request_dma(shost->dma_channel, "advansys");
14963 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014964 ASC_PRINT3
14965 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14966 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014967 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014968 }
14969 AscEnableIsaDma(shost->dma_channel);
14970 }
14971 }
14972#endif /* CONFIG_ISA */
14973
14974 /* Register IRQ Number. */
14975 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014976
14977 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
14978 "advansys", shost);
14979
14980 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014981 if (ret == -EBUSY) {
14982 ASC_PRINT2
14983 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
14984 boardp->id, shost->irq);
14985 } else if (ret == -EINVAL) {
14986 ASC_PRINT2
14987 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
14988 boardp->id, shost->irq);
14989 } else {
14990 ASC_PRINT3
14991 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
14992 boardp->id, shost->irq, ret);
14993 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014994 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014995 }
14996
14997 /*
14998 * Initialize board RISC chip and enable interrupts.
14999 */
15000 if (ASC_NARROW_BOARD(boardp)) {
15001 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
15002 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
15003 err_code = asc_dvc_varp->err_code;
15004
15005 if (warn_code || err_code) {
15006 ASC_PRINT4
15007 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
15008 boardp->id,
15009 asc_dvc_varp->init_state, warn_code, err_code);
15010 }
15011 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015012 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015013 }
15014
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015015 if (err_code != 0)
15016 goto err_free_wide_mem;
15017
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015018 ASC_DBG_PRT_SCSI_HOST(2, shost);
15019
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015020 ret = scsi_add_host(shost, dev);
15021 if (ret)
15022 goto err_free_wide_mem;
15023
15024 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015025 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015026
15027 err_free_wide_mem:
15028 advansys_wide_free_mem(boardp);
15029 free_irq(shost->irq, shost);
15030 err_free_dma:
15031 if (shost->dma_channel != NO_ISA_DMA)
15032 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015033 err_free_proc:
15034 kfree(boardp->prtbuf);
15035 err_unmap:
15036 if (boardp->ioremap_addr)
15037 iounmap(boardp->ioremap_addr);
15038 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015039 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015040 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015041}
15042
15043/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015044 * advansys_release()
15045 *
15046 * Release resources allocated for a single AdvanSys adapter.
15047 */
15048static int advansys_release(struct Scsi_Host *shost)
15049{
15050 asc_board_t *boardp;
15051
15052 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015053 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015054 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015055 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015056 if (shost->dma_channel != NO_ISA_DMA) {
15057 ASC_DBG(1, "advansys_release: free_dma()\n");
15058 free_dma(shost->dma_channel);
15059 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015060 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015061 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015062 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015063 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015064 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015065 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015066 ASC_DBG(1, "advansys_release: end\n");
15067 return 0;
15068}
15069
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015070static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
15071 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
15072 0x0210, 0x0230, 0x0250, 0x0330
15073};
15074
15075static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
15076{
15077 PortAddr iop_base = _asc_def_iop_base[id];
15078 struct Scsi_Host *shost;
15079
15080 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015081 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
15082 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015083 return -ENODEV;
15084 }
15085 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015086 if (!AscFindSignature(iop_base))
15087 goto nodev;
15088 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
15089 goto nodev;
15090
15091 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015092 if (!shost)
15093 goto nodev;
15094
15095 dev_set_drvdata(dev, shost);
15096 return 0;
15097
15098 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015099 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015100 return -ENODEV;
15101}
15102
15103static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
15104{
Matthew Wilcox71f36112007-07-30 08:04:53 -060015105 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015106 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015107 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015108 return 0;
15109}
15110
15111static struct isa_driver advansys_isa_driver = {
15112 .probe = advansys_isa_probe,
15113 .remove = __devexit_p(advansys_isa_remove),
15114 .driver = {
15115 .owner = THIS_MODULE,
15116 .name = "advansys",
15117 },
15118};
15119
15120static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
15121{
15122 PortAddr iop_base = _asc_def_iop_base[id];
15123 struct Scsi_Host *shost;
15124
15125 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015126 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
15127 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015128 return -ENODEV;
15129 }
15130 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015131 if (!AscFindSignature(iop_base))
15132 goto nodev;
15133 /*
15134 * I don't think this condition can actually happen, but the old
15135 * driver did it, and the chances of finding a VLB setup in 2007
15136 * to do testing with is slight to none.
15137 */
15138 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
15139 goto nodev;
15140
15141 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015142 if (!shost)
15143 goto nodev;
15144
15145 dev_set_drvdata(dev, shost);
15146 return 0;
15147
15148 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015149 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015150 return -ENODEV;
15151}
15152
15153static struct isa_driver advansys_vlb_driver = {
15154 .probe = advansys_vlb_probe,
15155 .remove = __devexit_p(advansys_isa_remove),
15156 .driver = {
15157 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060015158 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015159 },
15160};
15161
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015162static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
15163 { "ABP7401" },
15164 { "ABP7501" },
15165 { "" }
15166};
15167
15168MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
15169
15170/*
15171 * EISA is a little more tricky than PCI; each EISA device may have two
15172 * channels, and this driver is written to make each channel its own Scsi_Host
15173 */
15174struct eisa_scsi_data {
15175 struct Scsi_Host *host[2];
15176};
15177
15178static int __devinit advansys_eisa_probe(struct device *dev)
15179{
15180 int i, ioport;
15181 int err;
15182 struct eisa_device *edev = to_eisa_device(dev);
15183 struct eisa_scsi_data *data;
15184
15185 err = -ENOMEM;
15186 data = kzalloc(sizeof(*data), GFP_KERNEL);
15187 if (!data)
15188 goto fail;
15189 ioport = edev->base_addr + 0xc30;
15190
15191 err = -ENODEV;
15192 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015193 if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
15194 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
15195 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015196 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015197 }
15198 if (!AscFindSignature(ioport)) {
15199 release_region(ioport, ASC_IOADR_GAP);
15200 continue;
15201 }
15202
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015203 /*
15204 * I don't know why we need to do this for EISA chips, but
15205 * not for any others. It looks to be equivalent to
15206 * AscGetChipCfgMsw, but I may have overlooked something,
15207 * so I'm not converting it until I get an EISA board to
15208 * test with.
15209 */
15210 inw(ioport + 4);
15211 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015212 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015213 err = 0;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015214 } else {
15215 release_region(ioport, ASC_IOADR_GAP);
15216 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015217 }
15218
15219 if (err) {
15220 kfree(data);
15221 } else {
15222 dev_set_drvdata(dev, data);
15223 }
15224
15225 fail:
15226 return err;
15227}
15228
15229static __devexit int advansys_eisa_remove(struct device *dev)
15230{
15231 int i;
15232 struct eisa_scsi_data *data = dev_get_drvdata(dev);
15233
15234 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015235 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015236 struct Scsi_Host *shost = data->host[i];
15237 if (!shost)
15238 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015239 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015240 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015241 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015242 }
15243
15244 kfree(data);
15245 return 0;
15246}
15247
15248static struct eisa_driver advansys_eisa_driver = {
15249 .id_table = advansys_eisa_table,
15250 .driver = {
15251 .name = "advansys",
15252 .probe = advansys_eisa_probe,
15253 .remove = __devexit_p(advansys_eisa_remove),
15254 }
15255};
15256
Dave Jones2672ea82006-08-02 17:11:49 -040015257/* PCI Devices supported by this driver */
15258static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015259 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
15260 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15261 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
15262 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15263 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
15264 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15265 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
15266 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15267 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
15268 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15269 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
15270 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15271 {}
Dave Jones2672ea82006-08-02 17:11:49 -040015272};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015273
Dave Jones2672ea82006-08-02 17:11:49 -040015274MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015275
Matthew Wilcox9649af32007-07-26 21:51:47 -060015276static void __devinit advansys_set_latency(struct pci_dev *pdev)
15277{
15278 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
15279 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
15280 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
15281 } else {
15282 u8 latency;
15283 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
15284 if (latency < 0x20)
15285 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
15286 }
15287}
15288
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015289static int __devinit
15290advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15291{
15292 int err, ioport;
15293 struct Scsi_Host *shost;
15294
15295 err = pci_enable_device(pdev);
15296 if (err)
15297 goto fail;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015298 err = pci_request_regions(pdev, "advansys");
15299 if (err)
15300 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060015301 pci_set_master(pdev);
15302 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015303
15304 if (pci_resource_len(pdev, 0) == 0)
15305 goto nodev;
15306
15307 ioport = pci_resource_start(pdev, 0);
15308 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
15309
15310 if (!shost)
15311 goto nodev;
15312
15313 pci_set_drvdata(pdev, shost);
15314 return 0;
15315
15316 nodev:
15317 err = -ENODEV;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015318 pci_release_regions(pdev);
15319 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015320 pci_disable_device(pdev);
15321 fail:
15322 return err;
15323}
15324
15325static void __devexit advansys_pci_remove(struct pci_dev *pdev)
15326{
15327 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015328 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015329 pci_disable_device(pdev);
15330}
15331
15332static struct pci_driver advansys_pci_driver = {
15333 .name = "advansys",
15334 .id_table = advansys_pci_tbl,
15335 .probe = advansys_pci_probe,
15336 .remove = __devexit_p(advansys_pci_remove),
15337};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015338
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015339static int __init advansys_init(void)
15340{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015341 int error;
15342
15343 error = isa_register_driver(&advansys_isa_driver,
15344 ASC_IOADR_TABLE_MAX_IX);
15345 if (error)
15346 goto fail;
15347
15348 error = isa_register_driver(&advansys_vlb_driver,
15349 ASC_IOADR_TABLE_MAX_IX);
15350 if (error)
15351 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015352
15353 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015354 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015355 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015356
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015357 error = pci_register_driver(&advansys_pci_driver);
15358 if (error)
15359 goto unregister_eisa;
15360
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015361 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015362
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015363 unregister_eisa:
15364 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015365 unregister_vlb:
15366 isa_unregister_driver(&advansys_vlb_driver);
15367 unregister_isa:
15368 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015369 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015370 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015371}
15372
15373static void __exit advansys_exit(void)
15374{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015375 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015376 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015377 isa_unregister_driver(&advansys_vlb_driver);
15378 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015379}
15380
15381module_init(advansys_init);
15382module_exit(advansys_exit);
15383
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015384MODULE_LICENSE("GPL");