blob: a5bb4e416bea7afecec0fcaf12ce336384b7f211 [file] [log] [blame]
Matthew Wilcox01fbfe02007-09-09 08:56:40 -06001#define DRV_NAME "advansys"
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04002#define ASC_VERSION "3.4" /* AdvanSys Driver Version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003
4/*
5 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
6 *
7 * Copyright (c) 1995-2000 Advanced System Products, Inc.
8 * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04009 * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * All Rights Reserved.
11 *
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
20 * changed its name to ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040021 * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/string.h>
26#include <linux/kernel.h>
27#include <linux/types.h>
28#include <linux/ioport.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <linux/slab.h>
32#include <linux/mm.h>
33#include <linux/proc_fs.h>
34#include <linux/init.h>
35#include <linux/blkdev.h>
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060036#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060037#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040038#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/spinlock.h>
40#include <linux/dma-mapping.h>
41
42#include <asm/io.h>
43#include <asm/system.h>
44#include <asm/dma.h>
45
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040046#include <scsi/scsi_cmnd.h>
47#include <scsi/scsi_device.h>
48#include <scsi/scsi_tcq.h>
49#include <scsi/scsi.h>
50#include <scsi/scsi_host.h>
51
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060052/* FIXME:
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 *
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060054 * 1. Although all of the necessary command mapping places have the
55 * appropriate dma_map.. APIs, the driver still processes its internal
56 * queue using bus_to_virt() and virt_to_bus() which are illegal under
57 * the API. The entire queue processing structure will need to be
58 * altered to fix this.
59 * 2. Need to add memory mapping workaround. Test the memory mapping.
60 * If it doesn't work revert to I/O port access. Can a test be done
61 * safely?
62 * 3. Handle an interrupt not working. Keep an interrupt counter in
63 * the interrupt handler. In the timeout function if the interrupt
64 * has not occurred then print a message and run in polled mode.
65 * 4. Need to add support for target mode commands, cf. CAM XPT.
66 * 5. check DMA mapping functions for failure
Matthew Wilcox349d2c42007-09-09 08:56:34 -060067 * 6. Use scsi_transport_spi
68 * 7. advansys_info is not safe against multiple simultaneous callers
69 * 8. Kill boardp->id
70 * 9. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 */
72#warning this driver is still not properly converted to the DMA API
73
Linus Torvalds1da177e2005-04-16 15:20:36 -070074/* Enable driver /proc statistics. */
75#define ADVANSYS_STATS
76
77/* Enable driver tracing. */
78/* #define ADVANSYS_DEBUG */
79
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#define ASC_LIB_VERSION_MAJOR 1
81#define ASC_LIB_VERSION_MINOR 24
82#define ASC_LIB_SERIAL_NUMBER 123
83
84/*
85 * Portable Data Types
86 *
87 * Any instance where a 32-bit long or pointer type is assumed
88 * for precision or HW defined structures, the following define
89 * types must be used. In Linux the char, short, and int types
90 * are all consistent at 8, 16, and 32 bits respectively. Pointers
91 * and long types are 64 bits on Alpha and UltraSPARC.
92 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040093#define ASC_PADDR __u32 /* Physical/Bus address data type. */
94#define ASC_VADDR __u32 /* Virtual address data type. */
95#define ASC_DCNT __u32 /* Unsigned Data count type. */
96#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
98/*
99 * These macros are used to convert a virtual address to a
100 * 32-bit value. This currently can be used on Linux Alpha
101 * which uses 64-bit virtual address but a 32-bit bus address.
102 * This is likely to break in the future, but doing this now
103 * will give us time to change the HW and FW to handle 64-bit
104 * addresses.
105 */
106#define ASC_VADDR_TO_U32 virt_to_bus
107#define ASC_U32_TO_VADDR bus_to_virt
108
109typedef unsigned char uchar;
110
111#ifndef TRUE
112#define TRUE (1)
113#endif
114#ifndef FALSE
115#define FALSE (0)
116#endif
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118#define ERR (-1)
119#define UW_ERR (uint)(0xFFFF)
120#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Dave Jones2672ea82006-08-02 17:11:49 -0400122#define PCI_VENDOR_ID_ASP 0x10cd
123#define PCI_DEVICE_ID_ASP_1200A 0x1100
124#define PCI_DEVICE_ID_ASP_ABP940 0x1200
125#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
126#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
127#define PCI_DEVICE_ID_38C0800_REV1 0x2500
128#define PCI_DEVICE_ID_38C1600_REV1 0x2700
129
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130/*
131 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
132 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
133 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
134 * SRB structure.
135 */
136#define CC_VERY_LONG_SG_LIST 0
137#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
138
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400139#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140#define inp(port) inb(port)
141#define outp(port, byte) outb((byte), (port))
142
143#define inpw(port) inw(port)
144#define outpw(port, word) outw((word), (port))
145
146#define ASC_MAX_SG_QUEUE 7
147#define ASC_MAX_SG_LIST 255
148
149#define ASC_CS_TYPE unsigned short
150
151#define ASC_IS_ISA (0x0001)
152#define ASC_IS_ISAPNP (0x0081)
153#define ASC_IS_EISA (0x0002)
154#define ASC_IS_PCI (0x0004)
155#define ASC_IS_PCI_ULTRA (0x0104)
156#define ASC_IS_PCMCIA (0x0008)
157#define ASC_IS_MCA (0x0020)
158#define ASC_IS_VL (0x0040)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159#define ASC_IS_WIDESCSI_16 (0x0100)
160#define ASC_IS_WIDESCSI_32 (0x0200)
161#define ASC_IS_BIG_ENDIAN (0x8000)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163#define ASC_CHIP_MIN_VER_VL (0x01)
164#define ASC_CHIP_MAX_VER_VL (0x07)
165#define ASC_CHIP_MIN_VER_PCI (0x09)
166#define ASC_CHIP_MAX_VER_PCI (0x0F)
167#define ASC_CHIP_VER_PCI_BIT (0x08)
168#define ASC_CHIP_MIN_VER_ISA (0x11)
169#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
170#define ASC_CHIP_MAX_VER_ISA (0x27)
171#define ASC_CHIP_VER_ISA_BIT (0x30)
172#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
173#define ASC_CHIP_VER_ASYN_BUG (0x21)
174#define ASC_CHIP_VER_PCI 0x08
175#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
176#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
177#define ASC_CHIP_MIN_VER_EISA (0x41)
178#define ASC_CHIP_MAX_VER_EISA (0x47)
179#define ASC_CHIP_VER_EISA_BIT (0x40)
180#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
185#define ASC_SCSI_ID_BITS 3
186#define ASC_SCSI_TIX_TYPE uchar
187#define ASC_ALL_DEVICE_BIT_SET 0xFF
188#define ASC_SCSI_BIT_ID_TYPE uchar
189#define ASC_MAX_TID 7
190#define ASC_MAX_LUN 7
191#define ASC_SCSI_WIDTH_BIT_SET 0xFF
192#define ASC_MAX_SENSE_LEN 32
193#define ASC_MIN_SENSE_LEN 14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#define ASC_SCSI_RESET_HOLD_TIME_US 60
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196/*
Matthew Wilcoxf05ec592007-09-09 08:56:36 -0600197 * Narrow boards only support 12-byte commands, while wide boards
198 * extend to 16-byte commands.
199 */
200#define ASC_MAX_CDB_LEN 12
201#define ADV_MAX_CDB_LEN 16
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
206#define ASC_SG_LIST_PER_Q 7
207#define QS_FREE 0x00
208#define QS_READY 0x01
209#define QS_DISC1 0x02
210#define QS_DISC2 0x04
211#define QS_BUSY 0x08
212#define QS_ABORTED 0x40
213#define QS_DONE 0x80
214#define QC_NO_CALLBACK 0x01
215#define QC_SG_SWAP_QUEUE 0x02
216#define QC_SG_HEAD 0x04
217#define QC_DATA_IN 0x08
218#define QC_DATA_OUT 0x10
219#define QC_URGENT 0x20
220#define QC_MSG_OUT 0x40
221#define QC_REQ_SENSE 0x80
222#define QCSG_SG_XFER_LIST 0x02
223#define QCSG_SG_XFER_MORE 0x04
224#define QCSG_SG_XFER_END 0x08
225#define QD_IN_PROGRESS 0x00
226#define QD_NO_ERROR 0x01
227#define QD_ABORTED_BY_HOST 0x02
228#define QD_WITH_ERROR 0x04
229#define QD_INVALID_REQUEST 0x80
230#define QD_INVALID_HOST_NUM 0x81
231#define QD_INVALID_DEVICE 0x82
232#define QD_ERR_INTERNAL 0xFF
233#define QHSTA_NO_ERROR 0x00
234#define QHSTA_M_SEL_TIMEOUT 0x11
235#define QHSTA_M_DATA_OVER_RUN 0x12
236#define QHSTA_M_DATA_UNDER_RUN 0x12
237#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
238#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
239#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
240#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
241#define QHSTA_D_HOST_ABORT_FAILED 0x23
242#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
243#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
244#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
245#define QHSTA_M_WTM_TIMEOUT 0x41
246#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
247#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
248#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
249#define QHSTA_M_TARGET_STATUS_BUSY 0x45
250#define QHSTA_M_BAD_TAG_CODE 0x46
251#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
252#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
253#define QHSTA_D_LRAM_CMP_ERROR 0x81
254#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
255#define ASC_FLAG_SCSIQ_REQ 0x01
256#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
257#define ASC_FLAG_BIOS_ASYNC_IO 0x04
258#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
259#define ASC_FLAG_WIN16 0x10
260#define ASC_FLAG_WIN32 0x20
261#define ASC_FLAG_ISA_OVER_16MB 0x40
262#define ASC_FLAG_DOS_VM_CALLBACK 0x80
263#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
264#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
265#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
266#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
267#define ASC_SCSIQ_CPY_BEG 4
268#define ASC_SCSIQ_SGHD_CPY_BEG 2
269#define ASC_SCSIQ_B_FWD 0
270#define ASC_SCSIQ_B_BWD 1
271#define ASC_SCSIQ_B_STATUS 2
272#define ASC_SCSIQ_B_QNO 3
273#define ASC_SCSIQ_B_CNTL 4
274#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
275#define ASC_SCSIQ_D_DATA_ADDR 8
276#define ASC_SCSIQ_D_DATA_CNT 12
277#define ASC_SCSIQ_B_SENSE_LEN 20
278#define ASC_SCSIQ_DONE_INFO_BEG 22
279#define ASC_SCSIQ_D_SRBPTR 22
280#define ASC_SCSIQ_B_TARGET_IX 26
281#define ASC_SCSIQ_B_CDB_LEN 28
282#define ASC_SCSIQ_B_TAG_CODE 29
283#define ASC_SCSIQ_W_VM_ID 30
284#define ASC_SCSIQ_DONE_STATUS 32
285#define ASC_SCSIQ_HOST_STATUS 33
286#define ASC_SCSIQ_SCSI_STATUS 34
287#define ASC_SCSIQ_CDB_BEG 36
288#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
289#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
290#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
291#define ASC_SCSIQ_B_SG_WK_QP 49
292#define ASC_SCSIQ_B_SG_WK_IX 50
293#define ASC_SCSIQ_W_ALT_DC1 52
294#define ASC_SCSIQ_B_LIST_CNT 6
295#define ASC_SCSIQ_B_CUR_LIST_CNT 7
296#define ASC_SGQ_B_SG_CNTL 4
297#define ASC_SGQ_B_SG_HEAD_QP 5
298#define ASC_SGQ_B_SG_LIST_CNT 6
299#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
300#define ASC_SGQ_LIST_BEG 8
301#define ASC_DEF_SCSI1_QNG 4
302#define ASC_MAX_SCSI1_QNG 4
303#define ASC_DEF_SCSI2_QNG 16
304#define ASC_MAX_SCSI2_QNG 32
305#define ASC_TAG_CODE_MASK 0x23
306#define ASC_STOP_REQ_RISC_STOP 0x01
307#define ASC_STOP_ACK_RISC_STOP 0x03
308#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
309#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
310#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
311#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
312#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
313#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
314#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
315#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
316#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
317#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
318
319typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400320 uchar status;
321 uchar q_no;
322 uchar cntl;
323 uchar sg_queue_cnt;
324 uchar target_id;
325 uchar target_lun;
326 ASC_PADDR data_addr;
327 ASC_DCNT data_cnt;
328 ASC_PADDR sense_addr;
329 uchar sense_len;
330 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331} ASC_SCSIQ_1;
332
333typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400334 ASC_VADDR srb_ptr;
335 uchar target_ix;
336 uchar flag;
337 uchar cdb_len;
338 uchar tag_code;
339 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340} ASC_SCSIQ_2;
341
342typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400343 uchar done_stat;
344 uchar host_stat;
345 uchar scsi_stat;
346 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347} ASC_SCSIQ_3;
348
349typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400350 uchar cdb[ASC_MAX_CDB_LEN];
351 uchar y_first_sg_list_qp;
352 uchar y_working_sg_qp;
353 uchar y_working_sg_ix;
354 uchar y_res;
355 ushort x_req_count;
356 ushort x_reconnect_rtn;
357 ASC_PADDR x_saved_data_addr;
358 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359} ASC_SCSIQ_4;
360
361typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400362 ASC_SCSIQ_2 d2;
363 ASC_SCSIQ_3 d3;
364 uchar q_status;
365 uchar q_no;
366 uchar cntl;
367 uchar sense_len;
368 uchar extra_bytes;
369 uchar res;
370 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371} ASC_QDONE_INFO;
372
373typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400374 ASC_PADDR addr;
375 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376} ASC_SG_LIST;
377
378typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400379 ushort entry_cnt;
380 ushort queue_cnt;
381 ushort entry_to_copy;
382 ushort res;
Matthew Wilcox05848b62007-10-02 21:55:25 -0400383 ASC_SG_LIST sg_list[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384} ASC_SG_HEAD;
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400387 ASC_SCSIQ_1 q1;
388 ASC_SCSIQ_2 q2;
389 uchar *cdbptr;
390 ASC_SG_HEAD *sg_head;
391 ushort remain_sg_entry_cnt;
392 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393} ASC_SCSI_Q;
394
395typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400396 ASC_SCSIQ_1 r1;
397 ASC_SCSIQ_2 r2;
398 uchar *cdbptr;
399 ASC_SG_HEAD *sg_head;
400 uchar *sense_ptr;
401 ASC_SCSIQ_3 r3;
402 uchar cdb[ASC_MAX_CDB_LEN];
403 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404} ASC_SCSI_REQ_Q;
405
406typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400407 ASC_SCSIQ_1 r1;
408 ASC_SCSIQ_2 r2;
409 uchar *cdbptr;
410 ASC_SG_HEAD *sg_head;
411 uchar *sense_ptr;
412 ASC_SCSIQ_3 r3;
413 uchar cdb[ASC_MAX_CDB_LEN];
414 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415} ASC_SCSI_BIOS_REQ_Q;
416
417typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400418 uchar fwd;
419 uchar bwd;
420 ASC_SCSIQ_1 i1;
421 ASC_SCSIQ_2 i2;
422 ASC_SCSIQ_3 i3;
423 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424} ASC_RISC_Q;
425
426typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400427 uchar seq_no;
428 uchar q_no;
429 uchar cntl;
430 uchar sg_head_qp;
431 uchar sg_list_cnt;
432 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433} ASC_SG_LIST_Q;
434
435typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400436 uchar fwd;
437 uchar bwd;
438 ASC_SG_LIST_Q sg;
439 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440} ASC_RISC_SG_LIST_Q;
441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442#define ASCQ_ERR_Q_STATUS 0x0D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443#define ASCQ_ERR_CUR_QNG 0x17
444#define ASCQ_ERR_SG_Q_LINKS 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
446#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
447#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449/*
450 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
451 */
452#define ASC_WARN_NO_ERROR 0x0000
453#define ASC_WARN_IO_PORT_ROTATE 0x0001
454#define ASC_WARN_EEPROM_CHKSUM 0x0002
455#define ASC_WARN_IRQ_MODIFIED 0x0004
456#define ASC_WARN_AUTO_CONFIG 0x0008
457#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
458#define ASC_WARN_EEPROM_RECOVER 0x0020
459#define ASC_WARN_CFG_MSW_RECOVER 0x0040
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461/*
462 * Error code values are set in ASC_DVC_VAR 'err_code'.
463 */
464#define ASC_IERR_WRITE_EEPROM 0x0001
465#define ASC_IERR_MCODE_CHKSUM 0x0002
466#define ASC_IERR_SET_PC_ADDR 0x0004
467#define ASC_IERR_START_STOP_CHIP 0x0008
468#define ASC_IERR_IRQ_NO 0x0010
469#define ASC_IERR_SET_IRQ_NO 0x0020
470#define ASC_IERR_CHIP_VERSION 0x0040
471#define ASC_IERR_SET_SCSI_ID 0x0080
472#define ASC_IERR_GET_PHY_ADDR 0x0100
473#define ASC_IERR_BAD_SIGNATURE 0x0200
474#define ASC_IERR_NO_BUS_TYPE 0x0400
475#define ASC_IERR_SCAM 0x0800
476#define ASC_IERR_SET_SDTR 0x1000
477#define ASC_IERR_RW_LRAM 0x8000
478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479#define ASC_MAX_IRQ_NO 15
480#define ASC_MIN_IRQ_NO 10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
482#define ASC_MIN_TAG_Q_PER_DVC (0x04)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600483#define ASC_MIN_FREE_Q (0x02)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
485#define ASC_MAX_TOTAL_QNG 240
486#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
487#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
488#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
489#define ASC_MAX_INRAM_TAG_QNG 16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491#define ASC_MAX_SYN_XFER_NO 16
492#define ASC_SYN_MAX_OFFSET 0x0F
493#define ASC_DEF_SDTR_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
495#define SYN_XFER_NS_0 25
496#define SYN_XFER_NS_1 30
497#define SYN_XFER_NS_2 35
498#define SYN_XFER_NS_3 40
499#define SYN_XFER_NS_4 50
500#define SYN_XFER_NS_5 60
501#define SYN_XFER_NS_6 70
502#define SYN_XFER_NS_7 85
503#define SYN_ULTRA_XFER_NS_0 12
504#define SYN_ULTRA_XFER_NS_1 19
505#define SYN_ULTRA_XFER_NS_2 25
506#define SYN_ULTRA_XFER_NS_3 32
507#define SYN_ULTRA_XFER_NS_4 38
508#define SYN_ULTRA_XFER_NS_5 44
509#define SYN_ULTRA_XFER_NS_6 50
510#define SYN_ULTRA_XFER_NS_7 57
511#define SYN_ULTRA_XFER_NS_8 63
512#define SYN_ULTRA_XFER_NS_9 69
513#define SYN_ULTRA_XFER_NS_10 75
514#define SYN_ULTRA_XFER_NS_11 82
515#define SYN_ULTRA_XFER_NS_12 88
516#define SYN_ULTRA_XFER_NS_13 94
517#define SYN_ULTRA_XFER_NS_14 100
518#define SYN_ULTRA_XFER_NS_15 107
519
520typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400521 uchar msg_type;
522 uchar msg_len;
523 uchar msg_req;
524 union {
525 struct {
526 uchar sdtr_xfer_period;
527 uchar sdtr_req_ack_offset;
528 } sdtr;
529 struct {
530 uchar wdtr_width;
531 } wdtr;
532 struct {
533 uchar mdp_b3;
534 uchar mdp_b2;
535 uchar mdp_b1;
536 uchar mdp_b0;
537 } mdp;
538 } u_ext_msg;
539 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540} EXT_MSG;
541
542#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
543#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
544#define wdtr_width u_ext_msg.wdtr.wdtr_width
545#define mdp_b3 u_ext_msg.mdp_b3
546#define mdp_b2 u_ext_msg.mdp_b2
547#define mdp_b1 u_ext_msg.mdp_b1
548#define mdp_b0 u_ext_msg.mdp_b0
549
550typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400551 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
552 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
553 ASC_SCSI_BIT_ID_TYPE disc_enable;
554 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
555 uchar chip_scsi_id;
556 uchar isa_dma_speed;
557 uchar isa_dma_channel;
558 uchar chip_version;
559 ushort lib_serial_no;
560 ushort lib_version;
561 ushort mcode_date;
562 ushort mcode_version;
563 uchar max_tag_qng[ASC_MAX_TID + 1];
564 uchar *overrun_buf;
565 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400566 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567} ASC_DVC_CFG;
568
569#define ASC_DEF_DVC_CNTL 0xFFFF
570#define ASC_DEF_CHIP_SCSI_ID 7
571#define ASC_DEF_ISA_DMA_SPEED 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
573#define ASC_INIT_STATE_END_GET_CFG 0x0002
574#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
575#define ASC_INIT_STATE_END_SET_CFG 0x0008
576#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
577#define ASC_INIT_STATE_END_LOAD_MC 0x0020
578#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
579#define ASC_INIT_STATE_END_INQUIRY 0x0080
580#define ASC_INIT_RESET_SCSI_DONE 0x0100
581#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
583#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
584#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
585#define ASC_MIN_TAGGED_CMD 7
586#define ASC_MAX_SCSI_RESET_WAIT 30
587
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400588struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400591 PortAddr iop_base;
592 ushort err_code;
593 ushort dvc_cntl;
594 ushort bug_fix_cntl;
595 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400596 ASC_SCSI_BIT_ID_TYPE init_sdtr;
597 ASC_SCSI_BIT_ID_TYPE sdtr_done;
598 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
599 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
600 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
601 ASC_SCSI_BIT_ID_TYPE start_motor;
602 uchar scsi_reset_wait;
603 uchar chip_no;
604 char is_in_int;
605 uchar max_total_qng;
606 uchar cur_total_qng;
607 uchar in_critical_cnt;
608 uchar irq_no;
609 uchar last_q_shortage;
610 ushort init_state;
611 uchar cur_dvc_qng[ASC_MAX_TID + 1];
612 uchar max_dvc_qng[ASC_MAX_TID + 1];
613 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
614 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
615 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
616 ASC_DVC_CFG *cfg;
617 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
618 char redo_scam;
619 ushort res2;
620 uchar dos_int13_table[ASC_MAX_TID + 1];
621 ASC_DCNT max_dma_count;
622 ASC_SCSI_BIT_ID_TYPE no_scam;
623 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
624 uchar max_sdtr_index;
625 uchar host_init_sdtr_index;
626 struct asc_board *drv_ptr;
627 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628} ASC_DVC_VAR;
629
630typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400631 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632} ASC_DVC_INQ_INFO;
633
634typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400635 ASC_DCNT lba;
636 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637} ASC_CAP_INFO;
638
639typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400640 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641} ASC_CAP_INFO_ARRAY;
642
643#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
644#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
645#define ASC_CNTL_INITIATOR (ushort)0x0001
646#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
647#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
648#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
649#define ASC_CNTL_NO_SCAM (ushort)0x0010
650#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
651#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
652#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
653#define ASC_CNTL_RESET_SCSI (ushort)0x0200
654#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
655#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
656#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
657#define ASC_CNTL_BURST_MODE (ushort)0x2000
658#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
659#define ASC_EEP_DVC_CFG_BEG_VL 2
660#define ASC_EEP_MAX_DVC_ADDR_VL 15
661#define ASC_EEP_DVC_CFG_BEG 32
662#define ASC_EEP_MAX_DVC_ADDR 45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663#define ASC_EEP_MAX_RETRY 20
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
665/*
666 * These macros keep the chip SCSI id and ISA DMA speed
667 * bitfields in board order. C bitfields aren't portable
668 * between big and little-endian platforms so they are
669 * not used.
670 */
671
672#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
673#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
674#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
675 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
676#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
677 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
678
679typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400680 ushort cfg_lsw;
681 ushort cfg_msw;
682 uchar init_sdtr;
683 uchar disc_enable;
684 uchar use_cmd_qng;
685 uchar start_motor;
686 uchar max_total_qng;
687 uchar max_tag_qng;
688 uchar bios_scan;
689 uchar power_up_wait;
690 uchar no_scam;
691 uchar id_speed; /* low order 4 bits is chip scsi id */
692 /* high order 4 bits is isa dma speed */
693 uchar dos_int13_table[ASC_MAX_TID + 1];
694 uchar adapter_info[6];
695 ushort cntl;
696 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697} ASCEEP_CONFIG;
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699#define ASC_EEP_CMD_READ 0x80
700#define ASC_EEP_CMD_WRITE 0x40
701#define ASC_EEP_CMD_WRITE_ABLE 0x30
702#define ASC_EEP_CMD_WRITE_DISABLE 0x00
703#define ASC_OVERRUN_BSIZE 0x00000048UL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704#define ASCV_MSGOUT_BEG 0x0000
705#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
706#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
707#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
708#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
709#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
710#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
711#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
712#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
713#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
714#define ASCV_BREAK_ADDR (ushort)0x0028
715#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
716#define ASCV_BREAK_CONTROL (ushort)0x002C
717#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
718
719#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
720#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
721#define ASCV_MCODE_SIZE_W (ushort)0x0034
722#define ASCV_STOP_CODE_B (ushort)0x0036
723#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
724#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
725#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
726#define ASCV_HALTCODE_W (ushort)0x0040
727#define ASCV_CHKSUM_W (ushort)0x0042
728#define ASCV_MC_DATE_W (ushort)0x0044
729#define ASCV_MC_VER_W (ushort)0x0046
730#define ASCV_NEXTRDY_B (ushort)0x0048
731#define ASCV_DONENEXT_B (ushort)0x0049
732#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
733#define ASCV_SCSIBUSY_B (ushort)0x004B
734#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
735#define ASCV_CURCDB_B (ushort)0x004D
736#define ASCV_RCLUN_B (ushort)0x004E
737#define ASCV_BUSY_QHEAD_B (ushort)0x004F
738#define ASCV_DISC1_QHEAD_B (ushort)0x0050
739#define ASCV_DISC_ENABLE_B (ushort)0x0052
740#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
741#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
742#define ASCV_MCODE_CNTL_B (ushort)0x0056
743#define ASCV_NULL_TARGET_B (ushort)0x0057
744#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
745#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
746#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
747#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
748#define ASCV_HOST_FLAG_B (ushort)0x005D
749#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
750#define ASCV_VER_SERIAL_B (ushort)0x0065
751#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
752#define ASCV_WTM_FLAG_B (ushort)0x0068
753#define ASCV_RISC_FLAG_B (ushort)0x006A
754#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
755#define ASC_HOST_FLAG_IN_ISR 0x01
756#define ASC_HOST_FLAG_ACK_INT 0x02
757#define ASC_RISC_FLAG_GEN_INT 0x01
758#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
759#define IOP_CTRL (0x0F)
760#define IOP_STATUS (0x0E)
761#define IOP_INT_ACK IOP_STATUS
762#define IOP_REG_IFC (0x0D)
763#define IOP_SYN_OFFSET (0x0B)
764#define IOP_EXTRA_CONTROL (0x0D)
765#define IOP_REG_PC (0x0C)
766#define IOP_RAM_ADDR (0x0A)
767#define IOP_RAM_DATA (0x08)
768#define IOP_EEP_DATA (0x06)
769#define IOP_EEP_CMD (0x07)
770#define IOP_VERSION (0x03)
771#define IOP_CONFIG_HIGH (0x04)
772#define IOP_CONFIG_LOW (0x02)
773#define IOP_SIG_BYTE (0x01)
774#define IOP_SIG_WORD (0x00)
775#define IOP_REG_DC1 (0x0E)
776#define IOP_REG_DC0 (0x0C)
777#define IOP_REG_SB (0x0B)
778#define IOP_REG_DA1 (0x0A)
779#define IOP_REG_DA0 (0x08)
780#define IOP_REG_SC (0x09)
781#define IOP_DMA_SPEED (0x07)
782#define IOP_REG_FLAG (0x07)
783#define IOP_FIFO_H (0x06)
784#define IOP_FIFO_L (0x04)
785#define IOP_REG_ID (0x05)
786#define IOP_REG_QP (0x03)
787#define IOP_REG_IH (0x02)
788#define IOP_REG_IX (0x01)
789#define IOP_REG_AX (0x00)
790#define IFC_REG_LOCK (0x00)
791#define IFC_REG_UNLOCK (0x09)
792#define IFC_WR_EN_FILTER (0x10)
793#define IFC_RD_NO_EEPROM (0x10)
794#define IFC_SLEW_RATE (0x20)
795#define IFC_ACT_NEG (0x40)
796#define IFC_INP_FILTER (0x80)
797#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
798#define SC_SEL (uchar)(0x80)
799#define SC_BSY (uchar)(0x40)
800#define SC_ACK (uchar)(0x20)
801#define SC_REQ (uchar)(0x10)
802#define SC_ATN (uchar)(0x08)
803#define SC_IO (uchar)(0x04)
804#define SC_CD (uchar)(0x02)
805#define SC_MSG (uchar)(0x01)
806#define SEC_SCSI_CTL (uchar)(0x80)
807#define SEC_ACTIVE_NEGATE (uchar)(0x40)
808#define SEC_SLEW_RATE (uchar)(0x20)
809#define SEC_ENABLE_FILTER (uchar)(0x10)
810#define ASC_HALT_EXTMSG_IN (ushort)0x8000
811#define ASC_HALT_CHK_CONDITION (ushort)0x8100
812#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
813#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
814#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
815#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
816#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
817#define ASC_MAX_QNO 0xF8
818#define ASC_DATA_SEC_BEG (ushort)0x0080
819#define ASC_DATA_SEC_END (ushort)0x0080
820#define ASC_CODE_SEC_BEG (ushort)0x0080
821#define ASC_CODE_SEC_END (ushort)0x0080
822#define ASC_QADR_BEG (0x4000)
823#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
824#define ASC_QADR_END (ushort)0x7FFF
825#define ASC_QLAST_ADR (ushort)0x7FC0
826#define ASC_QBLK_SIZE 0x40
827#define ASC_BIOS_DATA_QBEG 0xF8
828#define ASC_MIN_ACTIVE_QNO 0x01
829#define ASC_QLINK_END 0xFF
830#define ASC_EEPROM_WORDS 0x10
831#define ASC_MAX_MGS_LEN 0x10
832#define ASC_BIOS_ADDR_DEF 0xDC00
833#define ASC_BIOS_SIZE 0x3800
834#define ASC_BIOS_RAM_OFF 0x3800
835#define ASC_BIOS_RAM_SIZE 0x800
836#define ASC_BIOS_MIN_ADDR 0xC000
837#define ASC_BIOS_MAX_ADDR 0xEC00
838#define ASC_BIOS_BANK_SIZE 0x0400
839#define ASC_MCODE_START_ADDR 0x0080
840#define ASC_CFG0_HOST_INT_ON 0x0020
841#define ASC_CFG0_BIOS_ON 0x0040
842#define ASC_CFG0_VERA_BURST_ON 0x0080
843#define ASC_CFG0_SCSI_PARITY_ON 0x0800
844#define ASC_CFG1_SCSI_TARGET_ON 0x0080
845#define ASC_CFG1_LRAM_8BITS_ON 0x0800
846#define ASC_CFG_MSW_CLR_MASK 0x3080
847#define CSW_TEST1 (ASC_CS_TYPE)0x8000
848#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
849#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
850#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
851#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
852#define CSW_TEST2 (ASC_CS_TYPE)0x0400
853#define CSW_TEST3 (ASC_CS_TYPE)0x0200
854#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
855#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
856#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
857#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
858#define CSW_HALTED (ASC_CS_TYPE)0x0010
859#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
860#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
861#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
862#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
863#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
864#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
865#define CIW_TEST1 (ASC_CS_TYPE)0x0200
866#define CIW_TEST2 (ASC_CS_TYPE)0x0400
867#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
868#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
869#define CC_CHIP_RESET (uchar)0x80
870#define CC_SCSI_RESET (uchar)0x40
871#define CC_HALT (uchar)0x20
872#define CC_SINGLE_STEP (uchar)0x10
873#define CC_DMA_ABLE (uchar)0x08
874#define CC_TEST (uchar)0x04
875#define CC_BANK_ONE (uchar)0x02
876#define CC_DIAG (uchar)0x01
877#define ASC_1000_ID0W 0x04C1
878#define ASC_1000_ID0W_FIX 0x00C1
879#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880#define ASC_EISA_REV_IOP_MASK (0x0C83)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881#define ASC_EISA_CFG_IOP_MASK (0x0C86)
882#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883#define INS_HALTINT (ushort)0x6281
884#define INS_HALT (ushort)0x6280
885#define INS_SINT (ushort)0x6200
886#define INS_RFLAG_WTM (ushort)0x7380
887#define ASC_MC_SAVE_CODE_WSIZE 0x500
888#define ASC_MC_SAVE_DATA_WSIZE 0x40
889
890typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400891 ushort data[ASC_MC_SAVE_DATA_WSIZE];
892 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893} ASC_MC_SAVED;
894
895#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
896#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
897#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
898#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
899#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
900#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
901#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
902#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
903#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
904#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
Matthew Wilcox51219352007-10-02 21:55:22 -0400905#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data))
906#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id))
907#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data)
908#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
910#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
911#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
912#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
913#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
914#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
915#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
916#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
917#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
918#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
919#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
920#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
921#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
922#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
923#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
924#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
925#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
926#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
927#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
928#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
929#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
930#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
931#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
932#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
933#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
934#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
935#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
936#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
937#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
938#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
939#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
940#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
941#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
942#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
943#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
944#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
945#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
946#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
947#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
948#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
949#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
950#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
951#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
952#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
953#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
954#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
955#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
956#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
957#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
958#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
959#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
960#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
961#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
962#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
963
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964#define ADV_LIB_VERSION_MAJOR 5
965#define ADV_LIB_VERSION_MINOR 14
966
967/*
968 * Define Adv Library required special types.
969 */
970
971/*
972 * Portable Data Types
973 *
974 * Any instance where a 32-bit long or pointer type is assumed
975 * for precision or HW defined structures, the following define
976 * types must be used. In Linux the char, short, and int types
977 * are all consistent at 8, 16, and 32 bits respectively. Pointers
978 * and long types are 64 bits on Alpha and UltraSPARC.
979 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400980#define ADV_PADDR __u32 /* Physical address data type. */
981#define ADV_VADDR __u32 /* Virtual address data type. */
982#define ADV_DCNT __u32 /* Unsigned Data count type. */
983#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
985/*
986 * These macros are used to convert a virtual address to a
987 * 32-bit value. This currently can be used on Linux Alpha
988 * which uses 64-bit virtual address but a 32-bit bus address.
989 * This is likely to break in the future, but doing this now
990 * will give us time to change the HW and FW to handle 64-bit
991 * addresses.
992 */
993#define ADV_VADDR_TO_U32 virt_to_bus
994#define ADV_U32_TO_VADDR bus_to_virt
995
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400996#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998/*
999 * Define Adv Library required memory access macros.
1000 */
1001#define ADV_MEM_READB(addr) readb(addr)
1002#define ADV_MEM_READW(addr) readw(addr)
1003#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1004#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1005#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1006
1007#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1008
1009/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 * Define total number of simultaneous maximum element scatter-gather
1011 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1012 * maximum number of outstanding commands per wide host adapter. Each
1013 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1014 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1015 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1016 * structures or 255 scatter-gather elements.
1017 *
1018 */
1019#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1020
1021/*
1022 * Define Adv Library required maximum number of scatter-gather
1023 * elements per request.
1024 */
1025#define ADV_MAX_SG_LIST 255
1026
1027/* Number of SG blocks needed. */
1028#define ADV_NUM_SG_BLOCK \
1029 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1030
1031/* Total contiguous memory needed for SG blocks. */
1032#define ADV_SG_TOTAL_MEM_SIZE \
1033 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1034
1035#define ADV_PAGE_SIZE PAGE_SIZE
1036
1037#define ADV_NUM_PAGE_CROSSING \
1038 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1041#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001042#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1044
1045#define ADV_EEP_DELAY_MS 100
1046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001047#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1048#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049/*
1050 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1051 * For later ICs Bit 13 controls whether the CIS (Card Information
1052 * Service Section) is loaded from EEPROM.
1053 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001054#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1055#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056/*
1057 * ASC38C1600 Bit 11
1058 *
1059 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1060 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1061 * Function 0 will specify INT B.
1062 *
1063 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1064 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1065 * Function 1 will specify INT A.
1066 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001067#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001069typedef struct adveep_3550_config {
1070 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001072 ushort cfg_lsw; /* 00 power up initialization */
1073 /* bit 13 set - Term Polarity Control */
1074 /* bit 14 set - BIOS Enable */
1075 /* bit 15 set - Big Endian Mode */
1076 ushort cfg_msw; /* 01 unused */
1077 ushort disc_enable; /* 02 disconnect enable */
1078 ushort wdtr_able; /* 03 Wide DTR able */
1079 ushort sdtr_able; /* 04 Synchronous DTR able */
1080 ushort start_motor; /* 05 send start up motor */
1081 ushort tagqng_able; /* 06 tag queuing able */
1082 ushort bios_scan; /* 07 BIOS device control */
1083 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001085 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1086 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001088 uchar scsi_reset_delay; /* 10 reset delay */
1089 uchar bios_id_lun; /* first boot device scsi id & lun */
1090 /* high nibble is lun */
1091 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001093 uchar termination; /* 11 0 - automatic */
1094 /* 1 - low off / high off */
1095 /* 2 - low off / high on */
1096 /* 3 - low on / high on */
1097 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001099 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001101 ushort bios_ctrl; /* 12 BIOS control bits */
1102 /* bit 0 BIOS don't act as initiator. */
1103 /* bit 1 BIOS > 1 GB support */
1104 /* bit 2 BIOS > 2 Disk Support */
1105 /* bit 3 BIOS don't support removables */
1106 /* bit 4 BIOS support bootable CD */
1107 /* bit 5 BIOS scan enabled */
1108 /* bit 6 BIOS support multiple LUNs */
1109 /* bit 7 BIOS display of message */
1110 /* bit 8 SCAM disabled */
1111 /* bit 9 Reset SCSI bus during init. */
1112 /* bit 10 */
1113 /* bit 11 No verbose initialization. */
1114 /* bit 12 SCSI parity enabled */
1115 /* bit 13 */
1116 /* bit 14 */
1117 /* bit 15 */
1118 ushort ultra_able; /* 13 ULTRA speed able */
1119 ushort reserved2; /* 14 reserved */
1120 uchar max_host_qng; /* 15 maximum host queuing */
1121 uchar max_dvc_qng; /* maximum per device queuing */
1122 ushort dvc_cntl; /* 16 control bit for driver */
1123 ushort bug_fix; /* 17 control bit for bug fix */
1124 ushort serial_number_word1; /* 18 Board serial number word 1 */
1125 ushort serial_number_word2; /* 19 Board serial number word 2 */
1126 ushort serial_number_word3; /* 20 Board serial number word 3 */
1127 ushort check_sum; /* 21 EEP check sum */
1128 uchar oem_name[16]; /* 22 OEM name */
1129 ushort dvc_err_code; /* 30 last device driver error code */
1130 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1131 ushort adv_err_addr; /* 32 last uc error address */
1132 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1133 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1134 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1135 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136} ADVEEP_3550_CONFIG;
1137
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001138typedef struct adveep_38C0800_config {
1139 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001141 ushort cfg_lsw; /* 00 power up initialization */
1142 /* bit 13 set - Load CIS */
1143 /* bit 14 set - BIOS Enable */
1144 /* bit 15 set - Big Endian Mode */
1145 ushort cfg_msw; /* 01 unused */
1146 ushort disc_enable; /* 02 disconnect enable */
1147 ushort wdtr_able; /* 03 Wide DTR able */
1148 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1149 ushort start_motor; /* 05 send start up motor */
1150 ushort tagqng_able; /* 06 tag queuing able */
1151 ushort bios_scan; /* 07 BIOS device control */
1152 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001154 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1155 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001157 uchar scsi_reset_delay; /* 10 reset delay */
1158 uchar bios_id_lun; /* first boot device scsi id & lun */
1159 /* high nibble is lun */
1160 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001162 uchar termination_se; /* 11 0 - automatic */
1163 /* 1 - low off / high off */
1164 /* 2 - low off / high on */
1165 /* 3 - low on / high on */
1166 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001168 uchar termination_lvd; /* 11 0 - automatic */
1169 /* 1 - low off / high off */
1170 /* 2 - low off / high on */
1171 /* 3 - low on / high on */
1172 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001174 ushort bios_ctrl; /* 12 BIOS control bits */
1175 /* bit 0 BIOS don't act as initiator. */
1176 /* bit 1 BIOS > 1 GB support */
1177 /* bit 2 BIOS > 2 Disk Support */
1178 /* bit 3 BIOS don't support removables */
1179 /* bit 4 BIOS support bootable CD */
1180 /* bit 5 BIOS scan enabled */
1181 /* bit 6 BIOS support multiple LUNs */
1182 /* bit 7 BIOS display of message */
1183 /* bit 8 SCAM disabled */
1184 /* bit 9 Reset SCSI bus during init. */
1185 /* bit 10 */
1186 /* bit 11 No verbose initialization. */
1187 /* bit 12 SCSI parity enabled */
1188 /* bit 13 */
1189 /* bit 14 */
1190 /* bit 15 */
1191 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1192 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1193 uchar max_host_qng; /* 15 maximum host queueing */
1194 uchar max_dvc_qng; /* maximum per device queuing */
1195 ushort dvc_cntl; /* 16 control bit for driver */
1196 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1197 ushort serial_number_word1; /* 18 Board serial number word 1 */
1198 ushort serial_number_word2; /* 19 Board serial number word 2 */
1199 ushort serial_number_word3; /* 20 Board serial number word 3 */
1200 ushort check_sum; /* 21 EEP check sum */
1201 uchar oem_name[16]; /* 22 OEM name */
1202 ushort dvc_err_code; /* 30 last device driver error code */
1203 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1204 ushort adv_err_addr; /* 32 last uc error address */
1205 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1206 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1207 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1208 ushort reserved36; /* 36 reserved */
1209 ushort reserved37; /* 37 reserved */
1210 ushort reserved38; /* 38 reserved */
1211 ushort reserved39; /* 39 reserved */
1212 ushort reserved40; /* 40 reserved */
1213 ushort reserved41; /* 41 reserved */
1214 ushort reserved42; /* 42 reserved */
1215 ushort reserved43; /* 43 reserved */
1216 ushort reserved44; /* 44 reserved */
1217 ushort reserved45; /* 45 reserved */
1218 ushort reserved46; /* 46 reserved */
1219 ushort reserved47; /* 47 reserved */
1220 ushort reserved48; /* 48 reserved */
1221 ushort reserved49; /* 49 reserved */
1222 ushort reserved50; /* 50 reserved */
1223 ushort reserved51; /* 51 reserved */
1224 ushort reserved52; /* 52 reserved */
1225 ushort reserved53; /* 53 reserved */
1226 ushort reserved54; /* 54 reserved */
1227 ushort reserved55; /* 55 reserved */
1228 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1229 ushort cisprt_msw; /* 57 CIS PTR MSW */
1230 ushort subsysvid; /* 58 SubSystem Vendor ID */
1231 ushort subsysid; /* 59 SubSystem ID */
1232 ushort reserved60; /* 60 reserved */
1233 ushort reserved61; /* 61 reserved */
1234 ushort reserved62; /* 62 reserved */
1235 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236} ADVEEP_38C0800_CONFIG;
1237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001238typedef struct adveep_38C1600_config {
1239 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001241 ushort cfg_lsw; /* 00 power up initialization */
1242 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1243 /* clear - Func. 0 INTA, Func. 1 INTB */
1244 /* bit 13 set - Load CIS */
1245 /* bit 14 set - BIOS Enable */
1246 /* bit 15 set - Big Endian Mode */
1247 ushort cfg_msw; /* 01 unused */
1248 ushort disc_enable; /* 02 disconnect enable */
1249 ushort wdtr_able; /* 03 Wide DTR able */
1250 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1251 ushort start_motor; /* 05 send start up motor */
1252 ushort tagqng_able; /* 06 tag queuing able */
1253 ushort bios_scan; /* 07 BIOS device control */
1254 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001256 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1257 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001259 uchar scsi_reset_delay; /* 10 reset delay */
1260 uchar bios_id_lun; /* first boot device scsi id & lun */
1261 /* high nibble is lun */
1262 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001264 uchar termination_se; /* 11 0 - automatic */
1265 /* 1 - low off / high off */
1266 /* 2 - low off / high on */
1267 /* 3 - low on / high on */
1268 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001270 uchar termination_lvd; /* 11 0 - automatic */
1271 /* 1 - low off / high off */
1272 /* 2 - low off / high on */
1273 /* 3 - low on / high on */
1274 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001276 ushort bios_ctrl; /* 12 BIOS control bits */
1277 /* bit 0 BIOS don't act as initiator. */
1278 /* bit 1 BIOS > 1 GB support */
1279 /* bit 2 BIOS > 2 Disk Support */
1280 /* bit 3 BIOS don't support removables */
1281 /* bit 4 BIOS support bootable CD */
1282 /* bit 5 BIOS scan enabled */
1283 /* bit 6 BIOS support multiple LUNs */
1284 /* bit 7 BIOS display of message */
1285 /* bit 8 SCAM disabled */
1286 /* bit 9 Reset SCSI bus during init. */
1287 /* bit 10 Basic Integrity Checking disabled */
1288 /* bit 11 No verbose initialization. */
1289 /* bit 12 SCSI parity enabled */
1290 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1291 /* bit 14 */
1292 /* bit 15 */
1293 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1294 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1295 uchar max_host_qng; /* 15 maximum host queueing */
1296 uchar max_dvc_qng; /* maximum per device queuing */
1297 ushort dvc_cntl; /* 16 control bit for driver */
1298 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1299 ushort serial_number_word1; /* 18 Board serial number word 1 */
1300 ushort serial_number_word2; /* 19 Board serial number word 2 */
1301 ushort serial_number_word3; /* 20 Board serial number word 3 */
1302 ushort check_sum; /* 21 EEP check sum */
1303 uchar oem_name[16]; /* 22 OEM name */
1304 ushort dvc_err_code; /* 30 last device driver error code */
1305 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1306 ushort adv_err_addr; /* 32 last uc error address */
1307 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1308 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1309 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1310 ushort reserved36; /* 36 reserved */
1311 ushort reserved37; /* 37 reserved */
1312 ushort reserved38; /* 38 reserved */
1313 ushort reserved39; /* 39 reserved */
1314 ushort reserved40; /* 40 reserved */
1315 ushort reserved41; /* 41 reserved */
1316 ushort reserved42; /* 42 reserved */
1317 ushort reserved43; /* 43 reserved */
1318 ushort reserved44; /* 44 reserved */
1319 ushort reserved45; /* 45 reserved */
1320 ushort reserved46; /* 46 reserved */
1321 ushort reserved47; /* 47 reserved */
1322 ushort reserved48; /* 48 reserved */
1323 ushort reserved49; /* 49 reserved */
1324 ushort reserved50; /* 50 reserved */
1325 ushort reserved51; /* 51 reserved */
1326 ushort reserved52; /* 52 reserved */
1327 ushort reserved53; /* 53 reserved */
1328 ushort reserved54; /* 54 reserved */
1329 ushort reserved55; /* 55 reserved */
1330 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1331 ushort cisprt_msw; /* 57 CIS PTR MSW */
1332 ushort subsysvid; /* 58 SubSystem Vendor ID */
1333 ushort subsysid; /* 59 SubSystem ID */
1334 ushort reserved60; /* 60 reserved */
1335 ushort reserved61; /* 61 reserved */
1336 ushort reserved62; /* 62 reserved */
1337 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338} ADVEEP_38C1600_CONFIG;
1339
1340/*
1341 * EEPROM Commands
1342 */
1343#define ASC_EEP_CMD_DONE 0x0200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
1345/* bios_ctrl */
1346#define BIOS_CTRL_BIOS 0x0001
1347#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1348#define BIOS_CTRL_GT_2_DISK 0x0004
1349#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1350#define BIOS_CTRL_BOOTABLE_CD 0x0010
1351#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1352#define BIOS_CTRL_DISPLAY_MSG 0x0080
1353#define BIOS_CTRL_NO_SCAM 0x0100
1354#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1355#define BIOS_CTRL_INIT_VERBOSE 0x0800
1356#define BIOS_CTRL_SCSI_PARITY 0x1000
1357#define BIOS_CTRL_AIPP_DIS 0x2000
1358
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001359#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001361#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363/*
1364 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1365 * a special 16K Adv Library and Microcode version. After the issue is
1366 * resolved, should restore 32K support.
1367 *
1368 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1369 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001370#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372/*
1373 * Byte I/O register address from base of 'iop_base'.
1374 */
1375#define IOPB_INTR_STATUS_REG 0x00
1376#define IOPB_CHIP_ID_1 0x01
1377#define IOPB_INTR_ENABLES 0x02
1378#define IOPB_CHIP_TYPE_REV 0x03
1379#define IOPB_RES_ADDR_4 0x04
1380#define IOPB_RES_ADDR_5 0x05
1381#define IOPB_RAM_DATA 0x06
1382#define IOPB_RES_ADDR_7 0x07
1383#define IOPB_FLAG_REG 0x08
1384#define IOPB_RES_ADDR_9 0x09
1385#define IOPB_RISC_CSR 0x0A
1386#define IOPB_RES_ADDR_B 0x0B
1387#define IOPB_RES_ADDR_C 0x0C
1388#define IOPB_RES_ADDR_D 0x0D
1389#define IOPB_SOFT_OVER_WR 0x0E
1390#define IOPB_RES_ADDR_F 0x0F
1391#define IOPB_MEM_CFG 0x10
1392#define IOPB_RES_ADDR_11 0x11
1393#define IOPB_GPIO_DATA 0x12
1394#define IOPB_RES_ADDR_13 0x13
1395#define IOPB_FLASH_PAGE 0x14
1396#define IOPB_RES_ADDR_15 0x15
1397#define IOPB_GPIO_CNTL 0x16
1398#define IOPB_RES_ADDR_17 0x17
1399#define IOPB_FLASH_DATA 0x18
1400#define IOPB_RES_ADDR_19 0x19
1401#define IOPB_RES_ADDR_1A 0x1A
1402#define IOPB_RES_ADDR_1B 0x1B
1403#define IOPB_RES_ADDR_1C 0x1C
1404#define IOPB_RES_ADDR_1D 0x1D
1405#define IOPB_RES_ADDR_1E 0x1E
1406#define IOPB_RES_ADDR_1F 0x1F
1407#define IOPB_DMA_CFG0 0x20
1408#define IOPB_DMA_CFG1 0x21
1409#define IOPB_TICKLE 0x22
1410#define IOPB_DMA_REG_WR 0x23
1411#define IOPB_SDMA_STATUS 0x24
1412#define IOPB_SCSI_BYTE_CNT 0x25
1413#define IOPB_HOST_BYTE_CNT 0x26
1414#define IOPB_BYTE_LEFT_TO_XFER 0x27
1415#define IOPB_BYTE_TO_XFER_0 0x28
1416#define IOPB_BYTE_TO_XFER_1 0x29
1417#define IOPB_BYTE_TO_XFER_2 0x2A
1418#define IOPB_BYTE_TO_XFER_3 0x2B
1419#define IOPB_ACC_GRP 0x2C
1420#define IOPB_RES_ADDR_2D 0x2D
1421#define IOPB_DEV_ID 0x2E
1422#define IOPB_RES_ADDR_2F 0x2F
1423#define IOPB_SCSI_DATA 0x30
1424#define IOPB_RES_ADDR_31 0x31
1425#define IOPB_RES_ADDR_32 0x32
1426#define IOPB_SCSI_DATA_HSHK 0x33
1427#define IOPB_SCSI_CTRL 0x34
1428#define IOPB_RES_ADDR_35 0x35
1429#define IOPB_RES_ADDR_36 0x36
1430#define IOPB_RES_ADDR_37 0x37
1431#define IOPB_RAM_BIST 0x38
1432#define IOPB_PLL_TEST 0x39
1433#define IOPB_PCI_INT_CFG 0x3A
1434#define IOPB_RES_ADDR_3B 0x3B
1435#define IOPB_RFIFO_CNT 0x3C
1436#define IOPB_RES_ADDR_3D 0x3D
1437#define IOPB_RES_ADDR_3E 0x3E
1438#define IOPB_RES_ADDR_3F 0x3F
1439
1440/*
1441 * Word I/O register address from base of 'iop_base'.
1442 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001443#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1444#define IOPW_CTRL_REG 0x02 /* CC */
1445#define IOPW_RAM_ADDR 0x04 /* LA */
1446#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001448#define IOPW_RISC_CSR 0x0A /* CSR */
1449#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1450#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001452#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001454#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001456#define IOPW_EE_CMD 0x1A /* EC */
1457#define IOPW_EE_DATA 0x1C /* ED */
1458#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001460#define IOPW_Q_BASE 0x22 /* QB */
1461#define IOPW_QP 0x24 /* QP */
1462#define IOPW_IX 0x26 /* IX */
1463#define IOPW_SP 0x28 /* SP */
1464#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465#define IOPW_RES_ADDR_2C 0x2C
1466#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001467#define IOPW_SCSI_DATA 0x30 /* SD */
1468#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1469#define IOPW_SCSI_CTRL 0x34 /* SC */
1470#define IOPW_HSHK_CFG 0x36 /* HCFG */
1471#define IOPW_SXFR_STATUS 0x36 /* SXS */
1472#define IOPW_SXFR_CNTL 0x38 /* SXL */
1473#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001475#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
1477/*
1478 * Doubleword I/O register address from base of 'iop_base'.
1479 */
1480#define IOPDW_RES_ADDR_0 0x00
1481#define IOPDW_RAM_DATA 0x04
1482#define IOPDW_RES_ADDR_8 0x08
1483#define IOPDW_RES_ADDR_C 0x0C
1484#define IOPDW_RES_ADDR_10 0x10
1485#define IOPDW_COMMA 0x14
1486#define IOPDW_COMMB 0x18
1487#define IOPDW_RES_ADDR_1C 0x1C
1488#define IOPDW_SDMA_ADDR0 0x20
1489#define IOPDW_SDMA_ADDR1 0x24
1490#define IOPDW_SDMA_COUNT 0x28
1491#define IOPDW_SDMA_ERROR 0x2C
1492#define IOPDW_RDMA_ADDR0 0x30
1493#define IOPDW_RDMA_ADDR1 0x34
1494#define IOPDW_RDMA_COUNT 0x38
1495#define IOPDW_RDMA_ERROR 0x3C
1496
1497#define ADV_CHIP_ID_BYTE 0x25
1498#define ADV_CHIP_ID_WORD 0x04C1
1499
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500#define ADV_INTR_ENABLE_HOST_INTR 0x01
1501#define ADV_INTR_ENABLE_SEL_INTR 0x02
1502#define ADV_INTR_ENABLE_DPR_INTR 0x04
1503#define ADV_INTR_ENABLE_RTA_INTR 0x08
1504#define ADV_INTR_ENABLE_RMA_INTR 0x10
1505#define ADV_INTR_ENABLE_RST_INTR 0x20
1506#define ADV_INTR_ENABLE_DPE_INTR 0x40
1507#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1508
1509#define ADV_INTR_STATUS_INTRA 0x01
1510#define ADV_INTR_STATUS_INTRB 0x02
1511#define ADV_INTR_STATUS_INTRC 0x04
1512
1513#define ADV_RISC_CSR_STOP (0x0000)
1514#define ADV_RISC_TEST_COND (0x2000)
1515#define ADV_RISC_CSR_RUN (0x4000)
1516#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1517
1518#define ADV_CTRL_REG_HOST_INTR 0x0100
1519#define ADV_CTRL_REG_SEL_INTR 0x0200
1520#define ADV_CTRL_REG_DPR_INTR 0x0400
1521#define ADV_CTRL_REG_RTA_INTR 0x0800
1522#define ADV_CTRL_REG_RMA_INTR 0x1000
1523#define ADV_CTRL_REG_RES_BIT14 0x2000
1524#define ADV_CTRL_REG_DPE_INTR 0x4000
1525#define ADV_CTRL_REG_POWER_DONE 0x8000
1526#define ADV_CTRL_REG_ANY_INTR 0xFF00
1527
1528#define ADV_CTRL_REG_CMD_RESET 0x00C6
1529#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1530#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1531#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1532#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1533
1534#define ADV_TICKLE_NOP 0x00
1535#define ADV_TICKLE_A 0x01
1536#define ADV_TICKLE_B 0x02
1537#define ADV_TICKLE_C 0x03
1538
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539#define AdvIsIntPending(port) \
1540 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1541
1542/*
1543 * SCSI_CFG0 Register bit definitions
1544 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001545#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1546#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1547#define EVEN_PARITY 0x1000 /* Select Even Parity */
1548#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1549#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1550#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1551#define SCAM_EN 0x0080 /* Enable SCAM selection */
1552#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1553#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1554#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1555#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
1557/*
1558 * SCSI_CFG1 Register bit definitions
1559 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001560#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1561#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1562#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1563#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1564#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1565#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1566#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1567#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1568#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1569#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1570#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1571#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1572#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1573#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1574#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576/*
1577 * Addendum for ASC-38C0800 Chip
1578 *
1579 * The ASC-38C1600 Chip uses the same definitions except that the
1580 * bus mode override bits [12:10] have been moved to byte register
1581 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1582 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1583 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1584 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1585 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1586 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001587#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1588#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1589#define HVD 0x1000 /* HVD Device Detect */
1590#define LVD 0x0800 /* LVD Device Detect */
1591#define SE 0x0400 /* SE Device Detect */
1592#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1593#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1594#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1595#define TERM_SE 0x0030 /* SE Termination Bits */
1596#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1597#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1598#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1599#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1600#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1601#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1602#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1603#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
1605#define CABLE_ILLEGAL_A 0x7
1606 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1607
1608#define CABLE_ILLEGAL_B 0xB
1609 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1610
1611/*
1612 * MEM_CFG Register bit definitions
1613 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001614#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1615#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1616#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1617#define RAM_SZ_2KB 0x00 /* 2 KB */
1618#define RAM_SZ_4KB 0x04 /* 4 KB */
1619#define RAM_SZ_8KB 0x08 /* 8 KB */
1620#define RAM_SZ_16KB 0x0C /* 16 KB */
1621#define RAM_SZ_32KB 0x10 /* 32 KB */
1622#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
1624/*
1625 * DMA_CFG0 Register bit definitions
1626 *
1627 * This register is only accessible to the host.
1628 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001629#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1630#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1631#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1632#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1633#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1634#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1635#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1636#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1637#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1638#define START_CTL 0x0C /* DMA start conditions */
1639#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1640#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1641#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1642#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1643#define READ_CMD 0x03 /* Memory Read Method */
1644#define READ_CMD_MR 0x00 /* Memory Read */
1645#define READ_CMD_MRL 0x02 /* Memory Read Long */
1646#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
1648/*
1649 * ASC-38C0800 RAM BIST Register bit definitions
1650 */
1651#define RAM_TEST_MODE 0x80
1652#define PRE_TEST_MODE 0x40
1653#define NORMAL_MODE 0x00
1654#define RAM_TEST_DONE 0x10
1655#define RAM_TEST_STATUS 0x0F
1656#define RAM_TEST_HOST_ERROR 0x08
1657#define RAM_TEST_INTRAM_ERROR 0x04
1658#define RAM_TEST_RISC_ERROR 0x02
1659#define RAM_TEST_SCSI_ERROR 0x01
1660#define RAM_TEST_SUCCESS 0x00
1661#define PRE_TEST_VALUE 0x05
1662#define NORMAL_VALUE 0x00
1663
1664/*
1665 * ASC38C1600 Definitions
1666 *
1667 * IOPB_PCI_INT_CFG Bit Field Definitions
1668 */
1669
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001670#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
1672/*
1673 * Bit 1 can be set to change the interrupt for the Function to operate in
1674 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1675 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1676 * mode, otherwise the operating mode is undefined.
1677 */
1678#define TOTEMPOLE 0x02
1679
1680/*
1681 * Bit 0 can be used to change the Int Pin for the Function. The value is
1682 * 0 by default for both Functions with Function 0 using INT A and Function
1683 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1684 * INT A is used.
1685 *
1686 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1687 * value specified in the PCI Configuration Space.
1688 */
1689#define INTAB 0x01
1690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691/*
1692 * Adv Library Status Definitions
1693 */
1694#define ADV_TRUE 1
1695#define ADV_FALSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696#define ADV_SUCCESS 1
1697#define ADV_BUSY 0
1698#define ADV_ERROR (-1)
1699
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700/*
1701 * ADV_DVC_VAR 'warn_code' values
1702 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001703#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1704#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1705#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001706#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001708#define ADV_MAX_TID 15 /* max. target identifier */
1709#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710
1711/*
1712 * Error code values are set in ADV_DVC_VAR 'err_code'.
1713 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001714#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
1715#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
1716#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
1717#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
1718#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
1719#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
1720#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
1721#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
1722#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
1723#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
1724#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
1725#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
1726#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
1727#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
1729/*
1730 * Fixed locations of microcode operating variables.
1731 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001732#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1733#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1734#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1735#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1736#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1737#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1738#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1739#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1740#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1741#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1742#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1743#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1744#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745#define ASC_MC_CHIP_TYPE 0x009A
1746#define ASC_MC_INTRB_CODE 0x009B
1747#define ASC_MC_WDTR_ABLE 0x009C
1748#define ASC_MC_SDTR_ABLE 0x009E
1749#define ASC_MC_TAGQNG_ABLE 0x00A0
1750#define ASC_MC_DISC_ENABLE 0x00A2
1751#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1752#define ASC_MC_IDLE_CMD 0x00A6
1753#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1754#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1755#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1756#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1757#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1758#define ASC_MC_SDTR_DONE 0x00B6
1759#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1760#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1761#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001762#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001764#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765#define ASC_MC_ICQ 0x0160
1766#define ASC_MC_IRQ 0x0164
1767#define ASC_MC_PPR_ABLE 0x017A
1768
1769/*
1770 * BIOS LRAM variable absolute offsets.
1771 */
1772#define BIOS_CODESEG 0x54
1773#define BIOS_CODELEN 0x56
1774#define BIOS_SIGNATURE 0x58
1775#define BIOS_VERSION 0x5A
1776
1777/*
1778 * Microcode Control Flags
1779 *
1780 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1781 * and handled by the microcode.
1782 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001783#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1784#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
1786/*
1787 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1788 */
1789#define HSHK_CFG_WIDE_XFR 0x8000
1790#define HSHK_CFG_RATE 0x0F00
1791#define HSHK_CFG_OFFSET 0x001F
1792
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001793#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1794#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1795#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1796#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001798#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
1799#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
1800#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
1801#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
1802#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001804#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
1805#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
1806#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
1807#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
1808#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809/*
1810 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
1811 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
1812 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001813#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
1814#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816/*
1817 * All fields here are accessed by the board microcode and need to be
1818 * little-endian.
1819 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001820typedef struct adv_carr_t {
1821 ADV_VADDR carr_va; /* Carrier Virtual Address */
1822 ADV_PADDR carr_pa; /* Carrier Physical Address */
1823 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
1824 /*
1825 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
1826 *
1827 * next_vpa [3:1] Reserved Bits
1828 * next_vpa [0] Done Flag set in Response Queue.
1829 */
1830 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831} ADV_CARR_T;
1832
1833/*
1834 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
1835 */
1836#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
1837
1838#define ASC_RQ_DONE 0x00000001
1839#define ASC_RQ_GOOD 0x00000002
1840#define ASC_CQ_STOPPER 0x00000000
1841
1842#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
1843
1844#define ADV_CARRIER_NUM_PAGE_CROSSING \
1845 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
1846 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1847
1848#define ADV_CARRIER_BUFSIZE \
1849 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
1850
1851/*
1852 * ASC_SCSI_REQ_Q 'a_flag' definitions
1853 *
1854 * The Adv Library should limit use to the lower nibble (4 bits) of
1855 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
1856 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001857#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
1858#define ADV_SCSIQ_DONE 0x02 /* request done */
1859#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001861#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
1862#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
1863#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
1865/*
1866 * Adapter temporary configuration structure
1867 *
1868 * This structure can be discarded after initialization. Don't add
1869 * fields here needed after initialization.
1870 *
1871 * Field naming convention:
1872 *
1873 * *_enable indicates the field enables or disables a feature. The
1874 * value of the field is never reset.
1875 */
1876typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001877 ushort disc_enable; /* enable disconnection */
1878 uchar chip_version; /* chip version */
1879 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
1880 ushort lib_version; /* Adv Library version number */
1881 ushort control_flag; /* Microcode Control Flag */
1882 ushort mcode_date; /* Microcode date */
1883 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001884 ushort serial1; /* EEPROM serial number word 1 */
1885 ushort serial2; /* EEPROM serial number word 2 */
1886 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887} ADV_DVC_CFG;
1888
1889struct adv_dvc_var;
1890struct adv_scsi_req_q;
1891
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892/*
1893 * Adapter operation variable structure.
1894 *
1895 * One structure is required per host adapter.
1896 *
1897 * Field naming convention:
1898 *
1899 * *_able indicates both whether a feature should be enabled or disabled
1900 * and whether a device isi capable of the feature. At initialization
1901 * this field may be set, but later if a device is found to be incapable
1902 * of the feature, the field is cleared.
1903 */
1904typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001905 AdvPortAddr iop_base; /* I/O port address */
1906 ushort err_code; /* fatal error code */
1907 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001908 ushort wdtr_able; /* try WDTR for a device */
1909 ushort sdtr_able; /* try SDTR for a device */
1910 ushort ultra_able; /* try SDTR Ultra speed for a device */
1911 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
1912 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
1913 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
1914 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
1915 ushort tagqng_able; /* try tagged queuing with a device */
1916 ushort ppr_able; /* PPR message capable per TID bitmask. */
1917 uchar max_dvc_qng; /* maximum number of tagged commands per device */
1918 ushort start_motor; /* start motor command allowed */
1919 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
1920 uchar chip_no; /* should be assigned by caller */
1921 uchar max_host_qng; /* maximum number of Q'ed command allowed */
1922 uchar irq_no; /* IRQ number */
1923 ushort no_scam; /* scam_tolerant of EEPROM */
1924 struct asc_board *drv_ptr; /* driver pointer to private structure */
1925 uchar chip_scsi_id; /* chip SCSI target ID */
1926 uchar chip_type;
1927 uchar bist_err_code;
1928 ADV_CARR_T *carrier_buf;
1929 ADV_CARR_T *carr_freelist; /* Carrier free list. */
1930 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
1931 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
1932 ushort carr_pending_cnt; /* Count of pending carriers. */
1933 /*
1934 * Note: The following fields will not be used after initialization. The
1935 * driver may discard the buffer after initialization is done.
1936 */
1937 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938} ADV_DVC_VAR;
1939
1940#define NO_OF_SG_PER_BLOCK 15
1941
1942typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001943 uchar reserved1;
1944 uchar reserved2;
1945 uchar reserved3;
1946 uchar sg_cnt; /* Valid entries in block. */
1947 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
1948 struct {
1949 ADV_PADDR sg_addr; /* SG element address. */
1950 ADV_DCNT sg_count; /* SG element count. */
1951 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952} ADV_SG_BLOCK;
1953
1954/*
1955 * ADV_SCSI_REQ_Q - microcode request structure
1956 *
1957 * All fields in this structure up to byte 60 are used by the microcode.
1958 * The microcode makes assumptions about the size and ordering of fields
1959 * in this structure. Do not change the structure definition here without
1960 * coordinating the change with the microcode.
1961 *
1962 * All fields accessed by microcode must be maintained in little_endian
1963 * order.
1964 */
1965typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001966 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
1967 uchar target_cmd;
1968 uchar target_id; /* Device target identifier. */
1969 uchar target_lun; /* Device target logical unit number. */
1970 ADV_PADDR data_addr; /* Data buffer physical address. */
1971 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
1972 ADV_PADDR sense_addr;
1973 ADV_PADDR carr_pa;
1974 uchar mflag;
1975 uchar sense_len;
1976 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
1977 uchar scsi_cntl;
1978 uchar done_status; /* Completion status. */
1979 uchar scsi_status; /* SCSI status byte. */
1980 uchar host_status; /* Ucode host status. */
1981 uchar sg_working_ix;
1982 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
1983 ADV_PADDR sg_real_addr; /* SG list physical address. */
1984 ADV_PADDR scsiq_rptr;
1985 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
1986 ADV_VADDR scsiq_ptr;
1987 ADV_VADDR carr_va;
1988 /*
1989 * End of microcode structure - 60 bytes. The rest of the structure
1990 * is used by the Adv Library and ignored by the microcode.
1991 */
1992 ADV_VADDR srb_ptr;
1993 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
1994 char *vdata_addr; /* Data buffer virtual address. */
1995 uchar a_flag;
1996 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997} ADV_SCSI_REQ_Q;
1998
1999/*
2000 * Microcode idle loop commands
2001 */
2002#define IDLE_CMD_COMPLETED 0
2003#define IDLE_CMD_STOP_CHIP 0x0001
2004#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2005#define IDLE_CMD_SEND_INT 0x0004
2006#define IDLE_CMD_ABORT 0x0008
2007#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002008#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
2009#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010#define IDLE_CMD_SCSIREQ 0x0080
2011
2012#define IDLE_CMD_STATUS_SUCCESS 0x0001
2013#define IDLE_CMD_STATUS_FAILURE 0x0002
2014
2015/*
2016 * AdvSendIdleCmd() flag definitions.
2017 */
2018#define ADV_NOWAIT 0x01
2019
2020/*
2021 * Wait loop time out values.
2022 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002023#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2024#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002025#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002027#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2028#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2029#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2030#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002032#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034/* Read byte from a register. */
2035#define AdvReadByteRegister(iop_base, reg_off) \
2036 (ADV_MEM_READB((iop_base) + (reg_off)))
2037
2038/* Write byte to a register. */
2039#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2040 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2041
2042/* Read word (2 bytes) from a register. */
2043#define AdvReadWordRegister(iop_base, reg_off) \
2044 (ADV_MEM_READW((iop_base) + (reg_off)))
2045
2046/* Write word (2 bytes) to a register. */
2047#define AdvWriteWordRegister(iop_base, reg_off, word) \
2048 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2049
2050/* Write dword (4 bytes) to a register. */
2051#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2052 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2053
2054/* Read byte from LRAM. */
2055#define AdvReadByteLram(iop_base, addr, byte) \
2056do { \
2057 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2058 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2059} while (0)
2060
2061/* Write byte to LRAM. */
2062#define AdvWriteByteLram(iop_base, addr, byte) \
2063 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2064 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2065
2066/* Read word (2 bytes) from LRAM. */
2067#define AdvReadWordLram(iop_base, addr, word) \
2068do { \
2069 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2070 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2071} while (0)
2072
2073/* Write word (2 bytes) to LRAM. */
2074#define AdvWriteWordLram(iop_base, addr, word) \
2075 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2076 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2077
2078/* Write little-endian double word (4 bytes) to LRAM */
2079/* Because of unspecified C language ordering don't use auto-increment. */
2080#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2081 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2082 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2083 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2084 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2085 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2086 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2087
2088/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2089#define AdvReadWordAutoIncLram(iop_base) \
2090 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2091
2092/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2093#define AdvWriteWordAutoIncLram(iop_base, word) \
2094 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2095
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096/*
2097 * Define macro to check for Condor signature.
2098 *
2099 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2100 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2101 */
2102#define AdvFindSignature(iop_base) \
2103 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2104 ADV_CHIP_ID_BYTE) && \
2105 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2106 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2107
2108/*
2109 * Define macro to Return the version number of the chip at 'iop_base'.
2110 *
2111 * The second parameter 'bus_type' is currently unused.
2112 */
2113#define AdvGetChipVersion(iop_base, bus_type) \
2114 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2115
2116/*
2117 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2118 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2119 *
2120 * If the request has not yet been sent to the device it will simply be
2121 * aborted from RISC memory. If the request is disconnected it will be
2122 * aborted on reselection by sending an Abort Message to the target ID.
2123 *
2124 * Return value:
2125 * ADV_TRUE(1) - Queue was successfully aborted.
2126 * ADV_FALSE(0) - Queue was not found on the active queue list.
2127 */
2128#define AdvAbortQueue(asc_dvc, scsiq) \
2129 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2130 (ADV_DCNT) (scsiq))
2131
2132/*
2133 * Send a Bus Device Reset Message to the specified target ID.
2134 *
2135 * All outstanding commands will be purged if sending the
2136 * Bus Device Reset Message is successful.
2137 *
2138 * Return Value:
2139 * ADV_TRUE(1) - All requests on the target are purged.
2140 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2141 * are not purged.
2142 */
2143#define AdvResetDevice(asc_dvc, target_id) \
2144 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2145 (ADV_DCNT) (target_id))
2146
2147/*
2148 * SCSI Wide Type definition.
2149 */
2150#define ADV_SCSI_BIT_ID_TYPE ushort
2151
2152/*
2153 * AdvInitScsiTarget() 'cntl_flag' options.
2154 */
2155#define ADV_SCAN_LUN 0x01
2156#define ADV_CAPINFO_NOLUN 0x02
2157
2158/*
2159 * Convert target id to target id bit mask.
2160 */
2161#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2162
2163/*
2164 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2165 */
2166
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002167#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168#define QD_NO_ERROR 0x01
2169#define QD_ABORTED_BY_HOST 0x02
2170#define QD_WITH_ERROR 0x04
2171
2172#define QHSTA_NO_ERROR 0x00
2173#define QHSTA_M_SEL_TIMEOUT 0x11
2174#define QHSTA_M_DATA_OVER_RUN 0x12
2175#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2176#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002177#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2178#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2179#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2180#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2181#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2182#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2183#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002185#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2186#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2187#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2188#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2189#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2190#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2191#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2192#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193#define QHSTA_M_WTM_TIMEOUT 0x41
2194#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2195#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2196#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002197#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2198#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2199#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
2201/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 * DvcGetPhyAddr() flag arguments
2203 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002204#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2205#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2206#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2207#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2208#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2209#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210
2211/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2212#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2213#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2214#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2215
2216/*
2217 * Total contiguous memory needed for driver SG blocks.
2218 *
2219 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2220 * number of scatter-gather elements the driver supports in a
2221 * single request.
2222 */
2223
2224#define ADV_SG_LIST_MAX_BYTE_SIZE \
2225 (sizeof(ADV_SG_BLOCK) * \
2226 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2227
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228/* Reference Scsi_Host hostdata */
2229#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
2230
2231/* asc_board_t flags */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002232#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233
2234#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002236#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002238#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
2240#ifdef CONFIG_PROC_FS
2241/* /proc/scsi/advansys/[0...] related definitions */
2242#define ASC_PRTBUF_SIZE 2048
2243#define ASC_PRTLINE_SIZE 160
2244
2245#define ASC_PRT_NEXT() \
2246 if (cp) { \
2247 totlen += len; \
2248 leftlen -= len; \
2249 if (leftlen == 0) { \
2250 return totlen; \
2251 } \
2252 cp += len; \
2253 }
2254#endif /* CONFIG_PROC_FS */
2255
2256/* Asc Library return codes */
2257#define ASC_TRUE 1
2258#define ASC_FALSE 0
2259#define ASC_NOERROR 1
2260#define ASC_BUSY 0
2261#define ASC_ERROR (-1)
2262
2263/* struct scsi_cmnd function return codes */
2264#define STATUS_BYTE(byte) (byte)
2265#define MSG_BYTE(byte) ((byte) << 8)
2266#define HOST_BYTE(byte) ((byte) << 16)
2267#define DRIVER_BYTE(byte) ((byte) << 24)
2268
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002270#define ASC_STATS(shost, counter)
2271#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002273#define ASC_STATS(shost, counter) \
2274 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002276#define ASC_STATS_ADD(shost, counter, count) \
2277 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278#endif /* ADVANSYS_STATS */
2279
2280#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2281
2282/* If the result wraps when calculating tenths, return 0. */
2283#define ASC_TENTHS(num, den) \
2284 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2285 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2286
2287/*
2288 * Display a message to the console.
2289 */
2290#define ASC_PRINT(s) \
2291 { \
2292 printk("advansys: "); \
2293 printk(s); \
2294 }
2295
2296#define ASC_PRINT1(s, a1) \
2297 { \
2298 printk("advansys: "); \
2299 printk((s), (a1)); \
2300 }
2301
2302#define ASC_PRINT2(s, a1, a2) \
2303 { \
2304 printk("advansys: "); \
2305 printk((s), (a1), (a2)); \
2306 }
2307
2308#define ASC_PRINT3(s, a1, a2, a3) \
2309 { \
2310 printk("advansys: "); \
2311 printk((s), (a1), (a2), (a3)); \
2312 }
2313
2314#define ASC_PRINT4(s, a1, a2, a3, a4) \
2315 { \
2316 printk("advansys: "); \
2317 printk((s), (a1), (a2), (a3), (a4)); \
2318 }
2319
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320#ifndef ADVANSYS_DEBUG
2321
2322#define ASC_DBG(lvl, s)
2323#define ASC_DBG1(lvl, s, a1)
2324#define ASC_DBG2(lvl, s, a1, a2)
2325#define ASC_DBG3(lvl, s, a1, a2, a3)
2326#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2327#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2328#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
2329#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2330#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2331#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2332#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2333#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2334#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2335#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2336#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2337
2338#else /* ADVANSYS_DEBUG */
2339
2340/*
2341 * Debugging Message Levels:
2342 * 0: Errors Only
2343 * 1: High-Level Tracing
2344 * 2-N: Verbose Tracing
2345 */
2346
2347#define ASC_DBG(lvl, s) \
2348 { \
2349 if (asc_dbglvl >= (lvl)) { \
2350 printk(s); \
2351 } \
2352 }
2353
2354#define ASC_DBG1(lvl, s, a1) \
2355 { \
2356 if (asc_dbglvl >= (lvl)) { \
2357 printk((s), (a1)); \
2358 } \
2359 }
2360
2361#define ASC_DBG2(lvl, s, a1, a2) \
2362 { \
2363 if (asc_dbglvl >= (lvl)) { \
2364 printk((s), (a1), (a2)); \
2365 } \
2366 }
2367
2368#define ASC_DBG3(lvl, s, a1, a2, a3) \
2369 { \
2370 if (asc_dbglvl >= (lvl)) { \
2371 printk((s), (a1), (a2), (a3)); \
2372 } \
2373 }
2374
2375#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2376 { \
2377 if (asc_dbglvl >= (lvl)) { \
2378 printk((s), (a1), (a2), (a3), (a4)); \
2379 } \
2380 }
2381
2382#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2383 { \
2384 if (asc_dbglvl >= (lvl)) { \
2385 asc_prt_scsi_host(s); \
2386 } \
2387 }
2388
2389#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
2390 { \
2391 if (asc_dbglvl >= (lvl)) { \
2392 asc_prt_scsi_cmnd(s); \
2393 } \
2394 }
2395
2396#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2397 { \
2398 if (asc_dbglvl >= (lvl)) { \
2399 asc_prt_asc_scsi_q(scsiqp); \
2400 } \
2401 }
2402
2403#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2404 { \
2405 if (asc_dbglvl >= (lvl)) { \
2406 asc_prt_asc_qdone_info(qdone); \
2407 } \
2408 }
2409
2410#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2411 { \
2412 if (asc_dbglvl >= (lvl)) { \
2413 asc_prt_adv_scsi_req_q(scsiqp); \
2414 } \
2415 }
2416
2417#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2418 { \
2419 if (asc_dbglvl >= (lvl)) { \
2420 asc_prt_hex((name), (start), (length)); \
2421 } \
2422 }
2423
2424#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2425 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2426
2427#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2428 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2429
2430#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2431 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2432#endif /* ADVANSYS_DEBUG */
2433
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434#ifdef ADVANSYS_STATS
2435
2436/* Per board statistics structure */
2437struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002438 /* Driver Entrypoint Statistics */
2439 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2440 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2441 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2442 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2443 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2444 ADV_DCNT done; /* # calls to request's scsi_done function */
2445 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2446 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2447 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2448 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2449 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2450 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2451 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2452 ADV_DCNT exe_unknown; /* # unknown returns. */
2453 /* Data Transfer Statistics */
2454 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2455 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2456 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2457 ADV_DCNT sg_elem; /* # scatter-gather elements */
2458 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459};
2460#endif /* ADVANSYS_STATS */
2461
2462/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 * Adv Library Request Structures
2464 *
2465 * The following two structures are used to process Wide Board requests.
2466 *
2467 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2468 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2469 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2470 * Mid-Level SCSI request structure.
2471 *
2472 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2473 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2474 * up to 255 scatter-gather elements may be used per request or
2475 * ADV_SCSI_REQ_Q.
2476 *
2477 * Both structures must be 32 byte aligned.
2478 */
2479typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002480 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2481 uchar align[32]; /* Sgblock structure padding. */
2482 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483} adv_sgblk_t;
2484
2485typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002486 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2487 uchar align[32]; /* Request structure padding. */
2488 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2489 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2490 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491} adv_req_t;
2492
2493/*
2494 * Structure allocated for each board.
2495 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002496 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 * of the 'Scsi_Host' structure starting at the 'hostdata'
2498 * field. It is guaranteed to be allocated from DMA-able memory.
2499 */
2500typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002501 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002502 int id; /* Board Id */
2503 uint flags; /* Board flags */
2504 union {
2505 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2506 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2507 } dvc_var;
2508 union {
2509 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2510 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2511 } dvc_cfg;
2512 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002513 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002514 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2515 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2516 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2517 union {
2518 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2519 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2520 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2521 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2522 } eep_config;
2523 ulong last_reset; /* Saved last reset time */
2524 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002525 /* /proc/scsi/advansys/[0...] */
2526 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002528 struct asc_stats asc_stats; /* Board statistics */
2529#endif /* ADVANSYS_STATS */
2530 /*
2531 * The following fields are used only for Narrow Boards.
2532 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002533 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2534 /*
2535 * The following fields are used only for Wide Boards.
2536 */
2537 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2538 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002539 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002540 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2541 adv_req_t *adv_reqp; /* Request structures. */
2542 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2543 ushort bios_signature; /* BIOS Signature. */
2544 ushort bios_version; /* BIOS Version. */
2545 ushort bios_codeseg; /* BIOS Code Segment. */
2546 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547} asc_board_t;
2548
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002549#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2550 dvc_var.adv_dvc_var)
2551#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2552
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002554static int asc_board_count;
2555
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002557static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002560static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002563 * asc_prt_scsi_host()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 */
Matthew Wilcox51219352007-10-02 21:55:22 -04002565static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002567 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Matthew Wilcox51219352007-10-02 21:55:22 -04002569 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
Matthew Wilcox51219352007-10-02 21:55:22 -04002571 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
2572 printk(" host_busy %u, host_no %d, last_reset %d,\n",
2573 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Matthew Wilcox51219352007-10-02 21:55:22 -04002575 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
2576 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577
Matthew Wilcox51219352007-10-02 21:55:22 -04002578 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
2579 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
Matthew Wilcox51219352007-10-02 21:55:22 -04002581 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
2582 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002584 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04002585 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
2586 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002587 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04002588 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
2589 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002590 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591}
Matthew Wilcox51219352007-10-02 21:55:22 -04002592
2593/*
2594 * asc_prt_scsi_cmnd()
2595 */
2596static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
2597{
2598 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
2599
2600 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
2601 (ulong)s->device->host, (ulong)s->device, s->device->id,
2602 s->device->lun, s->device->channel);
2603
2604 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
2605
2606 printk("sc_data_direction %u, resid %d\n",
2607 s->sc_data_direction, s->resid);
2608
2609 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
2610
2611 printk(" serial_number 0x%x, retries %d, allowed %d\n",
2612 (unsigned)s->serial_number, s->retries, s->allowed);
2613
2614 printk(" timeout_per_command %d\n", s->timeout_per_command);
2615
2616 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
2617 s->scsi_done, s->done, s->host_scribble, s->result);
2618
2619 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
2620}
2621
2622/*
2623 * asc_prt_asc_dvc_var()
2624 */
2625static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
2626{
2627 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
2628
2629 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
2630 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
2631
2632 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
2633 (unsigned)h->init_sdtr);
2634
2635 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
2636 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
2637 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
2638 (unsigned)h->chip_no);
2639
2640 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
2641 "%u,\n", (unsigned)h->queue_full_or_busy,
2642 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
2643
2644 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
2645 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
2646 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
2647 (unsigned)h->in_critical_cnt);
2648
2649 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
2650 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
2651 (unsigned)h->init_state, (unsigned)h->no_scam,
2652 (unsigned)h->pci_fix_asyn_xfer);
2653
2654 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
2655}
2656
2657/*
2658 * asc_prt_asc_dvc_cfg()
2659 */
2660static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
2661{
2662 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
2663
2664 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
2665 h->can_tagged_qng, h->cmd_qng_enabled);
2666 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
2667 h->disc_enable, h->sdtr_enable);
2668
2669 printk
2670 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
2671 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
2672 h->chip_version);
2673
2674 printk
2675 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
2676 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
2677 h->mcode_date);
2678
2679 printk(" mcode_version %d, overrun_buf 0x%lx\n",
2680 h->mcode_version, (ulong)h->overrun_buf);
2681}
2682
2683/*
2684 * asc_prt_asc_scsi_q()
2685 */
2686static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
2687{
2688 ASC_SG_HEAD *sgp;
2689 int i;
2690
2691 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
2692
2693 printk
2694 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
2695 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
2696 q->q2.tag_code);
2697
2698 printk
2699 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2700 (ulong)le32_to_cpu(q->q1.data_addr),
2701 (ulong)le32_to_cpu(q->q1.data_cnt),
2702 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
2703
2704 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
2705 (ulong)q->cdbptr, q->q2.cdb_len,
2706 (ulong)q->sg_head, q->q1.sg_queue_cnt);
2707
2708 if (q->sg_head) {
2709 sgp = q->sg_head;
2710 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
2711 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
2712 sgp->queue_cnt);
2713 for (i = 0; i < sgp->entry_cnt; i++) {
2714 printk(" [%u]: addr 0x%lx, bytes %lu\n",
2715 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
2716 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
2717 }
2718
2719 }
2720}
2721
2722/*
2723 * asc_prt_asc_qdone_info()
2724 */
2725static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
2726{
2727 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
2728 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
2729 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
2730 q->d2.tag_code);
2731 printk
2732 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
2733 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
2734}
2735
2736/*
2737 * asc_prt_adv_dvc_var()
2738 *
2739 * Display an ADV_DVC_VAR structure.
2740 */
2741static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
2742{
2743 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
2744
2745 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
2746 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
2747
2748 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
2749 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
2750 (unsigned)h->wdtr_able);
2751
2752 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
2753 (unsigned)h->start_motor,
2754 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
2755
2756 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
2757 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
2758 (ulong)h->carr_freelist);
2759
2760 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
2761 (ulong)h->icq_sp, (ulong)h->irq_sp);
2762
2763 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
2764 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
2765
2766 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
2767 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
2768}
2769
2770/*
2771 * asc_prt_adv_dvc_cfg()
2772 *
2773 * Display an ADV_DVC_CFG structure.
2774 */
2775static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
2776{
2777 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
2778
2779 printk(" disc_enable 0x%x, termination 0x%x\n",
2780 h->disc_enable, h->termination);
2781
2782 printk(" chip_version 0x%x, mcode_date 0x%x\n",
2783 h->chip_version, h->mcode_date);
2784
2785 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
2786 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
2787
2788 printk(" control_flag 0x%x\n", h->control_flag);
2789}
2790
2791/*
2792 * asc_prt_adv_scsi_req_q()
2793 *
2794 * Display an ADV_SCSI_REQ_Q structure.
2795 */
2796static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
2797{
2798 int sg_blk_cnt;
2799 struct asc_sg_block *sg_ptr;
2800
2801 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
2802
2803 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
2804 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
2805
2806 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
2807 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
2808
2809 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2810 (ulong)le32_to_cpu(q->data_cnt),
2811 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
2812
2813 printk
2814 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
2815 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
2816
2817 printk(" sg_working_ix 0x%x, target_cmd %u\n",
2818 q->sg_working_ix, q->target_cmd);
2819
2820 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
2821 (ulong)le32_to_cpu(q->scsiq_rptr),
2822 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
2823
2824 /* Display the request's ADV_SG_BLOCK structures. */
2825 if (q->sg_list_ptr != NULL) {
2826 sg_blk_cnt = 0;
2827 while (1) {
2828 /*
2829 * 'sg_ptr' is a physical address. Convert it to a virtual
2830 * address by indexing 'sg_blk_cnt' into the virtual address
2831 * array 'sg_list_ptr'.
2832 *
2833 * XXX - Assumes all SG physical blocks are virtually contiguous.
2834 */
2835 sg_ptr =
2836 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
2837 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
2838 if (sg_ptr->sg_ptr == 0) {
2839 break;
2840 }
2841 sg_blk_cnt++;
2842 }
2843 }
2844}
2845
2846/*
2847 * asc_prt_adv_sgblock()
2848 *
2849 * Display an ADV_SG_BLOCK structure.
2850 */
2851static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
2852{
2853 int i;
2854
2855 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
2856 (ulong)b, sgblockno);
2857 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
2858 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
2859 BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
2860 if (b->sg_ptr != 0)
2861 BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
2862 for (i = 0; i < b->sg_cnt; i++) {
2863 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
2864 i, (ulong)b->sg_list[i].sg_addr,
2865 (ulong)b->sg_list[i].sg_count);
2866 }
2867}
2868
2869/*
2870 * asc_prt_hex()
2871 *
2872 * Print hexadecimal output in 4 byte groupings 32 bytes
2873 * or 8 double-words per line.
2874 */
2875static void asc_prt_hex(char *f, uchar *s, int l)
2876{
2877 int i;
2878 int j;
2879 int k;
2880 int m;
2881
2882 printk("%s: (%d bytes)\n", f, l);
2883
2884 for (i = 0; i < l; i += 32) {
2885
2886 /* Display a maximum of 8 double-words per line. */
2887 if ((k = (l - i) / 4) >= 8) {
2888 k = 8;
2889 m = 0;
2890 } else {
2891 m = (l - i) % 4;
2892 }
2893
2894 for (j = 0; j < k; j++) {
2895 printk(" %2.2X%2.2X%2.2X%2.2X",
2896 (unsigned)s[i + (j * 4)],
2897 (unsigned)s[i + (j * 4) + 1],
2898 (unsigned)s[i + (j * 4) + 2],
2899 (unsigned)s[i + (j * 4) + 3]);
2900 }
2901
2902 switch (m) {
2903 case 0:
2904 default:
2905 break;
2906 case 1:
2907 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
2908 break;
2909 case 2:
2910 printk(" %2.2X%2.2X",
2911 (unsigned)s[i + (j * 4)],
2912 (unsigned)s[i + (j * 4) + 1]);
2913 break;
2914 case 3:
2915 printk(" %2.2X%2.2X%2.2X",
2916 (unsigned)s[i + (j * 4) + 1],
2917 (unsigned)s[i + (j * 4) + 2],
2918 (unsigned)s[i + (j * 4) + 3]);
2919 break;
2920 }
2921
2922 printk("\n");
2923 }
2924}
2925#endif /* ADVANSYS_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
2927/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 * advansys_info()
2929 *
2930 * Return suitable for printing on the console with the argument
2931 * adapter's configuration information.
2932 *
2933 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
2934 * otherwise the static 'info' array will be overrun.
2935 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002936static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002938 static char info[ASC_INFO_SIZE];
2939 asc_board_t *boardp;
2940 ASC_DVC_VAR *asc_dvc_varp;
2941 ADV_DVC_VAR *adv_dvc_varp;
2942 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002943 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002945 boardp = ASC_BOARDP(shost);
2946 if (ASC_NARROW_BOARD(boardp)) {
2947 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
2948 ASC_DBG(1, "advansys_info: begin\n");
2949 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
2950 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
2951 ASC_IS_ISAPNP) {
2952 busname = "ISA PnP";
2953 } else {
2954 busname = "ISA";
2955 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002956 sprintf(info,
2957 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
2958 ASC_VERSION, busname,
2959 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002960 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
2961 shost->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002962 } else {
2963 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
2964 busname = "VL";
2965 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
2966 busname = "EISA";
2967 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
2968 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
2969 == ASC_IS_PCI_ULTRA) {
2970 busname = "PCI Ultra";
2971 } else {
2972 busname = "PCI";
2973 }
2974 } else {
2975 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002976 ASC_PRINT2("advansys_info: board %d: unknown "
2977 "bus type %d\n", boardp->id,
2978 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002979 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002980 sprintf(info,
2981 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002982 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002983 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
2984 shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002985 }
2986 } else {
2987 /*
2988 * Wide Adapter Information
2989 *
2990 * Memory-mapped I/O is used instead of I/O space to access
2991 * the adapter, but display the I/O Port range. The Memory
2992 * I/O address is displayed through the driver /proc file.
2993 */
2994 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
2995 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002996 widename = "Ultra-Wide";
2997 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002998 widename = "Ultra2-Wide";
2999 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003000 widename = "Ultra3-Wide";
3001 }
3002 sprintf(info,
3003 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
3004 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003005 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003006 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06003007 BUG_ON(strlen(info) >= ASC_INFO_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003008 ASC_DBG(1, "advansys_info: end\n");
3009 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010}
3011
Matthew Wilcox51219352007-10-02 21:55:22 -04003012#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013/*
Matthew Wilcox51219352007-10-02 21:55:22 -04003014 * asc_prt_line()
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 *
Matthew Wilcox51219352007-10-02 21:55:22 -04003016 * If 'cp' is NULL print to the console, otherwise print to a buffer.
3017 *
3018 * Return 0 if printing to the console, otherwise return the number of
3019 * bytes written to the buffer.
3020 *
3021 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
3022 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 */
Matthew Wilcox51219352007-10-02 21:55:22 -04003024static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025{
Matthew Wilcox51219352007-10-02 21:55:22 -04003026 va_list args;
3027 int ret;
3028 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
Matthew Wilcox51219352007-10-02 21:55:22 -04003030 va_start(args, fmt);
3031 ret = vsprintf(s, fmt, args);
3032 BUG_ON(ret >= ASC_PRTLINE_SIZE);
3033 if (buf == NULL) {
3034 (void)printk(s);
3035 ret = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003036 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04003037 ret = min(buflen, ret);
3038 memcpy(buf, s, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003039 }
Matthew Wilcox51219352007-10-02 21:55:22 -04003040 va_end(args);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003041 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042}
3043
3044/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 * asc_prt_board_devices()
3046 *
3047 * Print driver information for devices attached to the board.
3048 *
3049 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3050 * cf. asc_prt_line().
3051 *
3052 * Return the number of characters copied into 'cp'. No more than
3053 * 'cplen' characters will be copied to 'cp'.
3054 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003055static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003057 asc_board_t *boardp;
3058 int leftlen;
3059 int totlen;
3060 int len;
3061 int chip_scsi_id;
3062 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003064 boardp = ASC_BOARDP(shost);
3065 leftlen = cplen;
3066 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003068 len = asc_prt_line(cp, leftlen,
3069 "\nDevice Information for AdvanSys SCSI Host %d:\n",
3070 shost->host_no);
3071 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003073 if (ASC_NARROW_BOARD(boardp)) {
3074 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3075 } else {
3076 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003079 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
3080 ASC_PRT_NEXT();
3081 for (i = 0; i <= ADV_MAX_TID; i++) {
3082 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
3083 len = asc_prt_line(cp, leftlen, " %X,", i);
3084 ASC_PRT_NEXT();
3085 }
3086 }
3087 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
3088 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003090 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091}
3092
3093/*
3094 * Display Wide Board BIOS Information.
3095 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003096static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003098 asc_board_t *boardp;
3099 int leftlen;
3100 int totlen;
3101 int len;
3102 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003104 boardp = ASC_BOARDP(shost);
3105 leftlen = cplen;
3106 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003108 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
3109 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003111 /*
3112 * If the BIOS saved a valid signature, then fill in
3113 * the BIOS code segment base address.
3114 */
3115 if (boardp->bios_signature != 0x55AA) {
3116 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
3117 ASC_PRT_NEXT();
3118 len = asc_prt_line(cp, leftlen,
3119 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
3120 ASC_PRT_NEXT();
3121 len = asc_prt_line(cp, leftlen,
3122 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
3123 ASC_PRT_NEXT();
3124 } else {
3125 major = (boardp->bios_version >> 12) & 0xF;
3126 minor = (boardp->bios_version >> 8) & 0xF;
3127 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003129 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
3130 major, minor,
3131 letter >= 26 ? '?' : letter + 'A');
3132 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003134 /*
3135 * Current available ROM BIOS release is 3.1I for UW
3136 * and 3.2I for U2W. This code doesn't differentiate
3137 * UW and U2W boards.
3138 */
3139 if (major < 3 || (major <= 3 && minor < 1) ||
3140 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
3141 len = asc_prt_line(cp, leftlen,
3142 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
3143 ASC_PRT_NEXT();
3144 len = asc_prt_line(cp, leftlen,
3145 "ftp://ftp.connectcom.net/pub\n");
3146 ASC_PRT_NEXT();
3147 }
3148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003150 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151}
3152
3153/*
3154 * Add serial number to information bar if signature AAh
3155 * is found in at bit 15-9 (7 bits) of word 1.
3156 *
3157 * Serial Number consists fo 12 alpha-numeric digits.
3158 *
3159 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
3160 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
3161 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
3162 * 5 - Product revision (A-J) Word0: " "
3163 *
3164 * Signature Word1: 15-9 (7 bits)
3165 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
3166 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
3167 *
3168 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
3169 *
3170 * Note 1: Only production cards will have a serial number.
3171 *
3172 * Note 2: Signature is most significant 7 bits (0xFE).
3173 *
3174 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
3175 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003176static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003178 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003180 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
3181 return ASC_FALSE;
3182 } else {
3183 /*
3184 * First word - 6 digits.
3185 */
3186 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003188 /* Product type - 1st digit. */
3189 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
3190 /* Product type is P=Prototype */
3191 *cp += 0x8;
3192 }
3193 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003195 /* Manufacturing location - 2nd digit. */
3196 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003198 /* Product ID - 3rd, 4th digits. */
3199 num = w & 0x3FF;
3200 *cp++ = '0' + (num / 100);
3201 num %= 100;
3202 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003204 /* Product revision - 5th digit. */
3205 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003207 /*
3208 * Second word
3209 */
3210 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003212 /*
3213 * Year - 6th digit.
3214 *
3215 * If bit 15 of third word is set, then the
3216 * last digit of the year is greater than 7.
3217 */
3218 if (serialnum[2] & 0x8000) {
3219 *cp++ = '8' + ((w & 0x1C0) >> 6);
3220 } else {
3221 *cp++ = '0' + ((w & 0x1C0) >> 6);
3222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003224 /* Week of year - 7th, 8th digits. */
3225 num = w & 0x003F;
3226 *cp++ = '0' + num / 10;
3227 num %= 10;
3228 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003230 /*
3231 * Third word
3232 */
3233 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003235 /* Serial number - 9th digit. */
3236 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003238 /* 10th, 11th, 12th digits. */
3239 num = w % 1000;
3240 *cp++ = '0' + num / 100;
3241 num %= 100;
3242 *cp++ = '0' + num / 10;
3243 num %= 10;
3244 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003246 *cp = '\0'; /* Null Terminate the string. */
3247 return ASC_TRUE;
3248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249}
3250
3251/*
3252 * asc_prt_asc_board_eeprom()
3253 *
3254 * Print board EEPROM configuration.
3255 *
3256 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3257 * cf. asc_prt_line().
3258 *
3259 * Return the number of characters copied into 'cp'. No more than
3260 * 'cplen' characters will be copied to 'cp'.
3261 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003262static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003264 asc_board_t *boardp;
3265 ASC_DVC_VAR *asc_dvc_varp;
3266 int leftlen;
3267 int totlen;
3268 int len;
3269 ASCEEP_CONFIG *ep;
3270 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003272 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003274 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003276 boardp = ASC_BOARDP(shost);
3277 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3278 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003280 leftlen = cplen;
3281 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003283 len = asc_prt_line(cp, leftlen,
3284 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3285 shost->host_no);
3286 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003288 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
3289 == ASC_TRUE) {
3290 len =
3291 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3292 serialstr);
3293 ASC_PRT_NEXT();
3294 } else {
3295 if (ep->adapter_info[5] == 0xBB) {
3296 len = asc_prt_line(cp, leftlen,
3297 " Default Settings Used for EEPROM-less Adapter.\n");
3298 ASC_PRT_NEXT();
3299 } else {
3300 len = asc_prt_line(cp, leftlen,
3301 " Serial Number Signature Not Present.\n");
3302 ASC_PRT_NEXT();
3303 }
3304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003306 len = asc_prt_line(cp, leftlen,
3307 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3308 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
3309 ep->max_tag_qng);
3310 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003312 len = asc_prt_line(cp, leftlen,
3313 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
3314 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003316 len = asc_prt_line(cp, leftlen, " Target ID: ");
3317 ASC_PRT_NEXT();
3318 for (i = 0; i <= ASC_MAX_TID; i++) {
3319 len = asc_prt_line(cp, leftlen, " %d", i);
3320 ASC_PRT_NEXT();
3321 }
3322 len = asc_prt_line(cp, leftlen, "\n");
3323 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003325 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3326 ASC_PRT_NEXT();
3327 for (i = 0; i <= ASC_MAX_TID; i++) {
3328 len = asc_prt_line(cp, leftlen, " %c",
3329 (ep->
3330 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3331 'N');
3332 ASC_PRT_NEXT();
3333 }
3334 len = asc_prt_line(cp, leftlen, "\n");
3335 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003337 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3338 ASC_PRT_NEXT();
3339 for (i = 0; i <= ASC_MAX_TID; i++) {
3340 len = asc_prt_line(cp, leftlen, " %c",
3341 (ep->
3342 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3343 'N');
3344 ASC_PRT_NEXT();
3345 }
3346 len = asc_prt_line(cp, leftlen, "\n");
3347 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003349 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3350 ASC_PRT_NEXT();
3351 for (i = 0; i <= ASC_MAX_TID; i++) {
3352 len = asc_prt_line(cp, leftlen, " %c",
3353 (ep->
3354 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3355 'N');
3356 ASC_PRT_NEXT();
3357 }
3358 len = asc_prt_line(cp, leftlen, "\n");
3359 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003361 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3362 ASC_PRT_NEXT();
3363 for (i = 0; i <= ASC_MAX_TID; i++) {
3364 len = asc_prt_line(cp, leftlen, " %c",
3365 (ep->
3366 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3367 'N');
3368 ASC_PRT_NEXT();
3369 }
3370 len = asc_prt_line(cp, leftlen, "\n");
3371 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372
3373#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003374 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3375 len = asc_prt_line(cp, leftlen,
3376 " Host ISA DMA speed: %d MB/S\n",
3377 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
3378 ASC_PRT_NEXT();
3379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380#endif /* CONFIG_ISA */
3381
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003382 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383}
3384
3385/*
3386 * asc_prt_adv_board_eeprom()
3387 *
3388 * Print board EEPROM configuration.
3389 *
3390 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3391 * cf. asc_prt_line().
3392 *
3393 * Return the number of characters copied into 'cp'. No more than
3394 * 'cplen' characters will be copied to 'cp'.
3395 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003396static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003398 asc_board_t *boardp;
3399 ADV_DVC_VAR *adv_dvc_varp;
3400 int leftlen;
3401 int totlen;
3402 int len;
3403 int i;
3404 char *termstr;
3405 uchar serialstr[13];
3406 ADVEEP_3550_CONFIG *ep_3550 = NULL;
3407 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
3408 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
3409 ushort word;
3410 ushort *wordp;
3411 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003413 boardp = ASC_BOARDP(shost);
3414 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3415 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3416 ep_3550 = &boardp->eep_config.adv_3550_eep;
3417 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3418 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
3419 } else {
3420 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
3421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003423 leftlen = cplen;
3424 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003426 len = asc_prt_line(cp, leftlen,
3427 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3428 shost->host_no);
3429 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003431 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3432 wordp = &ep_3550->serial_number_word1;
3433 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3434 wordp = &ep_38C0800->serial_number_word1;
3435 } else {
3436 wordp = &ep_38C1600->serial_number_word1;
3437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003439 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
3440 len =
3441 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3442 serialstr);
3443 ASC_PRT_NEXT();
3444 } else {
3445 len = asc_prt_line(cp, leftlen,
3446 " Serial Number Signature Not Present.\n");
3447 ASC_PRT_NEXT();
3448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003450 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3451 len = asc_prt_line(cp, leftlen,
3452 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3453 ep_3550->adapter_scsi_id,
3454 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
3455 ASC_PRT_NEXT();
3456 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3457 len = asc_prt_line(cp, leftlen,
3458 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3459 ep_38C0800->adapter_scsi_id,
3460 ep_38C0800->max_host_qng,
3461 ep_38C0800->max_dvc_qng);
3462 ASC_PRT_NEXT();
3463 } else {
3464 len = asc_prt_line(cp, leftlen,
3465 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3466 ep_38C1600->adapter_scsi_id,
3467 ep_38C1600->max_host_qng,
3468 ep_38C1600->max_dvc_qng);
3469 ASC_PRT_NEXT();
3470 }
3471 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3472 word = ep_3550->termination;
3473 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3474 word = ep_38C0800->termination_lvd;
3475 } else {
3476 word = ep_38C1600->termination_lvd;
3477 }
3478 switch (word) {
3479 case 1:
3480 termstr = "Low Off/High Off";
3481 break;
3482 case 2:
3483 termstr = "Low Off/High On";
3484 break;
3485 case 3:
3486 termstr = "Low On/High On";
3487 break;
3488 default:
3489 case 0:
3490 termstr = "Automatic";
3491 break;
3492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003494 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3495 len = asc_prt_line(cp, leftlen,
3496 " termination: %u (%s), bios_ctrl: 0x%x\n",
3497 ep_3550->termination, termstr,
3498 ep_3550->bios_ctrl);
3499 ASC_PRT_NEXT();
3500 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3501 len = asc_prt_line(cp, leftlen,
3502 " termination: %u (%s), bios_ctrl: 0x%x\n",
3503 ep_38C0800->termination_lvd, termstr,
3504 ep_38C0800->bios_ctrl);
3505 ASC_PRT_NEXT();
3506 } else {
3507 len = asc_prt_line(cp, leftlen,
3508 " termination: %u (%s), bios_ctrl: 0x%x\n",
3509 ep_38C1600->termination_lvd, termstr,
3510 ep_38C1600->bios_ctrl);
3511 ASC_PRT_NEXT();
3512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003514 len = asc_prt_line(cp, leftlen, " Target ID: ");
3515 ASC_PRT_NEXT();
3516 for (i = 0; i <= ADV_MAX_TID; i++) {
3517 len = asc_prt_line(cp, leftlen, " %X", i);
3518 ASC_PRT_NEXT();
3519 }
3520 len = asc_prt_line(cp, leftlen, "\n");
3521 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003523 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3524 word = ep_3550->disc_enable;
3525 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3526 word = ep_38C0800->disc_enable;
3527 } else {
3528 word = ep_38C1600->disc_enable;
3529 }
3530 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3531 ASC_PRT_NEXT();
3532 for (i = 0; i <= ADV_MAX_TID; i++) {
3533 len = asc_prt_line(cp, leftlen, " %c",
3534 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3535 ASC_PRT_NEXT();
3536 }
3537 len = asc_prt_line(cp, leftlen, "\n");
3538 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003540 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3541 word = ep_3550->tagqng_able;
3542 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3543 word = ep_38C0800->tagqng_able;
3544 } else {
3545 word = ep_38C1600->tagqng_able;
3546 }
3547 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3548 ASC_PRT_NEXT();
3549 for (i = 0; i <= ADV_MAX_TID; i++) {
3550 len = asc_prt_line(cp, leftlen, " %c",
3551 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3552 ASC_PRT_NEXT();
3553 }
3554 len = asc_prt_line(cp, leftlen, "\n");
3555 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003557 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3558 word = ep_3550->start_motor;
3559 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3560 word = ep_38C0800->start_motor;
3561 } else {
3562 word = ep_38C1600->start_motor;
3563 }
3564 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3565 ASC_PRT_NEXT();
3566 for (i = 0; i <= ADV_MAX_TID; i++) {
3567 len = asc_prt_line(cp, leftlen, " %c",
3568 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3569 ASC_PRT_NEXT();
3570 }
3571 len = asc_prt_line(cp, leftlen, "\n");
3572 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003574 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3575 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3576 ASC_PRT_NEXT();
3577 for (i = 0; i <= ADV_MAX_TID; i++) {
3578 len = asc_prt_line(cp, leftlen, " %c",
3579 (ep_3550->
3580 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
3581 'Y' : 'N');
3582 ASC_PRT_NEXT();
3583 }
3584 len = asc_prt_line(cp, leftlen, "\n");
3585 ASC_PRT_NEXT();
3586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003588 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3589 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
3590 ASC_PRT_NEXT();
3591 for (i = 0; i <= ADV_MAX_TID; i++) {
3592 len = asc_prt_line(cp, leftlen, " %c",
3593 (ep_3550->
3594 ultra_able & ADV_TID_TO_TIDMASK(i))
3595 ? 'Y' : 'N');
3596 ASC_PRT_NEXT();
3597 }
3598 len = asc_prt_line(cp, leftlen, "\n");
3599 ASC_PRT_NEXT();
3600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003602 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3603 word = ep_3550->wdtr_able;
3604 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3605 word = ep_38C0800->wdtr_able;
3606 } else {
3607 word = ep_38C1600->wdtr_able;
3608 }
3609 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
3610 ASC_PRT_NEXT();
3611 for (i = 0; i <= ADV_MAX_TID; i++) {
3612 len = asc_prt_line(cp, leftlen, " %c",
3613 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3614 ASC_PRT_NEXT();
3615 }
3616 len = asc_prt_line(cp, leftlen, "\n");
3617 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003619 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
3620 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
3621 len = asc_prt_line(cp, leftlen,
3622 " Synchronous Transfer Speed (Mhz):\n ");
3623 ASC_PRT_NEXT();
3624 for (i = 0; i <= ADV_MAX_TID; i++) {
3625 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003627 if (i == 0) {
3628 sdtr_speed = adv_dvc_varp->sdtr_speed1;
3629 } else if (i == 4) {
3630 sdtr_speed = adv_dvc_varp->sdtr_speed2;
3631 } else if (i == 8) {
3632 sdtr_speed = adv_dvc_varp->sdtr_speed3;
3633 } else if (i == 12) {
3634 sdtr_speed = adv_dvc_varp->sdtr_speed4;
3635 }
3636 switch (sdtr_speed & ADV_MAX_TID) {
3637 case 0:
3638 speed_str = "Off";
3639 break;
3640 case 1:
3641 speed_str = " 5";
3642 break;
3643 case 2:
3644 speed_str = " 10";
3645 break;
3646 case 3:
3647 speed_str = " 20";
3648 break;
3649 case 4:
3650 speed_str = " 40";
3651 break;
3652 case 5:
3653 speed_str = " 80";
3654 break;
3655 default:
3656 speed_str = "Unk";
3657 break;
3658 }
3659 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
3660 ASC_PRT_NEXT();
3661 if (i == 7) {
3662 len = asc_prt_line(cp, leftlen, "\n ");
3663 ASC_PRT_NEXT();
3664 }
3665 sdtr_speed >>= 4;
3666 }
3667 len = asc_prt_line(cp, leftlen, "\n");
3668 ASC_PRT_NEXT();
3669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003671 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672}
3673
3674/*
3675 * asc_prt_driver_conf()
3676 *
3677 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3678 * cf. asc_prt_line().
3679 *
3680 * Return the number of characters copied into 'cp'. No more than
3681 * 'cplen' characters will be copied to 'cp'.
3682 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003683static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003685 asc_board_t *boardp;
3686 int leftlen;
3687 int totlen;
3688 int len;
3689 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003691 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003693 leftlen = cplen;
3694 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003696 len = asc_prt_line(cp, leftlen,
3697 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
3698 shost->host_no);
3699 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003701 len = asc_prt_line(cp, leftlen,
3702 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
3703 shost->host_busy, shost->last_reset, shost->max_id,
3704 shost->max_lun, shost->max_channel);
3705 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003707 len = asc_prt_line(cp, leftlen,
3708 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
3709 shost->unique_id, shost->can_queue, shost->this_id,
3710 shost->sg_tablesize, shost->cmd_per_lun);
3711 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003713 len = asc_prt_line(cp, leftlen,
3714 " unchecked_isa_dma %d, use_clustering %d\n",
3715 shost->unchecked_isa_dma, shost->use_clustering);
3716 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003718 len = asc_prt_line(cp, leftlen,
3719 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
3720 boardp->flags, boardp->last_reset, jiffies,
3721 boardp->asc_n_io_port);
3722 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003724 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003725 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003727 if (ASC_NARROW_BOARD(boardp)) {
3728 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3729 } else {
3730 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3731 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003733 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734}
3735
3736/*
3737 * asc_prt_asc_board_info()
3738 *
3739 * Print dynamic board configuration information.
3740 *
3741 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3742 * cf. asc_prt_line().
3743 *
3744 * Return the number of characters copied into 'cp'. No more than
3745 * 'cplen' characters will be copied to 'cp'.
3746 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003747static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003749 asc_board_t *boardp;
3750 int chip_scsi_id;
3751 int leftlen;
3752 int totlen;
3753 int len;
3754 ASC_DVC_VAR *v;
3755 ASC_DVC_CFG *c;
3756 int i;
3757 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003759 boardp = ASC_BOARDP(shost);
3760 v = &boardp->dvc_var.asc_dvc_var;
3761 c = &boardp->dvc_cfg.asc_dvc_cfg;
3762 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003764 leftlen = cplen;
3765 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003767 len = asc_prt_line(cp, leftlen,
3768 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3769 shost->host_no);
3770 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003772 len = asc_prt_line(cp, leftlen,
3773 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
3774 c->chip_version, c->lib_version, c->lib_serial_no,
3775 c->mcode_date);
3776 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003778 len = asc_prt_line(cp, leftlen,
3779 " mcode_version 0x%x, err_code %u\n",
3780 c->mcode_version, v->err_code);
3781 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003783 /* Current number of commands waiting for the host. */
3784 len = asc_prt_line(cp, leftlen,
3785 " Total Command Pending: %d\n", v->cur_total_qng);
3786 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003788 len = asc_prt_line(cp, leftlen, " Command Queuing:");
3789 ASC_PRT_NEXT();
3790 for (i = 0; i <= ASC_MAX_TID; i++) {
3791 if ((chip_scsi_id == i) ||
3792 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3793 continue;
3794 }
3795 len = asc_prt_line(cp, leftlen, " %X:%c",
3796 i,
3797 (v->
3798 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
3799 'Y' : 'N');
3800 ASC_PRT_NEXT();
3801 }
3802 len = asc_prt_line(cp, leftlen, "\n");
3803 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003805 /* Current number of commands waiting for a device. */
3806 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
3807 ASC_PRT_NEXT();
3808 for (i = 0; i <= ASC_MAX_TID; i++) {
3809 if ((chip_scsi_id == i) ||
3810 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3811 continue;
3812 }
3813 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
3814 ASC_PRT_NEXT();
3815 }
3816 len = asc_prt_line(cp, leftlen, "\n");
3817 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003819 /* Current limit on number of commands that can be sent to a device. */
3820 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
3821 ASC_PRT_NEXT();
3822 for (i = 0; i <= ASC_MAX_TID; i++) {
3823 if ((chip_scsi_id == i) ||
3824 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3825 continue;
3826 }
3827 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
3828 ASC_PRT_NEXT();
3829 }
3830 len = asc_prt_line(cp, leftlen, "\n");
3831 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003833 /* Indicate whether the device has returned queue full status. */
3834 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
3835 ASC_PRT_NEXT();
3836 for (i = 0; i <= ASC_MAX_TID; i++) {
3837 if ((chip_scsi_id == i) ||
3838 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3839 continue;
3840 }
3841 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
3842 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
3843 i, boardp->queue_full_cnt[i]);
3844 } else {
3845 len = asc_prt_line(cp, leftlen, " %X:N", i);
3846 }
3847 ASC_PRT_NEXT();
3848 }
3849 len = asc_prt_line(cp, leftlen, "\n");
3850 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003852 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3853 ASC_PRT_NEXT();
3854 for (i = 0; i <= ASC_MAX_TID; i++) {
3855 if ((chip_scsi_id == i) ||
3856 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3857 continue;
3858 }
3859 len = asc_prt_line(cp, leftlen, " %X:%c",
3860 i,
3861 (v->
3862 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3863 'N');
3864 ASC_PRT_NEXT();
3865 }
3866 len = asc_prt_line(cp, leftlen, "\n");
3867 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003869 for (i = 0; i <= ASC_MAX_TID; i++) {
3870 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003872 if ((chip_scsi_id == i) ||
3873 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3874 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
3875 continue;
3876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003878 len = asc_prt_line(cp, leftlen, " %X:", i);
3879 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003881 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
3882 len = asc_prt_line(cp, leftlen, " Asynchronous");
3883 ASC_PRT_NEXT();
3884 } else {
3885 syn_period_ix =
3886 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
3887 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003889 len = asc_prt_line(cp, leftlen,
3890 " Transfer Period Factor: %d (%d.%d Mhz),",
3891 v->sdtr_period_tbl[syn_period_ix],
3892 250 /
3893 v->sdtr_period_tbl[syn_period_ix],
3894 ASC_TENTHS(250,
3895 v->
3896 sdtr_period_tbl
3897 [syn_period_ix]));
3898 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003900 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
3901 boardp->
3902 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
3903 ASC_PRT_NEXT();
3904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003906 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3907 len = asc_prt_line(cp, leftlen, "*\n");
3908 renegotiate = 1;
3909 } else {
3910 len = asc_prt_line(cp, leftlen, "\n");
3911 }
3912 ASC_PRT_NEXT();
3913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003915 if (renegotiate) {
3916 len = asc_prt_line(cp, leftlen,
3917 " * = Re-negotiation pending before next command.\n");
3918 ASC_PRT_NEXT();
3919 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003921 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922}
3923
3924/*
3925 * asc_prt_adv_board_info()
3926 *
3927 * Print dynamic board configuration information.
3928 *
3929 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3930 * cf. asc_prt_line().
3931 *
3932 * Return the number of characters copied into 'cp'. No more than
3933 * 'cplen' characters will be copied to 'cp'.
3934 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003935static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003937 asc_board_t *boardp;
3938 int leftlen;
3939 int totlen;
3940 int len;
3941 int i;
3942 ADV_DVC_VAR *v;
3943 ADV_DVC_CFG *c;
3944 AdvPortAddr iop_base;
3945 ushort chip_scsi_id;
3946 ushort lramword;
3947 uchar lrambyte;
3948 ushort tagqng_able;
3949 ushort sdtr_able, wdtr_able;
3950 ushort wdtr_done, sdtr_done;
3951 ushort period = 0;
3952 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003954 boardp = ASC_BOARDP(shost);
3955 v = &boardp->dvc_var.adv_dvc_var;
3956 c = &boardp->dvc_cfg.adv_dvc_cfg;
3957 iop_base = v->iop_base;
3958 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003960 leftlen = cplen;
3961 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003963 len = asc_prt_line(cp, leftlen,
3964 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3965 shost->host_no);
3966 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003968 len = asc_prt_line(cp, leftlen,
3969 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
3970 v->iop_base,
3971 AdvReadWordRegister(iop_base,
3972 IOPW_SCSI_CFG1) & CABLE_DETECT,
3973 v->err_code);
3974 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003976 len = asc_prt_line(cp, leftlen,
3977 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
3978 c->chip_version, c->lib_version, c->mcode_date,
3979 c->mcode_version);
3980 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003982 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
3983 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
3984 ASC_PRT_NEXT();
3985 for (i = 0; i <= ADV_MAX_TID; i++) {
3986 if ((chip_scsi_id == i) ||
3987 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3988 continue;
3989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003991 len = asc_prt_line(cp, leftlen, " %X:%c",
3992 i,
3993 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3994 'N');
3995 ASC_PRT_NEXT();
3996 }
3997 len = asc_prt_line(cp, leftlen, "\n");
3998 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004000 len = asc_prt_line(cp, leftlen, " Queue Limit:");
4001 ASC_PRT_NEXT();
4002 for (i = 0; i <= ADV_MAX_TID; i++) {
4003 if ((chip_scsi_id == i) ||
4004 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4005 continue;
4006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004008 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
4009 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004011 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
4012 ASC_PRT_NEXT();
4013 }
4014 len = asc_prt_line(cp, leftlen, "\n");
4015 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004017 len = asc_prt_line(cp, leftlen, " Command Pending:");
4018 ASC_PRT_NEXT();
4019 for (i = 0; i <= ADV_MAX_TID; i++) {
4020 if ((chip_scsi_id == i) ||
4021 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4022 continue;
4023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004025 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
4026 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004028 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
4029 ASC_PRT_NEXT();
4030 }
4031 len = asc_prt_line(cp, leftlen, "\n");
4032 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004034 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
4035 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
4036 ASC_PRT_NEXT();
4037 for (i = 0; i <= ADV_MAX_TID; i++) {
4038 if ((chip_scsi_id == i) ||
4039 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4040 continue;
4041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004043 len = asc_prt_line(cp, leftlen, " %X:%c",
4044 i,
4045 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4046 'N');
4047 ASC_PRT_NEXT();
4048 }
4049 len = asc_prt_line(cp, leftlen, "\n");
4050 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004052 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
4053 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
4054 ASC_PRT_NEXT();
4055 for (i = 0; i <= ADV_MAX_TID; i++) {
4056 if ((chip_scsi_id == i) ||
4057 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4058 continue;
4059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004061 AdvReadWordLram(iop_base,
4062 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
4063 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004065 len = asc_prt_line(cp, leftlen, " %X:%d",
4066 i, (lramword & 0x8000) ? 16 : 8);
4067 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004069 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
4070 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
4071 len = asc_prt_line(cp, leftlen, "*");
4072 ASC_PRT_NEXT();
4073 renegotiate = 1;
4074 }
4075 }
4076 len = asc_prt_line(cp, leftlen, "\n");
4077 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004079 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
4080 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
4081 ASC_PRT_NEXT();
4082 for (i = 0; i <= ADV_MAX_TID; i++) {
4083 if ((chip_scsi_id == i) ||
4084 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4085 continue;
4086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004088 len = asc_prt_line(cp, leftlen, " %X:%c",
4089 i,
4090 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4091 'N');
4092 ASC_PRT_NEXT();
4093 }
4094 len = asc_prt_line(cp, leftlen, "\n");
4095 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004097 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
4098 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004100 AdvReadWordLram(iop_base,
4101 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
4102 lramword);
4103 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004105 if ((chip_scsi_id == i) ||
4106 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
4107 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
4108 continue;
4109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004111 len = asc_prt_line(cp, leftlen, " %X:", i);
4112 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004114 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
4115 len = asc_prt_line(cp, leftlen, " Asynchronous");
4116 ASC_PRT_NEXT();
4117 } else {
4118 len =
4119 asc_prt_line(cp, leftlen,
4120 " Transfer Period Factor: ");
4121 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004123 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
4124 len =
4125 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
4126 ASC_PRT_NEXT();
4127 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
4128 len =
4129 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
4130 ASC_PRT_NEXT();
4131 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004133 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004135 if (period == 0) { /* Should never happen. */
4136 len =
4137 asc_prt_line(cp, leftlen,
4138 "%d (? Mhz), ");
4139 ASC_PRT_NEXT();
4140 } else {
4141 len = asc_prt_line(cp, leftlen,
4142 "%d (%d.%d Mhz),",
4143 period, 250 / period,
4144 ASC_TENTHS(250,
4145 period));
4146 ASC_PRT_NEXT();
4147 }
4148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004150 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
4151 lramword & 0x1F);
4152 ASC_PRT_NEXT();
4153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004155 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
4156 len = asc_prt_line(cp, leftlen, "*\n");
4157 renegotiate = 1;
4158 } else {
4159 len = asc_prt_line(cp, leftlen, "\n");
4160 }
4161 ASC_PRT_NEXT();
4162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004164 if (renegotiate) {
4165 len = asc_prt_line(cp, leftlen,
4166 " * = Re-negotiation pending before next command.\n");
4167 ASC_PRT_NEXT();
4168 }
4169
4170 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171}
4172
4173/*
4174 * asc_proc_copy()
4175 *
4176 * Copy proc information to a read buffer taking into account the current
4177 * read offset in the file and the remaining space in the read buffer.
4178 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004179static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004181 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004183 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004185 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
4186 (unsigned)offset, (unsigned)advoffset, cplen);
4187 if (offset <= advoffset) {
4188 /* Read offset below current offset, copy everything. */
4189 cnt = min(cplen, leftlen);
4190 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
4191 (ulong)curbuf, (ulong)cp, cnt);
4192 memcpy(curbuf, cp, cnt);
4193 } else if (offset < advoffset + cplen) {
4194 /* Read offset within current range, partial copy. */
4195 cnt = (advoffset + cplen) - offset;
4196 cp = (cp + cplen) - cnt;
4197 cnt = min(cnt, leftlen);
4198 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
4199 (ulong)curbuf, (ulong)cp, cnt);
4200 memcpy(curbuf, cp, cnt);
4201 }
4202 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203}
4204
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205#ifdef ADVANSYS_STATS
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206/*
4207 * asc_prt_board_stats()
4208 *
4209 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4210 * cf. asc_prt_line().
4211 *
4212 * Return the number of characters copied into 'cp'. No more than
4213 * 'cplen' characters will be copied to 'cp'.
4214 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004215static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004217 int leftlen;
4218 int totlen;
4219 int len;
4220 struct asc_stats *s;
4221 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004223 leftlen = cplen;
4224 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004226 boardp = ASC_BOARDP(shost);
4227 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004229 len = asc_prt_line(cp, leftlen,
4230 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
4231 shost->host_no);
4232 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004234 len = asc_prt_line(cp, leftlen,
4235 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
4236 s->queuecommand, s->reset, s->biosparam,
4237 s->interrupt);
4238 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004240 len = asc_prt_line(cp, leftlen,
4241 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
4242 s->callback, s->done, s->build_error,
4243 s->adv_build_noreq, s->adv_build_nosg);
4244 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004246 len = asc_prt_line(cp, leftlen,
4247 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
4248 s->exe_noerror, s->exe_busy, s->exe_error,
4249 s->exe_unknown);
4250 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004252 /*
4253 * Display data transfer statistics.
4254 */
4255 if (s->cont_cnt > 0) {
4256 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
4257 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004259 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
4260 s->cont_xfer / 2,
4261 ASC_TENTHS(s->cont_xfer, 2));
4262 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004264 /* Contiguous transfer average size */
4265 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
4266 (s->cont_xfer / 2) / s->cont_cnt,
4267 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
4268 ASC_PRT_NEXT();
4269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004271 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004273 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
4274 s->sg_cnt, s->sg_elem);
4275 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004277 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
4278 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
4279 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004281 /* Scatter gather transfer statistics */
4282 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
4283 s->sg_elem / s->sg_cnt,
4284 ASC_TENTHS(s->sg_elem, s->sg_cnt));
4285 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004287 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
4288 (s->sg_xfer / 2) / s->sg_elem,
4289 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
4290 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004292 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
4293 (s->sg_xfer / 2) / s->sg_cnt,
4294 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
4295 ASC_PRT_NEXT();
4296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004298 /*
4299 * Display request queuing statistics.
4300 */
4301 len = asc_prt_line(cp, leftlen,
4302 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
4303 HZ);
4304 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004306 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308#endif /* ADVANSYS_STATS */
4309
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310/*
Matthew Wilcox51219352007-10-02 21:55:22 -04004311 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
4312 *
4313 * *buffer: I/O buffer
4314 * **start: if inout == FALSE pointer into buffer where user read should start
4315 * offset: current offset into a /proc/scsi/advansys/[0...] file
4316 * length: length of buffer
4317 * hostno: Scsi_Host host_no
4318 * inout: TRUE - user is writing; FALSE - user is reading
4319 *
4320 * Return the number of bytes read from or written to a
4321 * /proc/scsi/advansys/[0...] file.
4322 *
4323 * Note: This function uses the per board buffer 'prtbuf' which is
4324 * allocated when the board is initialized in advansys_detect(). The
4325 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4326 * used to write to the buffer. The way asc_proc_copy() is written
4327 * if 'prtbuf' is too small it will not be overwritten. Instead the
4328 * user just won't get all the available statistics.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 */
Matthew Wilcox51219352007-10-02 21:55:22 -04004330static int
4331advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
4332 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004334 asc_board_t *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04004335 char *cp;
4336 int cplen;
4337 int cnt;
4338 int totcnt;
4339 int leftlen;
4340 char *curbuf;
4341 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Matthew Wilcox51219352007-10-02 21:55:22 -04004343 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Matthew Wilcox51219352007-10-02 21:55:22 -04004345 /*
4346 * User write not supported.
4347 */
4348 if (inout == TRUE) {
4349 return (-ENOSYS);
4350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351
Matthew Wilcox51219352007-10-02 21:55:22 -04004352 /*
4353 * User read of /proc/scsi/advansys/[0...] file.
4354 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355
Matthew Wilcox51219352007-10-02 21:55:22 -04004356 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357
Matthew Wilcox51219352007-10-02 21:55:22 -04004358 /* Copy read data starting at the beginning of the buffer. */
4359 *start = buffer;
4360 curbuf = buffer;
4361 advoffset = 0;
4362 totcnt = 0;
4363 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364
Matthew Wilcox51219352007-10-02 21:55:22 -04004365 /*
4366 * Get board configuration information.
4367 *
4368 * advansys_info() returns the board string from its own static buffer.
4369 */
4370 cp = (char *)advansys_info(shost);
4371 strcat(cp, "\n");
4372 cplen = strlen(cp);
4373 /* Copy board information. */
4374 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4375 totcnt += cnt;
4376 leftlen -= cnt;
4377 if (leftlen == 0) {
4378 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4379 return totcnt;
4380 }
4381 advoffset += cplen;
4382 curbuf += cnt;
4383
4384 /*
4385 * Display Wide Board BIOS Information.
4386 */
Matthew Wilcox9a256fa2007-10-02 21:55:28 -04004387 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004388 cp = boardp->prtbuf;
4389 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
4390 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4391 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4392 cplen);
4393 totcnt += cnt;
4394 leftlen -= cnt;
4395 if (leftlen == 0) {
4396 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4397 return totcnt;
4398 }
4399 advoffset += cplen;
4400 curbuf += cnt;
4401 }
4402
4403 /*
4404 * Display driver information for each device attached to the board.
4405 */
4406 cp = boardp->prtbuf;
4407 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
4408 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4409 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4410 totcnt += cnt;
4411 leftlen -= cnt;
4412 if (leftlen == 0) {
4413 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4414 return totcnt;
4415 }
4416 advoffset += cplen;
4417 curbuf += cnt;
4418
4419 /*
4420 * Display EEPROM configuration for the board.
4421 */
4422 cp = boardp->prtbuf;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004423 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004424 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004425 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04004426 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004427 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004428 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4429 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4430 totcnt += cnt;
4431 leftlen -= cnt;
4432 if (leftlen == 0) {
4433 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4434 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004435 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004436 advoffset += cplen;
4437 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Matthew Wilcox51219352007-10-02 21:55:22 -04004439 /*
4440 * Display driver configuration and information for the board.
4441 */
4442 cp = boardp->prtbuf;
4443 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
4444 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4445 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4446 totcnt += cnt;
4447 leftlen -= cnt;
4448 if (leftlen == 0) {
4449 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4450 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004451 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004452 advoffset += cplen;
4453 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454
Matthew Wilcox51219352007-10-02 21:55:22 -04004455#ifdef ADVANSYS_STATS
4456 /*
4457 * Display driver statistics for the board.
4458 */
4459 cp = boardp->prtbuf;
4460 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
4461 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4462 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4463 totcnt += cnt;
4464 leftlen -= cnt;
4465 if (leftlen == 0) {
4466 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4467 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004468 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004469 advoffset += cplen;
4470 curbuf += cnt;
4471#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472
Matthew Wilcox51219352007-10-02 21:55:22 -04004473 /*
4474 * Display Asc Library dynamic configuration information
4475 * for the board.
4476 */
4477 cp = boardp->prtbuf;
4478 if (ASC_NARROW_BOARD(boardp)) {
4479 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
4480 } else {
4481 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004482 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004483 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4484 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4485 totcnt += cnt;
4486 leftlen -= cnt;
4487 if (leftlen == 0) {
4488 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4489 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004490 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004491 advoffset += cplen;
4492 curbuf += cnt;
4493
4494 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4495
4496 return totcnt;
4497}
4498#endif /* CONFIG_PROC_FS */
4499
4500static void asc_scsi_done(struct scsi_cmnd *scp)
4501{
4502 struct asc_board *boardp = ASC_BOARDP(scp->device->host);
4503
4504 if (scp->use_sg)
4505 dma_unmap_sg(boardp->dev,
4506 (struct scatterlist *)scp->request_buffer,
4507 scp->use_sg, scp->sc_data_direction);
4508 else if (scp->request_bufflen)
4509 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
4510 scp->request_bufflen, scp->sc_data_direction);
4511
4512 ASC_STATS(scp->device->host, done);
4513
4514 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515}
4516
Matthew Wilcox51219352007-10-02 21:55:22 -04004517static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518{
Matthew Wilcox51219352007-10-02 21:55:22 -04004519 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
Matthew Wilcox51219352007-10-02 21:55:22 -04004521 val = AscGetChipControl(iop_base) &
4522 (~
4523 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
4524 CC_CHIP_RESET));
4525 if (bank == 1) {
4526 val |= CC_BANK_ONE;
4527 } else if (bank == 2) {
4528 val |= CC_DIAG | CC_BANK_ONE;
4529 } else {
4530 val &= ~CC_BANK_ONE;
4531 }
4532 AscSetChipControl(iop_base, val);
4533 return;
4534}
4535
4536static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
4537{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004538 AscSetBank(iop_base, 1);
Matthew Wilcox51219352007-10-02 21:55:22 -04004539 AscWriteChipIH(iop_base, ins_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004540 AscSetBank(iop_base, 0);
Matthew Wilcox51219352007-10-02 21:55:22 -04004541 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542}
4543
Matthew Wilcox51219352007-10-02 21:55:22 -04004544static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545{
Matthew Wilcox51219352007-10-02 21:55:22 -04004546 AscSetChipControl(iop_base, 0);
4547 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4548 return (0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004549 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004550 return (1);
4551}
4552
4553static int AscStopChip(PortAddr iop_base)
4554{
4555 uchar cc_val;
4556
4557 cc_val =
4558 AscGetChipControl(iop_base) &
4559 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
4560 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
4561 AscSetChipIH(iop_base, INS_HALT);
4562 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4563 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
4564 return (0);
4565 }
4566 return (1);
4567}
4568
4569static int AscIsChipHalted(PortAddr iop_base)
4570{
4571 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4572 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
4573 return (1);
4574 }
4575 }
4576 return (0);
4577}
4578
4579static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
4580{
4581 PortAddr iop_base;
4582 int i = 10;
4583
4584 iop_base = asc_dvc->iop_base;
4585 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
4586 && (i-- > 0)) {
4587 mdelay(100);
4588 }
4589 AscStopChip(iop_base);
4590 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
4591 udelay(60);
4592 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4593 AscSetChipIH(iop_base, INS_HALT);
4594 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
4595 AscSetChipControl(iop_base, CC_HALT);
4596 mdelay(200);
4597 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
4598 AscSetChipStatus(iop_base, 0);
4599 return (AscIsChipHalted(iop_base));
4600}
4601
4602static int AscFindSignature(PortAddr iop_base)
4603{
4604 ushort sig_word;
4605
4606 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
4607 iop_base, AscGetChipSignatureByte(iop_base));
4608 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
4609 ASC_DBG2(1,
4610 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
4611 iop_base, AscGetChipSignatureWord(iop_base));
4612 sig_word = AscGetChipSignatureWord(iop_base);
4613 if ((sig_word == (ushort)ASC_1000_ID0W) ||
4614 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
4615 return (1);
4616 }
4617 }
4618 return (0);
4619}
4620
4621static void AscEnableInterrupt(PortAddr iop_base)
4622{
4623 ushort cfg;
4624
4625 cfg = AscGetChipCfgLsw(iop_base);
4626 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
4627 return;
4628}
4629
4630static void AscDisableInterrupt(PortAddr iop_base)
4631{
4632 ushort cfg;
4633
4634 cfg = AscGetChipCfgLsw(iop_base);
4635 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
4636 return;
4637}
4638
4639static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
4640{
4641 unsigned char byte_data;
4642 unsigned short word_data;
4643
4644 if (isodd_word(addr)) {
4645 AscSetChipLramAddr(iop_base, addr - 1);
4646 word_data = AscGetChipLramData(iop_base);
4647 byte_data = (word_data >> 8) & 0xFF;
4648 } else {
4649 AscSetChipLramAddr(iop_base, addr);
4650 word_data = AscGetChipLramData(iop_base);
4651 byte_data = word_data & 0xFF;
4652 }
4653 return byte_data;
4654}
4655
4656static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
4657{
4658 ushort word_data;
4659
4660 AscSetChipLramAddr(iop_base, addr);
4661 word_data = AscGetChipLramData(iop_base);
4662 return (word_data);
4663}
4664
4665#if CC_VERY_LONG_SG_LIST
4666static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
4667{
4668 ushort val_low, val_high;
4669 ASC_DCNT dword_data;
4670
4671 AscSetChipLramAddr(iop_base, addr);
4672 val_low = AscGetChipLramData(iop_base);
4673 val_high = AscGetChipLramData(iop_base);
4674 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
4675 return (dword_data);
4676}
4677#endif /* CC_VERY_LONG_SG_LIST */
4678
4679static void
4680AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
4681{
4682 int i;
4683
4684 AscSetChipLramAddr(iop_base, s_addr);
4685 for (i = 0; i < words; i++) {
4686 AscSetChipLramData(iop_base, set_wval);
4687 }
4688}
4689
4690static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
4691{
4692 AscSetChipLramAddr(iop_base, addr);
4693 AscSetChipLramData(iop_base, word_val);
4694 return;
4695}
4696
4697static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
4698{
4699 ushort word_data;
4700
4701 if (isodd_word(addr)) {
4702 addr--;
4703 word_data = AscReadLramWord(iop_base, addr);
4704 word_data &= 0x00FF;
4705 word_data |= (((ushort)byte_val << 8) & 0xFF00);
4706 } else {
4707 word_data = AscReadLramWord(iop_base, addr);
4708 word_data &= 0xFF00;
4709 word_data |= ((ushort)byte_val & 0x00FF);
4710 }
4711 AscWriteLramWord(iop_base, addr, word_data);
4712 return;
4713}
4714
4715/*
4716 * Copy 2 bytes to LRAM.
4717 *
4718 * The source data is assumed to be in little-endian order in memory
4719 * and is maintained in little-endian order when written to LRAM.
4720 */
4721static void
4722AscMemWordCopyPtrToLram(PortAddr iop_base,
4723 ushort s_addr, uchar *s_buffer, int words)
4724{
4725 int i;
4726
4727 AscSetChipLramAddr(iop_base, s_addr);
4728 for (i = 0; i < 2 * words; i += 2) {
4729 /*
4730 * On a little-endian system the second argument below
4731 * produces a little-endian ushort which is written to
4732 * LRAM in little-endian order. On a big-endian system
4733 * the second argument produces a big-endian ushort which
4734 * is "transparently" byte-swapped by outpw() and written
4735 * in little-endian order to LRAM.
4736 */
4737 outpw(iop_base + IOP_RAM_DATA,
4738 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
4739 }
4740 return;
4741}
4742
4743/*
4744 * Copy 4 bytes to LRAM.
4745 *
4746 * The source data is assumed to be in little-endian order in memory
4747 * and is maintained in little-endian order when writen to LRAM.
4748 */
4749static void
4750AscMemDWordCopyPtrToLram(PortAddr iop_base,
4751 ushort s_addr, uchar *s_buffer, int dwords)
4752{
4753 int i;
4754
4755 AscSetChipLramAddr(iop_base, s_addr);
4756 for (i = 0; i < 4 * dwords; i += 4) {
4757 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
4758 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
4759 }
4760 return;
4761}
4762
4763/*
4764 * Copy 2 bytes from LRAM.
4765 *
4766 * The source data is assumed to be in little-endian order in LRAM
4767 * and is maintained in little-endian order when written to memory.
4768 */
4769static void
4770AscMemWordCopyPtrFromLram(PortAddr iop_base,
4771 ushort s_addr, uchar *d_buffer, int words)
4772{
4773 int i;
4774 ushort word;
4775
4776 AscSetChipLramAddr(iop_base, s_addr);
4777 for (i = 0; i < 2 * words; i += 2) {
4778 word = inpw(iop_base + IOP_RAM_DATA);
4779 d_buffer[i] = word & 0xff;
4780 d_buffer[i + 1] = (word >> 8) & 0xff;
4781 }
4782 return;
4783}
4784
4785static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
4786{
4787 ASC_DCNT sum;
4788 int i;
4789
4790 sum = 0L;
4791 for (i = 0; i < words; i++, s_addr += 2) {
4792 sum += AscReadLramWord(iop_base, s_addr);
4793 }
4794 return (sum);
4795}
4796
4797static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
4798{
4799 uchar i;
4800 ushort s_addr;
4801 PortAddr iop_base;
4802 ushort warn_code;
4803
4804 iop_base = asc_dvc->iop_base;
4805 warn_code = 0;
4806 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
4807 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
4808 64) >> 1));
4809 i = ASC_MIN_ACTIVE_QNO;
4810 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
4811 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4812 (uchar)(i + 1));
4813 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4814 (uchar)(asc_dvc->max_total_qng));
4815 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4816 (uchar)i);
4817 i++;
4818 s_addr += ASC_QBLK_SIZE;
4819 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
4820 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4821 (uchar)(i + 1));
4822 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4823 (uchar)(i - 1));
4824 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4825 (uchar)i);
4826 }
4827 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4828 (uchar)ASC_QLINK_END);
4829 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4830 (uchar)(asc_dvc->max_total_qng - 1));
4831 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4832 (uchar)asc_dvc->max_total_qng);
4833 i++;
4834 s_addr += ASC_QBLK_SIZE;
4835 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
4836 i++, s_addr += ASC_QBLK_SIZE) {
4837 AscWriteLramByte(iop_base,
4838 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
4839 AscWriteLramByte(iop_base,
4840 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
4841 AscWriteLramByte(iop_base,
4842 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
4843 }
4844 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845}
4846
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004847static ASC_DCNT
4848AscLoadMicroCode(PortAddr iop_base,
4849 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004850{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004851 ASC_DCNT chksum;
4852 ushort mcode_word_size;
4853 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004854
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004855 /* Write the microcode buffer starting at LRAM address 0. */
4856 mcode_word_size = (ushort)(mcode_size >> 1);
4857 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
4858 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004860 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
4861 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
4862 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
4863 (ushort)ASC_CODE_SEC_BEG,
4864 (ushort)((mcode_size -
4865 s_addr - (ushort)
4866 ASC_CODE_SEC_BEG) /
4867 2));
4868 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
4869 (ulong)mcode_chksum);
4870 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
4871 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
4872 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873}
4874
Linus Torvalds1da177e2005-04-16 15:20:36 -07004875/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004876static uchar _asc_mcode_buf[] = {
4877 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004878 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
4883 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4884 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004885 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004886 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
4887 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
4888 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004889 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004890 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
4891 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
4892 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004893 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004894 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
4895 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
4896 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004897 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004898 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
4899 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
4900 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004901 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004902 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
4903 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
4904 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004905 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004906 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
4907 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
4908 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004909 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004910 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
4911 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
4912 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004913 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004914 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
4915 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
4916 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004917 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004918 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
4919 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
4920 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004921 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004922 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
4923 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
4924 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004925 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004926 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
4927 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
4928 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004929 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004930 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
4931 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
4932 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004933 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004934 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
4935 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
4936 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004937 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004938 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
4939 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
4940 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004941 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004942 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
4943 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
4944 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004945 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004946 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
4947 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
4948 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004949 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004950 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
4951 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
4952 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004953 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004954 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
4955 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
4956 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004957 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004958 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
4959 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
4960 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004961 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004962 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
4963 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
4964 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004965 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004966 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
4967 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
4968 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004969 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004970 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
4971 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
4972 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004973 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004974 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
4975 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
4976 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004977 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004978 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
4979 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
4980 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004981 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004982 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
4983 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
4984 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004985 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004986 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
4987 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
4988 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004989 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004990 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
4991 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
4992 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004993 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004994 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
4995 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
4996 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004997 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004998 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
4999 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
5000 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005001 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005002 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
5003 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
5004 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005005 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005006 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
5007 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
5008 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005009 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005010 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
5011 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
5012 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005013 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005014 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
5015 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
5016 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005017 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005018 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
5019 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
5020 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005021 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005022 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
5023 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
5024 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005025 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005026 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
5027 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
5028 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005029 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005030 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
5031 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
5032 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005033 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005034 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
5035 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
5036 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005037 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005038 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
5039 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
5040 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005041 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005042 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
5043 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
5044 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005045 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005046 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
5047 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
5048 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005049 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005050 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
5051 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
5052 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005053 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005054 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
5055 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
5056 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005057 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005058 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
5059 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
5060 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005061 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005062 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
5063 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
5064 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005065 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005066 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
5067 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
5068 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069};
5070
Matthew Wilcox51219352007-10-02 21:55:22 -04005071static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005072static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005075static unsigned char _adv_asc3550_buf[] = {
5076 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005077 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
5078 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
5079 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005080 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005081 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
5082 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
5083 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005084 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005085 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
5086 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
5087 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005088 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005089 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
5090 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
5091 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005092 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005093 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
5094 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
5095 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005096 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005097 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
5098 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
5099 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005100 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005101 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
5102 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
5103 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005104 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005105 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
5106 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
5107 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005108 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005109 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
5110 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
5111 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005112 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005113 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
5114 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
5115 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005116 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005117 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
5118 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
5119 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005120 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005121 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
5122 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5123 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005124 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005125 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
5126 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
5127 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005128 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005129 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
5130 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5131 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005132 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005133 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
5134 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
5135 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005136 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005137 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
5138 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
5139 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005140 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005141 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
5142 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
5143 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005144 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005145 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
5146 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
5147 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005148 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005149 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
5150 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
5151 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005152 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005153 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
5154 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
5155 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005156 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005157 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
5158 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
5159 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005160 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005161 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
5162 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
5163 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005164 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005165 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
5166 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
5167 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005168 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005169 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
5170 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
5171 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005172 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005173 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
5174 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
5175 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005176 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005177 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
5178 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
5179 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005180 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005181 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
5182 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
5183 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005184 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005185 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
5186 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
5187 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005188 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005189 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
5190 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
5191 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005192 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005193 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
5194 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
5195 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005196 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005197 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
5198 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
5199 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005200 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005201 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
5202 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
5203 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005204 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005205 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
5206 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
5207 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005208 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005209 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
5210 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
5211 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005212 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005213 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
5214 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
5215 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005216 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005217 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
5218 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
5219 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005220 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005221 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5222 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
5223 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005224 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005225 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
5226 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
5227 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005228 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005229 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
5230 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
5231 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005232 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005233 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
5234 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
5235 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005236 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005237 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
5238 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
5239 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005240 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005241 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
5242 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
5243 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005244 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005245 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
5246 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
5247 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005248 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005249 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
5250 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
5251 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005252 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005253 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
5254 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
5255 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005256 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005257 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
5258 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
5259 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005260 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005261 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
5262 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
5263 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005264 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005265 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
5266 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
5267 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005268 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005269 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
5270 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
5271 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005272 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005273 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
5274 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
5275 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005276 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005277 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
5278 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
5279 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005280 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005281 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
5282 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
5283 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005284 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005285 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
5286 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
5287 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005288 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005289 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
5290 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
5291 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005292 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005293 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
5294 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
5295 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005296 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005297 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
5298 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
5299 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005300 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005301 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
5302 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
5303 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005304 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005305 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
5306 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
5307 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005308 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005309 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
5310 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
5311 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005312 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005313 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
5314 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
5315 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005316 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005317 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
5318 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
5319 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005320 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005321 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
5322 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
5323 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005324 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005325 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
5326 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
5327 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005328 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005329 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
5330 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
5331 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005332 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005333 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
5334 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
5335 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005336 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005337 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
5338 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
5339 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005340 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005341 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
5342 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
5343 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005344 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005345 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
5346 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
5347 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005348 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005349 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
5350 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
5351 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005352 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005353 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
5354 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
5355 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005356 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005357 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
5358 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
5359 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005360 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005361 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
5362 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
5363 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005364 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005365 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
5366 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
5367 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005368 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005369 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
5370 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
5371 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005372 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005373 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
5374 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
5375 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005376 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005377 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
5378 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
5379 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005380 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005381 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
5382 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
5383 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005384 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005385 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
5386 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
5387 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005388 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005389 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
5390 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
5391 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005392 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005393 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
5394 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
5395 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005396 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005397 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
5398 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
5399 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005400 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005401 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
5402 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
5403 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005404 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005405 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
5406 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
5407 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005408 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005409 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
5410 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
5411 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005412 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005413 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
5414 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
5415 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005416 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005417 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
5418 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
5419 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005420 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005421 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
5422 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
5423 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005424 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005425 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
5426 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
5427 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005428 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005429 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
5430 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
5431 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005432 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005433 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
5434 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
5435 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005436 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005437 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
5438 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
5439 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005440 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005441 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
5442 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
5443 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005444 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005445 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
5446 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
5447 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005448 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005449 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
5450 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
5451 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005452 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005453 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
5454 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
5455 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005456 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005457 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
5458 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
5459 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005460 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005461 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
5462 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
5463 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005464 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005465 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
5466 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
5467 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005468 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005469 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
5470 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
5471 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005472 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005473 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
5474 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
5475 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005476 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005477 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
5478 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
5479 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005480 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005481 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
5482 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
5483 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005485 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
5486 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
5487 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005488 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005489 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
5490 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
5491 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005492 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005493 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
5494 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495};
5496
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005497static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
5498static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499
5500/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005501static unsigned char _adv_asc38C0800_buf[] = {
5502 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005503 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
5504 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
5505 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005506 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005507 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
5508 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
5509 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005510 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005511 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
5512 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
5513 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005514 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005515 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
5516 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
5517 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005518 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005519 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
5520 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
5521 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005522 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005523 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
5524 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
5525 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005526 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005527 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
5528 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
5529 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005530 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005531 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
5532 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
5533 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005534 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005535 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
5536 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
5537 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005538 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005539 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
5540 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
5541 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005542 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005543 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
5544 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
5545 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005546 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005547 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
5548 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5549 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005550 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005551 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
5552 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
5553 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005554 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005555 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
5556 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5557 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005558 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005559 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
5560 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
5561 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005562 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005563 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
5564 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
5565 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005566 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005567 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
5568 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
5569 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005570 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005571 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
5572 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
5573 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005574 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005575 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
5576 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
5577 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005578 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005579 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
5580 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
5581 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005582 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005583 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
5584 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
5585 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005586 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005587 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
5588 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
5589 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005590 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005591 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
5592 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
5593 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005594 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005595 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
5596 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
5597 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005598 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005599 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
5600 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
5601 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005602 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005603 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
5604 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
5605 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005606 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005607 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
5608 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
5609 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005610 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005611 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
5612 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
5613 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005614 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005615 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
5616 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
5617 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005618 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005619 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
5620 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
5621 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005622 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005623 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
5624 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
5625 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005626 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005627 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
5628 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
5629 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005630 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005631 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
5632 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
5633 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005634 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005635 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
5636 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
5637 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005638 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005639 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
5640 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
5641 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005642 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005643 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
5644 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
5645 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005646 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005647 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
5648 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
5649 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005650 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005651 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
5652 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
5653 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005654 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005655 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
5656 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
5657 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005658 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005659 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
5660 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
5661 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005662 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005663 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
5664 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
5665 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005666 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005667 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
5668 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
5669 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005670 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005671 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
5672 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
5673 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005674 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005675 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
5676 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
5677 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005678 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005679 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
5680 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
5681 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005682 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005683 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
5684 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
5685 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005686 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005687 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
5688 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
5689 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005690 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005691 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
5692 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
5693 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005694 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005695 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
5696 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
5697 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005698 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005699 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
5700 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
5701 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005702 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005703 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
5704 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
5705 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005706 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005707 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
5708 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
5709 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005710 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005711 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
5712 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
5713 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005714 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005715 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
5716 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
5717 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005718 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005719 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
5720 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
5721 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005722 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005723 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
5724 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
5725 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005726 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005727 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
5728 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
5729 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005730 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005731 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
5732 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
5733 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005734 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005735 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
5736 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
5737 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005738 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005739 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
5740 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
5741 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005742 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005743 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
5744 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
5745 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005746 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005747 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
5748 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
5749 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005750 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005751 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
5752 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
5753 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005754 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005755 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
5756 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
5757 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005758 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005759 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
5760 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
5761 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005762 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005763 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
5764 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
5765 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005766 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005767 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
5768 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
5769 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005770 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005771 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
5772 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
5773 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005774 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005775 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
5776 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
5777 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005778 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005779 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
5780 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
5781 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005782 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005783 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
5784 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
5785 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005786 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005787 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
5788 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
5789 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005790 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005791 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
5792 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
5793 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005794 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005795 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
5796 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
5797 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005798 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005799 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
5800 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
5801 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005802 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005803 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
5804 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
5805 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005806 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005807 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
5808 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
5809 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005810 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005811 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
5812 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
5813 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005814 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005815 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
5816 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
5817 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005818 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005819 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
5820 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
5821 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005822 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005823 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
5824 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
5825 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005826 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005827 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
5828 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
5829 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005830 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005831 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
5832 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
5833 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005834 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005835 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
5836 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
5837 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005838 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005839 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
5840 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
5841 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005842 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005843 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
5844 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
5845 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005846 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005847 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
5848 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5849 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005850 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005851 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5852 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
5853 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005854 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005855 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
5856 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
5857 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005858 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005859 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
5860 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
5861 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005862 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005863 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
5864 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
5865 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005866 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005867 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
5868 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
5869 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005870 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005871 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
5872 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
5873 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005874 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005875 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
5876 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
5877 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005878 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005879 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
5880 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
5881 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005882 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005883 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
5884 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
5885 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005886 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005887 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
5888 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
5889 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005890 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005891 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
5892 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
5893 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005894 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005895 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
5896 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
5897 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005898 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005899 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
5900 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
5901 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005902 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005903 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
5904 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
5905 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005906 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005907 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
5908 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
5909 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005910 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005911 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
5912 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
5913 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005914 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005915 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
5916 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
5917 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005918 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005919 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
5920 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
5921 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005922 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005923 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
5924 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
5925 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005926 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005927 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
5928 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
5929 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005930 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005931 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
5932 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
5933 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005934 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005935 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
5936 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
5937 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005938 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005939 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
5940 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
5941 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005942 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005943 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
5944 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
5945 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005946 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947};
5948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005949static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
5950static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005951
5952/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005953static unsigned char _adv_asc38C1600_buf[] = {
5954 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005955 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
5956 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
5957 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005958 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005959 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
5960 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
5961 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005962 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005963 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
5964 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
5965 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005966 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005967 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
5968 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
5969 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005970 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005971 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
5972 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
5973 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005974 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005975 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
5976 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
5977 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005978 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005979 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
5980 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
5981 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005982 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005983 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
5984 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
5985 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005986 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005987 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
5988 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
5989 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005990 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005991 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
5992 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
5993 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005994 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005995 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
5996 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
5997 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005998 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005999 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
6000 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
6001 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006002 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006003 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
6004 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
6005 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006006 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006007 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
6008 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
6009 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006010 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006011 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
6012 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
6013 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006014 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006015 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
6016 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
6017 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006018 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006019 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
6020 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
6021 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006022 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006023 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
6024 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
6025 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006026 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006027 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
6028 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
6029 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006030 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006031 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
6032 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
6033 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006034 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006035 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
6036 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
6037 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006038 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006039 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
6040 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
6041 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006042 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006043 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
6044 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
6045 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006046 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006047 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
6048 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
6049 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006050 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006051 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
6052 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
6053 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006054 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006055 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
6056 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
6057 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006058 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006059 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
6060 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
6061 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006062 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006063 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
6064 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
6065 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006066 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006067 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
6068 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
6069 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006070 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006071 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
6072 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
6073 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006074 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006075 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
6076 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
6077 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006078 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006079 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
6080 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
6081 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006082 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006083 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
6084 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
6085 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006086 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006087 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
6088 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
6089 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006090 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006091 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
6092 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
6093 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006094 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006095 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
6096 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
6097 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006098 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006099 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
6100 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
6101 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006102 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006103 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
6104 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
6105 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006106 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006107 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
6108 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
6109 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006110 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006111 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
6112 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
6113 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006114 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006115 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
6116 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
6117 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006118 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006119 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
6120 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
6121 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006122 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006123 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
6124 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
6125 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006126 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006127 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
6128 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
6129 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006130 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006131 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
6132 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
6133 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006134 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006135 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
6136 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
6137 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006138 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006139 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
6140 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
6141 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006142 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006143 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
6144 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
6145 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006146 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006147 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
6148 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
6149 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006150 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006151 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
6152 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
6153 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006154 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006155 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
6156 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
6157 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006158 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006159 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
6160 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
6161 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006162 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006163 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
6164 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
6165 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006166 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006167 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
6168 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
6169 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006170 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006171 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
6172 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
6173 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006174 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006175 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
6176 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
6177 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006178 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006179 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
6180 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
6181 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006182 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006183 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
6184 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
6185 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006186 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006187 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
6188 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
6189 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006190 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006191 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
6192 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
6193 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006194 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006195 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
6196 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
6197 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006198 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006199 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
6200 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
6201 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006202 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006203 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
6204 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
6205 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006206 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006207 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
6208 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
6209 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006210 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006211 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
6212 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
6213 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006214 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006215 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
6216 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
6217 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006218 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006219 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
6220 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
6221 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006222 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006223 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
6224 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
6225 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006226 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006227 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
6228 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
6229 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006230 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006231 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
6232 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
6233 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006234 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006235 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
6236 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
6237 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006238 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006239 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
6240 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
6241 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006242 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006243 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
6244 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
6245 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006246 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006247 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
6248 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
6249 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006250 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006251 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
6252 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
6253 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006254 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006255 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
6256 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
6257 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006258 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006259 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
6260 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
6261 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006262 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006263 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
6264 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
6265 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006266 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006267 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
6268 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
6269 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006270 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006271 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
6272 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
6273 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006274 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006275 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
6276 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
6277 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006278 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006279 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
6280 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
6281 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006282 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006283 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
6284 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
6285 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006286 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006287 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
6288 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
6289 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006290 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006291 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
6292 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
6293 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006294 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006295 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
6296 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
6297 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006298 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006299 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
6300 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
6301 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006302 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006303 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
6304 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
6305 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006306 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006307 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
6308 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
6309 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006310 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006311 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
6312 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
6313 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006314 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006315 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
6316 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
6317 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006318 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006319 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
6320 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
6321 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006322 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006323 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
6324 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
6325 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006326 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006327 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
6328 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
6329 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006330 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006331 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
6332 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
6333 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006334 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006335 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
6336 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
6337 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006338 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006339 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
6340 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
6341 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006342 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006343 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
6344 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
6345 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006346 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006347 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
6348 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
6349 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006350 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006351 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
6352 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
6353 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006354 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006355 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
6356 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
6357 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006358 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006359 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
6360 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
6361 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006362 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006363 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
6364 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
6365 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006366 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006367 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
6368 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
6369 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006370 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006371 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
6372 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
6373 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006374 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006375 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
6376 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
6377 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006378 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006379 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
6380 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
6381 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006382 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006383 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
6384 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
6385 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006386 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006387 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
6388 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
6389 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006390 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006391 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
6392 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
6393 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006394 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006395 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
6396 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
6397 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006398 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006399 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
6400 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
6401 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006402 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006403 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
6404 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
6405 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006406 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006407 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
6408 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
6409 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006410 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006411 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
6412 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
6413 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006414 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006415 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
6416 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
6417 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006418 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006419 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
6420 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
6421 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006422 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006423 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
6424 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
6425 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006426 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006427 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
6428 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
6429 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006430 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006431 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
6432 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
6433 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006434 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006435 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
6436 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
6437 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006438 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006439 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
6440 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
6441 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006442 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006443 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
6444 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
6445 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006446 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006447 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
6448 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
6449 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006450 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006451 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
6452 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
6453 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006454 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006455 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
6456 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
6457 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006458 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006459 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
6460 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
6461 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006462 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006463 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
6464 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
6465 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006466 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006467 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
6468 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
6469 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006470 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006471 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
6472 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
6473 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006474 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006475 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
6476 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
6477 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006478 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006479 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
6480 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
6481 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006482};
6483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006484static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
6485static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486
Matthew Wilcox51219352007-10-02 21:55:22 -04006487static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006488{
Matthew Wilcox51219352007-10-02 21:55:22 -04006489 PortAddr iop_base;
6490 int i;
6491 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492
Matthew Wilcox51219352007-10-02 21:55:22 -04006493 iop_base = asc_dvc->iop_base;
6494 AscPutRiscVarFreeQHead(iop_base, 1);
6495 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6496 AscPutVarFreeQHead(iop_base, 1);
6497 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6498 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6499 (uchar)((int)asc_dvc->max_total_qng + 1));
6500 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6501 (uchar)((int)asc_dvc->max_total_qng + 2));
6502 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
6503 asc_dvc->max_total_qng);
6504 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6505 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6506 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6507 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6508 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6509 AscPutQDoneInProgress(iop_base, 0);
6510 lram_addr = ASC_QADR_BEG;
6511 for (i = 0; i < 32; i++, lram_addr += 2) {
6512 AscWriteLramWord(iop_base, lram_addr, 0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006514}
6515
Matthew Wilcox51219352007-10-02 21:55:22 -04006516static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006517{
Matthew Wilcox51219352007-10-02 21:55:22 -04006518 int i;
6519 ushort warn_code;
6520 PortAddr iop_base;
6521 ASC_PADDR phy_addr;
6522 ASC_DCNT phy_size;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006523
Matthew Wilcox51219352007-10-02 21:55:22 -04006524 iop_base = asc_dvc->iop_base;
6525 warn_code = 0;
6526 for (i = 0; i <= ASC_MAX_TID; i++) {
6527 AscPutMCodeInitSDTRAtID(iop_base, i,
6528 asc_dvc->cfg->sdtr_period_offset[i]);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006529 }
6530
Matthew Wilcox51219352007-10-02 21:55:22 -04006531 AscInitQLinkVar(asc_dvc);
6532 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
6533 asc_dvc->cfg->disc_enable);
6534 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
6535 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006536
Matthew Wilcox51219352007-10-02 21:55:22 -04006537 /* Align overrun buffer on an 8 byte boundary. */
6538 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
6539 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
6540 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
6541 (uchar *)&phy_addr, 1);
6542 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
6543 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
6544 (uchar *)&phy_size, 1);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006545
Matthew Wilcox51219352007-10-02 21:55:22 -04006546 asc_dvc->cfg->mcode_date =
6547 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
6548 asc_dvc->cfg->mcode_version =
6549 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006550
Matthew Wilcox51219352007-10-02 21:55:22 -04006551 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6552 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6553 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
6554 return warn_code;
6555 }
6556 if (AscStartChip(iop_base) != 1) {
6557 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
6558 return warn_code;
6559 }
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006560
Matthew Wilcox51219352007-10-02 21:55:22 -04006561 return warn_code;
6562}
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006563
Matthew Wilcox51219352007-10-02 21:55:22 -04006564static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
6565{
6566 ushort warn_code;
6567 PortAddr iop_base;
6568
6569 iop_base = asc_dvc->iop_base;
6570 warn_code = 0;
6571 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
6572 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
6573 AscResetChipAndScsiBus(asc_dvc);
6574 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6575 }
6576 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
6577 if (asc_dvc->err_code != 0)
6578 return UW_ERR;
6579 if (!AscFindSignature(asc_dvc->iop_base)) {
6580 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
6581 return warn_code;
6582 }
6583 AscDisableInterrupt(iop_base);
6584 warn_code |= AscInitLram(asc_dvc);
6585 if (asc_dvc->err_code != 0)
6586 return UW_ERR;
6587 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
6588 (ulong)_asc_mcode_chksum);
6589 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
6590 _asc_mcode_size) != _asc_mcode_chksum) {
6591 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
6592 return warn_code;
6593 }
6594 warn_code |= AscInitMicroCodeVar(asc_dvc);
6595 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
6596 AscEnableInterrupt(iop_base);
6597 return warn_code;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006598}
6599
Linus Torvalds1da177e2005-04-16 15:20:36 -07006600/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006601 * Load the Microcode
6602 *
6603 * Write the microcode image to RISC memory starting at address 0.
6604 *
6605 * The microcode is stored compressed in the following format:
6606 *
6607 * 254 word (508 byte) table indexed by byte code followed
6608 * by the following byte codes:
6609 *
6610 * 1-Byte Code:
6611 * 00: Emit word 0 in table.
6612 * 01: Emit word 1 in table.
6613 * .
6614 * FD: Emit word 253 in table.
6615 *
6616 * Multi-Byte Code:
6617 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
6618 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
6619 *
6620 * Returns 0 or an error if the checksum doesn't match
6621 */
6622static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
6623 int memsize, int chksum)
6624{
6625 int i, j, end, len = 0;
6626 ADV_DCNT sum;
6627
6628 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6629
6630 for (i = 253 * 2; i < size; i++) {
6631 if (buf[i] == 0xff) {
6632 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
6633 for (j = 0; j < buf[i + 1]; j++) {
6634 AdvWriteWordAutoIncLram(iop_base, word);
6635 len += 2;
6636 }
6637 i += 3;
6638 } else if (buf[i] == 0xfe) {
6639 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
6640 AdvWriteWordAutoIncLram(iop_base, word);
6641 i += 2;
6642 len += 2;
6643 } else {
6644 unsigned char off = buf[i] * 2;
6645 unsigned short word = (buf[off + 1] << 8) | buf[off];
6646 AdvWriteWordAutoIncLram(iop_base, word);
6647 len += 2;
6648 }
6649 }
6650
6651 end = len;
6652
6653 while (len < memsize) {
6654 AdvWriteWordAutoIncLram(iop_base, 0);
6655 len += 2;
6656 }
6657
6658 /* Verify the microcode checksum. */
6659 sum = 0;
6660 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6661
6662 for (len = 0; len < end; len += 2) {
6663 sum += AdvReadWordAutoIncLram(iop_base);
6664 }
6665
6666 if (sum != chksum)
6667 return ASC_IERR_MCODE_CHKSUM;
6668
6669 return 0;
6670}
6671
6672/*
Matthew Wilcox51219352007-10-02 21:55:22 -04006673 * DvcGetPhyAddr()
6674 *
6675 * Return the physical address of 'vaddr' and set '*lenp' to the
6676 * number of physically contiguous bytes that follow 'vaddr'.
6677 * 'flag' indicates the type of structure whose physical address
6678 * is being translated.
6679 *
6680 * Note: Because Linux currently doesn't page the kernel and all
6681 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
6682 */
6683ADV_PADDR
6684DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
6685 uchar *vaddr, ADV_SDCNT *lenp, int flag)
6686{
6687 ADV_PADDR paddr = virt_to_bus(vaddr);
6688
6689 ASC_DBG4(4, "DvcGetPhyAddr: vaddr 0x%p, lenp 0x%p *lenp %lu, paddr 0x%lx\n",
6690 vaddr, lenp, (ulong)*((ulong *)lenp), (ulong)paddr);
6691
6692 return paddr;
6693}
6694
6695static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
6696{
6697 ADV_CARR_T *carrp;
6698 ADV_SDCNT buf_size;
6699 ADV_PADDR carr_paddr;
6700
6701 BUG_ON(!asc_dvc->carrier_buf);
6702
6703 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
6704 asc_dvc->carr_freelist = NULL;
6705 if (carrp == asc_dvc->carrier_buf) {
6706 buf_size = ADV_CARRIER_BUFSIZE;
6707 } else {
6708 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
6709 }
6710
6711 do {
6712 /* Get physical address of the carrier 'carrp'. */
6713 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
6714 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
6715 (uchar *)carrp,
6716 (ADV_SDCNT *)&contig_len,
6717 ADV_IS_CARRIER_FLAG));
6718
6719 buf_size -= sizeof(ADV_CARR_T);
6720
6721 /*
6722 * If the current carrier is not physically contiguous, then
6723 * maybe there was a page crossing. Try the next carrier
6724 * aligned start address.
6725 */
6726 if (contig_len < sizeof(ADV_CARR_T)) {
6727 carrp++;
6728 continue;
6729 }
6730
6731 carrp->carr_pa = carr_paddr;
6732 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
6733
6734 /*
6735 * Insert the carrier at the beginning of the freelist.
6736 */
6737 carrp->next_vpa =
6738 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
6739 asc_dvc->carr_freelist = carrp;
6740
6741 carrp++;
6742 } while (buf_size > 0);
6743}
6744
6745/*
6746 * Send an idle command to the chip and wait for completion.
6747 *
6748 * Command completion is polled for once per microsecond.
6749 *
6750 * The function can be called from anywhere including an interrupt handler.
6751 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
6752 * functions to prevent reentrancy.
6753 *
6754 * Return Values:
6755 * ADV_TRUE - command completed successfully
6756 * ADV_FALSE - command failed
6757 * ADV_ERROR - command timed out
6758 */
6759static int
6760AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
6761 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
6762{
6763 int result;
6764 ADV_DCNT i, j;
6765 AdvPortAddr iop_base;
6766
6767 iop_base = asc_dvc->iop_base;
6768
6769 /*
6770 * Clear the idle command status which is set by the microcode
6771 * to a non-zero value to indicate when the command is completed.
6772 * The non-zero result is one of the IDLE_CMD_STATUS_* values
6773 */
6774 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
6775
6776 /*
6777 * Write the idle command value after the idle command parameter
6778 * has been written to avoid a race condition. If the order is not
6779 * followed, the microcode may process the idle command before the
6780 * parameters have been written to LRAM.
6781 */
6782 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
6783 cpu_to_le32(idle_cmd_parameter));
6784 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
6785
6786 /*
6787 * Tickle the RISC to tell it to process the idle command.
6788 */
6789 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
6790 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
6791 /*
6792 * Clear the tickle value. In the ASC-3550 the RISC flag
6793 * command 'clr_tickle_b' does not work unless the host
6794 * value is cleared.
6795 */
6796 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
6797 }
6798
6799 /* Wait for up to 100 millisecond for the idle command to timeout. */
6800 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
6801 /* Poll once each microsecond for command completion. */
6802 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
6803 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
6804 result);
6805 if (result != 0)
6806 return result;
6807 udelay(1);
6808 }
6809 }
6810
6811 BUG(); /* The idle command should never timeout. */
6812 return ADV_ERROR;
6813}
6814
6815/*
6816 * Reset SCSI Bus and purge all outstanding requests.
6817 *
6818 * Return Value:
6819 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
6820 * ADV_FALSE(0) - Microcode command failed.
6821 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
6822 * may be hung which requires driver recovery.
6823 */
6824static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
6825{
6826 int status;
6827
6828 /*
6829 * Send the SCSI Bus Reset idle start idle command which asserts
6830 * the SCSI Bus Reset signal.
6831 */
6832 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
6833 if (status != ADV_TRUE) {
6834 return status;
6835 }
6836
6837 /*
6838 * Delay for the specified SCSI Bus Reset hold time.
6839 *
6840 * The hold time delay is done on the host because the RISC has no
6841 * microsecond accurate timer.
6842 */
6843 udelay(ASC_SCSI_RESET_HOLD_TIME_US);
6844
6845 /*
6846 * Send the SCSI Bus Reset end idle command which de-asserts
6847 * the SCSI Bus Reset signal and purges any pending requests.
6848 */
6849 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
6850 if (status != ADV_TRUE) {
6851 return status;
6852 }
6853
6854 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6855
6856 return status;
6857}
6858
6859/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006860 * Initialize the ASC-3550.
6861 *
6862 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
6863 *
6864 * For a non-fatal error return a warning code. If there are no warnings
6865 * then 0 is returned.
6866 *
6867 * Needed after initialization for error recovery.
6868 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006869static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006870{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006871 AdvPortAddr iop_base;
6872 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006873 int begin_addr;
6874 int end_addr;
6875 ushort code_sum;
6876 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006877 int i;
6878 ushort scsi_cfg1;
6879 uchar tid;
6880 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
6881 ushort wdtr_able = 0, sdtr_able, tagqng_able;
6882 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006883
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006884 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006885 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006886 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006888 /*
6889 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
6890 */
6891 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006892 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006893 return ADV_ERROR;
6894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006896 warn_code = 0;
6897 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006899 /*
6900 * Save the RISC memory BIOS region before writing the microcode.
6901 * The BIOS may already be loaded and using its RISC LRAM region
6902 * so its region must be saved and restored.
6903 *
6904 * Note: This code makes the assumption, which is currently true,
6905 * that a chip reset does not clear RISC LRAM.
6906 */
6907 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6908 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6909 bios_mem[i]);
6910 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006911
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006912 /*
6913 * Save current per TID negotiated values.
6914 */
6915 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
6916 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006917
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006918 bios_version =
6919 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
6920 major = (bios_version >> 12) & 0xF;
6921 minor = (bios_version >> 8) & 0xF;
6922 if (major < 3 || (major == 3 && minor == 1)) {
6923 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
6924 AdvReadWordLram(iop_base, 0x120, wdtr_able);
6925 } else {
6926 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6927 }
6928 }
6929 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
6930 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6931 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6932 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
6933 max_cmd[tid]);
6934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006936 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
6937 _adv_asc3550_size, ADV_3550_MEMSIZE,
6938 _adv_asc3550_chksum);
6939 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006940 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006942 /*
6943 * Restore the RISC memory BIOS region.
6944 */
6945 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6946 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6947 bios_mem[i]);
6948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006949
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006950 /*
6951 * Calculate and write the microcode code checksum to the microcode
6952 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
6953 */
6954 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
6955 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
6956 code_sum = 0;
6957 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
6958 for (word = begin_addr; word < end_addr; word += 2) {
6959 code_sum += AdvReadWordAutoIncLram(iop_base);
6960 }
6961 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006963 /*
6964 * Read and save microcode version and date.
6965 */
6966 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
6967 asc_dvc->cfg->mcode_date);
6968 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
6969 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006970
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006971 /*
6972 * Set the chip type to indicate the ASC3550.
6973 */
6974 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006976 /*
6977 * If the PCI Configuration Command Register "Parity Error Response
6978 * Control" Bit was clear (0), then set the microcode variable
6979 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
6980 * to ignore DMA parity errors.
6981 */
6982 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
6983 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6984 word |= CONTROL_FLAG_IGNORE_PERR;
6985 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006987
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006988 /*
6989 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
6990 * threshold of 128 bytes. This register is only accessible to the host.
6991 */
6992 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
6993 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006995 /*
6996 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006997 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006998 * device reports it is capable of in Inquiry byte 7.
6999 *
7000 * If SCSI Bus Resets have been disabled, then directly set
7001 * SDTR and WDTR from the EEPROM configuration. This will allow
7002 * the BIOS and warm boot to work without a SCSI bus hang on
7003 * the Inquiry caused by host and target mismatched DTR values.
7004 * Without the SCSI Bus Reset, before an Inquiry a device can't
7005 * be assumed to be in Asynchronous, Narrow mode.
7006 */
7007 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7008 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7009 asc_dvc->wdtr_able);
7010 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7011 asc_dvc->sdtr_able);
7012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007014 /*
7015 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
7016 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
7017 * bitmask. These values determine the maximum SDTR speed negotiated
7018 * with a device.
7019 *
7020 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7021 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7022 * without determining here whether the device supports SDTR.
7023 *
7024 * 4-bit speed SDTR speed name
7025 * =========== ===============
7026 * 0000b (0x0) SDTR disabled
7027 * 0001b (0x1) 5 Mhz
7028 * 0010b (0x2) 10 Mhz
7029 * 0011b (0x3) 20 Mhz (Ultra)
7030 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
7031 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
7032 * 0110b (0x6) Undefined
7033 * .
7034 * 1111b (0xF) Undefined
7035 */
7036 word = 0;
7037 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7038 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
7039 /* Set Ultra speed for TID 'tid'. */
7040 word |= (0x3 << (4 * (tid % 4)));
7041 } else {
7042 /* Set Fast speed for TID 'tid'. */
7043 word |= (0x2 << (4 * (tid % 4)));
7044 }
7045 if (tid == 3) { /* Check if done with sdtr_speed1. */
7046 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
7047 word = 0;
7048 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
7049 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
7050 word = 0;
7051 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
7052 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
7053 word = 0;
7054 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
7055 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
7056 /* End of loop. */
7057 }
7058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007060 /*
7061 * Set microcode operating variable for the disconnect per TID bitmask.
7062 */
7063 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7064 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007066 /*
7067 * Set SCSI_CFG0 Microcode Default Value.
7068 *
7069 * The microcode will set the SCSI_CFG0 register using this value
7070 * after it is started below.
7071 */
7072 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7073 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7074 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007076 /*
7077 * Determine SCSI_CFG1 Microcode Default Value.
7078 *
7079 * The microcode will set the SCSI_CFG1 register using this value
7080 * after it is started below.
7081 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007083 /* Read current SCSI_CFG1 Register value. */
7084 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007086 /*
7087 * If all three connectors are in use, return an error.
7088 */
7089 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
7090 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
7091 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
7092 return ADV_ERROR;
7093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007095 /*
7096 * If the internal narrow cable is reversed all of the SCSI_CTRL
7097 * register signals will be set. Check for and return an error if
7098 * this condition is found.
7099 */
7100 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7101 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7102 return ADV_ERROR;
7103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007105 /*
7106 * If this is a differential board and a single-ended device
7107 * is attached to one of the connectors, return an error.
7108 */
7109 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
7110 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
7111 return ADV_ERROR;
7112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007113
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007114 /*
7115 * If automatic termination control is enabled, then set the
7116 * termination value based on a table listed in a_condor.h.
7117 *
7118 * If manual termination was specified with an EEPROM setting
7119 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
7120 * is ready to be 'ored' into SCSI_CFG1.
7121 */
7122 if (asc_dvc->cfg->termination == 0) {
7123 /*
7124 * The software always controls termination by setting TERM_CTL_SEL.
7125 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
7126 */
7127 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007129 switch (scsi_cfg1 & CABLE_DETECT) {
7130 /* TERM_CTL_H: on, TERM_CTL_L: on */
7131 case 0x3:
7132 case 0x7:
7133 case 0xB:
7134 case 0xD:
7135 case 0xE:
7136 case 0xF:
7137 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
7138 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007139
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007140 /* TERM_CTL_H: on, TERM_CTL_L: off */
7141 case 0x1:
7142 case 0x5:
7143 case 0x9:
7144 case 0xA:
7145 case 0xC:
7146 asc_dvc->cfg->termination |= TERM_CTL_H;
7147 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007149 /* TERM_CTL_H: off, TERM_CTL_L: off */
7150 case 0x2:
7151 case 0x6:
7152 break;
7153 }
7154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007155
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007156 /*
7157 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
7158 */
7159 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007161 /*
7162 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
7163 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
7164 * referenced, because the hardware internally inverts
7165 * the Termination High and Low bits if TERM_POL is set.
7166 */
7167 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007168
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007169 /*
7170 * Set SCSI_CFG1 Microcode Default Value
7171 *
7172 * Set filter value and possibly modified termination control
7173 * bits in the Microcode SCSI_CFG1 Register Value.
7174 *
7175 * The microcode will set the SCSI_CFG1 register using this value
7176 * after it is started below.
7177 */
7178 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
7179 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007180
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007181 /*
7182 * Set MEM_CFG Microcode Default Value
7183 *
7184 * The microcode will set the MEM_CFG register using this value
7185 * after it is started below.
7186 *
7187 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7188 * are defined.
7189 *
7190 * ASC-3550 has 8KB internal memory.
7191 */
7192 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7193 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007194
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007195 /*
7196 * Set SEL_MASK Microcode Default Value
7197 *
7198 * The microcode will set the SEL_MASK register using this value
7199 * after it is started below.
7200 */
7201 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7202 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007203
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007204 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007205
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007206 /*
7207 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7208 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007210 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7211 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7212 return ADV_ERROR;
7213 }
7214 asc_dvc->carr_freelist = (ADV_CARR_T *)
7215 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007216
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007217 /*
7218 * The first command issued will be placed in the stopper carrier.
7219 */
7220 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007221
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007222 /*
7223 * Set RISC ICQ physical address start value.
7224 */
7225 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007226
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007227 /*
7228 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7229 */
7230 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7231 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7232 return ADV_ERROR;
7233 }
7234 asc_dvc->carr_freelist = (ADV_CARR_T *)
7235 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007237 /*
7238 * The first command completed by the RISC will be placed in
7239 * the stopper.
7240 *
7241 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7242 * completed the RISC will set the ASC_RQ_STOPPER bit.
7243 */
7244 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007246 /*
7247 * Set RISC IRQ physical address start value.
7248 */
7249 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7250 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007251
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007252 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7253 (ADV_INTR_ENABLE_HOST_INTR |
7254 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007256 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7257 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007259 /* finally, finally, gentlemen, start your engine */
7260 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007262 /*
7263 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7264 * Resets should be performed. The RISC has to be running
7265 * to issue a SCSI Bus Reset.
7266 */
7267 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7268 /*
7269 * If the BIOS Signature is present in memory, restore the
7270 * BIOS Handshake Configuration Table and do not perform
7271 * a SCSI Bus Reset.
7272 */
7273 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7274 0x55AA) {
7275 /*
7276 * Restore per TID negotiated values.
7277 */
7278 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7279 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7280 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7281 tagqng_able);
7282 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7283 AdvWriteByteLram(iop_base,
7284 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7285 max_cmd[tid]);
7286 }
7287 } else {
7288 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7289 warn_code = ASC_WARN_BUSRESET_ERROR;
7290 }
7291 }
7292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007294 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007295}
7296
7297/*
7298 * Initialize the ASC-38C0800.
7299 *
7300 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
7301 *
7302 * For a non-fatal error return a warning code. If there are no warnings
7303 * then 0 is returned.
7304 *
7305 * Needed after initialization for error recovery.
7306 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007307static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007308{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007309 AdvPortAddr iop_base;
7310 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007311 int begin_addr;
7312 int end_addr;
7313 ushort code_sum;
7314 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007315 int i;
7316 ushort scsi_cfg1;
7317 uchar byte;
7318 uchar tid;
7319 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7320 ushort wdtr_able, sdtr_able, tagqng_able;
7321 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007322
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007323 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007324 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007325 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007327 /*
7328 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
7329 */
7330 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
7331 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7332 return ADV_ERROR;
7333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007334
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007335 warn_code = 0;
7336 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007337
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007338 /*
7339 * Save the RISC memory BIOS region before writing the microcode.
7340 * The BIOS may already be loaded and using its RISC LRAM region
7341 * so its region must be saved and restored.
7342 *
7343 * Note: This code makes the assumption, which is currently true,
7344 * that a chip reset does not clear RISC LRAM.
7345 */
7346 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7347 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7348 bios_mem[i]);
7349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007351 /*
7352 * Save current per TID negotiated values.
7353 */
7354 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7355 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7356 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7357 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7358 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7359 max_cmd[tid]);
7360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007361
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007362 /*
7363 * RAM BIST (RAM Built-In Self Test)
7364 *
7365 * Address : I/O base + offset 0x38h register (byte).
7366 * Function: Bit 7-6(RW) : RAM mode
7367 * Normal Mode : 0x00
7368 * Pre-test Mode : 0x40
7369 * RAM Test Mode : 0x80
7370 * Bit 5 : unused
7371 * Bit 4(RO) : Done bit
7372 * Bit 3-0(RO) : Status
7373 * Host Error : 0x08
7374 * Int_RAM Error : 0x04
7375 * RISC Error : 0x02
7376 * SCSI Error : 0x01
7377 * No Error : 0x00
7378 *
7379 * Note: RAM BIST code should be put right here, before loading the
7380 * microcode and after saving the RISC memory BIOS region.
7381 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007382
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007383 /*
7384 * LRAM Pre-test
7385 *
7386 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7387 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7388 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7389 * to NORMAL_MODE, return an error too.
7390 */
7391 for (i = 0; i < 2; i++) {
7392 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007393 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007394 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7395 if ((byte & RAM_TEST_DONE) == 0
7396 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007397 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007398 return ADV_ERROR;
7399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007400
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007401 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007402 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007403 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7404 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007405 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007406 return ADV_ERROR;
7407 }
7408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007409
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007410 /*
7411 * LRAM Test - It takes about 1.5 ms to run through the test.
7412 *
7413 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7414 * If Done bit not set or Status not 0, save register byte, set the
7415 * err_code, and return an error.
7416 */
7417 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007418 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007419
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007420 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7421 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7422 /* Get here if Done bit not set or Status not 0. */
7423 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007424 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007425 return ADV_ERROR;
7426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007428 /* We need to reset back to normal mode after LRAM test passes. */
7429 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007430
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007431 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
7432 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
7433 _adv_asc38C0800_chksum);
7434 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007435 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007436
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007437 /*
7438 * Restore the RISC memory BIOS region.
7439 */
7440 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7441 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7442 bios_mem[i]);
7443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007445 /*
7446 * Calculate and write the microcode code checksum to the microcode
7447 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7448 */
7449 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7450 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7451 code_sum = 0;
7452 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7453 for (word = begin_addr; word < end_addr; word += 2) {
7454 code_sum += AdvReadWordAutoIncLram(iop_base);
7455 }
7456 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007457
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007458 /*
7459 * Read microcode version and date.
7460 */
7461 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7462 asc_dvc->cfg->mcode_date);
7463 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7464 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007466 /*
7467 * Set the chip type to indicate the ASC38C0800.
7468 */
7469 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007470
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007471 /*
7472 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7473 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7474 * cable detection and then we are able to read C_DET[3:0].
7475 *
7476 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7477 * Microcode Default Value' section below.
7478 */
7479 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7480 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7481 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007482
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007483 /*
7484 * If the PCI Configuration Command Register "Parity Error Response
7485 * Control" Bit was clear (0), then set the microcode variable
7486 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7487 * to ignore DMA parity errors.
7488 */
7489 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7490 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7491 word |= CONTROL_FLAG_IGNORE_PERR;
7492 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007494
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007495 /*
7496 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
7497 * bits for the default FIFO threshold.
7498 *
7499 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
7500 *
7501 * For DMA Errata #4 set the BC_THRESH_ENB bit.
7502 */
7503 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7504 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
7505 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007507 /*
7508 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007509 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007510 * device reports it is capable of in Inquiry byte 7.
7511 *
7512 * If SCSI Bus Resets have been disabled, then directly set
7513 * SDTR and WDTR from the EEPROM configuration. This will allow
7514 * the BIOS and warm boot to work without a SCSI bus hang on
7515 * the Inquiry caused by host and target mismatched DTR values.
7516 * Without the SCSI Bus Reset, before an Inquiry a device can't
7517 * be assumed to be in Asynchronous, Narrow mode.
7518 */
7519 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7520 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7521 asc_dvc->wdtr_able);
7522 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7523 asc_dvc->sdtr_able);
7524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007525
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007526 /*
7527 * Set microcode operating variables for DISC and SDTR_SPEED1,
7528 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7529 * configuration values.
7530 *
7531 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7532 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7533 * without determining here whether the device supports SDTR.
7534 */
7535 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7536 asc_dvc->cfg->disc_enable);
7537 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7538 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7539 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7540 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007542 /*
7543 * Set SCSI_CFG0 Microcode Default Value.
7544 *
7545 * The microcode will set the SCSI_CFG0 register using this value
7546 * after it is started below.
7547 */
7548 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7549 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7550 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007552 /*
7553 * Determine SCSI_CFG1 Microcode Default Value.
7554 *
7555 * The microcode will set the SCSI_CFG1 register using this value
7556 * after it is started below.
7557 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007558
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007559 /* Read current SCSI_CFG1 Register value. */
7560 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007561
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007562 /*
7563 * If the internal narrow cable is reversed all of the SCSI_CTRL
7564 * register signals will be set. Check for and return an error if
7565 * this condition is found.
7566 */
7567 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7568 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7569 return ADV_ERROR;
7570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007571
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007572 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007573 * All kind of combinations of devices attached to one of four
7574 * connectors are acceptable except HVD device attached. For example,
7575 * LVD device can be attached to SE connector while SE device attached
7576 * to LVD connector. If LVD device attached to SE connector, it only
7577 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007578 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007579 * If an HVD device is attached to one of LVD connectors, return an
7580 * error. However, there is no way to detect HVD device attached to
7581 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007582 */
7583 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007584 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007585 return ADV_ERROR;
7586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007588 /*
7589 * If either SE or LVD automatic termination control is enabled, then
7590 * set the termination value based on a table listed in a_condor.h.
7591 *
7592 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007593 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
7594 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007595 */
7596 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
7597 /* SE automatic termination control is enabled. */
7598 switch (scsi_cfg1 & C_DET_SE) {
7599 /* TERM_SE_HI: on, TERM_SE_LO: on */
7600 case 0x1:
7601 case 0x2:
7602 case 0x3:
7603 asc_dvc->cfg->termination |= TERM_SE;
7604 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007605
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007606 /* TERM_SE_HI: on, TERM_SE_LO: off */
7607 case 0x0:
7608 asc_dvc->cfg->termination |= TERM_SE_HI;
7609 break;
7610 }
7611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007612
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007613 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
7614 /* LVD automatic termination control is enabled. */
7615 switch (scsi_cfg1 & C_DET_LVD) {
7616 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
7617 case 0x4:
7618 case 0x8:
7619 case 0xC:
7620 asc_dvc->cfg->termination |= TERM_LVD;
7621 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007622
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007623 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
7624 case 0x0:
7625 break;
7626 }
7627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007629 /*
7630 * Clear any set TERM_SE and TERM_LVD bits.
7631 */
7632 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007633
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007634 /*
7635 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
7636 */
7637 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007638
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007639 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007640 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
7641 * bits and set possibly modified termination control bits in the
7642 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007643 */
7644 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007645
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007646 /*
7647 * Set SCSI_CFG1 Microcode Default Value
7648 *
7649 * Set possibly modified termination control and reset DIS_TERM_DRV
7650 * bits in the Microcode SCSI_CFG1 Register Value.
7651 *
7652 * The microcode will set the SCSI_CFG1 register using this value
7653 * after it is started below.
7654 */
7655 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007657 /*
7658 * Set MEM_CFG Microcode Default Value
7659 *
7660 * The microcode will set the MEM_CFG register using this value
7661 * after it is started below.
7662 *
7663 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7664 * are defined.
7665 *
7666 * ASC-38C0800 has 16KB internal memory.
7667 */
7668 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7669 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007671 /*
7672 * Set SEL_MASK Microcode Default Value
7673 *
7674 * The microcode will set the SEL_MASK register using this value
7675 * after it is started below.
7676 */
7677 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7678 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007679
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007680 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007682 /*
7683 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7684 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007685
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007686 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7687 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7688 return ADV_ERROR;
7689 }
7690 asc_dvc->carr_freelist = (ADV_CARR_T *)
7691 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007692
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007693 /*
7694 * The first command issued will be placed in the stopper carrier.
7695 */
7696 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007697
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007698 /*
7699 * Set RISC ICQ physical address start value.
7700 * carr_pa is LE, must be native before write
7701 */
7702 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007703
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007704 /*
7705 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7706 */
7707 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7708 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7709 return ADV_ERROR;
7710 }
7711 asc_dvc->carr_freelist = (ADV_CARR_T *)
7712 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007713
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007714 /*
7715 * The first command completed by the RISC will be placed in
7716 * the stopper.
7717 *
7718 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7719 * completed the RISC will set the ASC_RQ_STOPPER bit.
7720 */
7721 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007722
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007723 /*
7724 * Set RISC IRQ physical address start value.
7725 *
7726 * carr_pa is LE, must be native before write *
7727 */
7728 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7729 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007731 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7732 (ADV_INTR_ENABLE_HOST_INTR |
7733 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007735 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7736 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007738 /* finally, finally, gentlemen, start your engine */
7739 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007741 /*
7742 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7743 * Resets should be performed. The RISC has to be running
7744 * to issue a SCSI Bus Reset.
7745 */
7746 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7747 /*
7748 * If the BIOS Signature is present in memory, restore the
7749 * BIOS Handshake Configuration Table and do not perform
7750 * a SCSI Bus Reset.
7751 */
7752 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7753 0x55AA) {
7754 /*
7755 * Restore per TID negotiated values.
7756 */
7757 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7758 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7759 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7760 tagqng_able);
7761 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7762 AdvWriteByteLram(iop_base,
7763 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7764 max_cmd[tid]);
7765 }
7766 } else {
7767 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7768 warn_code = ASC_WARN_BUSRESET_ERROR;
7769 }
7770 }
7771 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007772
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007773 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007774}
7775
7776/*
7777 * Initialize the ASC-38C1600.
7778 *
7779 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
7780 *
7781 * For a non-fatal error return a warning code. If there are no warnings
7782 * then 0 is returned.
7783 *
7784 * Needed after initialization for error recovery.
7785 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007786static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007787{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007788 AdvPortAddr iop_base;
7789 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007790 int begin_addr;
7791 int end_addr;
7792 ushort code_sum;
7793 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007794 int i;
7795 ushort scsi_cfg1;
7796 uchar byte;
7797 uchar tid;
7798 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7799 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
7800 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007802 /* If there is already an error, don't continue. */
7803 if (asc_dvc->err_code != 0) {
7804 return ADV_ERROR;
7805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007806
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007807 /*
7808 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
7809 */
7810 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
7811 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7812 return ADV_ERROR;
7813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007815 warn_code = 0;
7816 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007817
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007818 /*
7819 * Save the RISC memory BIOS region before writing the microcode.
7820 * The BIOS may already be loaded and using its RISC LRAM region
7821 * so its region must be saved and restored.
7822 *
7823 * Note: This code makes the assumption, which is currently true,
7824 * that a chip reset does not clear RISC LRAM.
7825 */
7826 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7827 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7828 bios_mem[i]);
7829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007830
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007831 /*
7832 * Save current per TID negotiated values.
7833 */
7834 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7835 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7836 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
7837 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7838 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7839 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7840 max_cmd[tid]);
7841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007842
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007843 /*
7844 * RAM BIST (Built-In Self Test)
7845 *
7846 * Address : I/O base + offset 0x38h register (byte).
7847 * Function: Bit 7-6(RW) : RAM mode
7848 * Normal Mode : 0x00
7849 * Pre-test Mode : 0x40
7850 * RAM Test Mode : 0x80
7851 * Bit 5 : unused
7852 * Bit 4(RO) : Done bit
7853 * Bit 3-0(RO) : Status
7854 * Host Error : 0x08
7855 * Int_RAM Error : 0x04
7856 * RISC Error : 0x02
7857 * SCSI Error : 0x01
7858 * No Error : 0x00
7859 *
7860 * Note: RAM BIST code should be put right here, before loading the
7861 * microcode and after saving the RISC memory BIOS region.
7862 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007863
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007864 /*
7865 * LRAM Pre-test
7866 *
7867 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7868 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7869 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7870 * to NORMAL_MODE, return an error too.
7871 */
7872 for (i = 0; i < 2; i++) {
7873 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007874 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007875 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7876 if ((byte & RAM_TEST_DONE) == 0
7877 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007878 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007879 return ADV_ERROR;
7880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007882 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007883 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007884 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7885 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007886 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007887 return ADV_ERROR;
7888 }
7889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007890
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007891 /*
7892 * LRAM Test - It takes about 1.5 ms to run through the test.
7893 *
7894 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7895 * If Done bit not set or Status not 0, save register byte, set the
7896 * err_code, and return an error.
7897 */
7898 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007899 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007900
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007901 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7902 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7903 /* Get here if Done bit not set or Status not 0. */
7904 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007905 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007906 return ADV_ERROR;
7907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007908
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007909 /* We need to reset back to normal mode after LRAM test passes. */
7910 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007911
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007912 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
7913 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
7914 _adv_asc38C1600_chksum);
7915 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007916 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007917
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007918 /*
7919 * Restore the RISC memory BIOS region.
7920 */
7921 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7922 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7923 bios_mem[i]);
7924 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007926 /*
7927 * Calculate and write the microcode code checksum to the microcode
7928 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7929 */
7930 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7931 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7932 code_sum = 0;
7933 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7934 for (word = begin_addr; word < end_addr; word += 2) {
7935 code_sum += AdvReadWordAutoIncLram(iop_base);
7936 }
7937 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007938
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007939 /*
7940 * Read microcode version and date.
7941 */
7942 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7943 asc_dvc->cfg->mcode_date);
7944 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7945 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007946
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007947 /*
7948 * Set the chip type to indicate the ASC38C1600.
7949 */
7950 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007951
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007952 /*
7953 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7954 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7955 * cable detection and then we are able to read C_DET[3:0].
7956 *
7957 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7958 * Microcode Default Value' section below.
7959 */
7960 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7961 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7962 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007964 /*
7965 * If the PCI Configuration Command Register "Parity Error Response
7966 * Control" Bit was clear (0), then set the microcode variable
7967 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7968 * to ignore DMA parity errors.
7969 */
7970 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7971 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7972 word |= CONTROL_FLAG_IGNORE_PERR;
7973 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007976 /*
7977 * If the BIOS control flag AIPP (Asynchronous Information
7978 * Phase Protection) disable bit is not set, then set the firmware
7979 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
7980 * AIPP checking and encoding.
7981 */
7982 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
7983 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7984 word |= CONTROL_FLAG_ENABLE_AIPP;
7985 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007987
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007988 /*
7989 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
7990 * and START_CTL_TH [3:2].
7991 */
7992 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7993 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007995 /*
7996 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007997 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007998 * device reports it is capable of in Inquiry byte 7.
7999 *
8000 * If SCSI Bus Resets have been disabled, then directly set
8001 * SDTR and WDTR from the EEPROM configuration. This will allow
8002 * the BIOS and warm boot to work without a SCSI bus hang on
8003 * the Inquiry caused by host and target mismatched DTR values.
8004 * Without the SCSI Bus Reset, before an Inquiry a device can't
8005 * be assumed to be in Asynchronous, Narrow mode.
8006 */
8007 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
8008 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
8009 asc_dvc->wdtr_able);
8010 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
8011 asc_dvc->sdtr_able);
8012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008013
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008014 /*
8015 * Set microcode operating variables for DISC and SDTR_SPEED1,
8016 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
8017 * configuration values.
8018 *
8019 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
8020 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
8021 * without determining here whether the device supports SDTR.
8022 */
8023 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
8024 asc_dvc->cfg->disc_enable);
8025 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
8026 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
8027 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
8028 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008030 /*
8031 * Set SCSI_CFG0 Microcode Default Value.
8032 *
8033 * The microcode will set the SCSI_CFG0 register using this value
8034 * after it is started below.
8035 */
8036 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
8037 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
8038 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008039
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008040 /*
8041 * Calculate SCSI_CFG1 Microcode Default Value.
8042 *
8043 * The microcode will set the SCSI_CFG1 register using this value
8044 * after it is started below.
8045 *
8046 * Each ASC-38C1600 function has only two cable detect bits.
8047 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
8048 */
8049 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008050
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008051 /*
8052 * If the cable is reversed all of the SCSI_CTRL register signals
8053 * will be set. Check for and return an error if this condition is
8054 * found.
8055 */
8056 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
8057 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
8058 return ADV_ERROR;
8059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008061 /*
8062 * Each ASC-38C1600 function has two connectors. Only an HVD device
8063 * can not be connected to either connector. An LVD device or SE device
8064 * may be connected to either connecor. If an SE device is connected,
8065 * then at most Ultra speed (20 Mhz) can be used on both connectors.
8066 *
8067 * If an HVD device is attached, return an error.
8068 */
8069 if (scsi_cfg1 & HVD) {
8070 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
8071 return ADV_ERROR;
8072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008074 /*
8075 * Each function in the ASC-38C1600 uses only the SE cable detect and
8076 * termination because there are two connectors for each function. Each
8077 * function may use either LVD or SE mode. Corresponding the SE automatic
8078 * termination control EEPROM bits are used for each function. Each
8079 * function has its own EEPROM. If SE automatic control is enabled for
8080 * the function, then set the termination value based on a table listed
8081 * in a_condor.h.
8082 *
8083 * If manual termination is specified in the EEPROM for the function,
8084 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
8085 * ready to be 'ored' into SCSI_CFG1.
8086 */
8087 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06008088 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008089 /* SE automatic termination control is enabled. */
8090 switch (scsi_cfg1 & C_DET_SE) {
8091 /* TERM_SE_HI: on, TERM_SE_LO: on */
8092 case 0x1:
8093 case 0x2:
8094 case 0x3:
8095 asc_dvc->cfg->termination |= TERM_SE;
8096 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008097
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008098 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06008099 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008100 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
8101 } else {
8102 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
8103 asc_dvc->cfg->termination |= TERM_SE_HI;
8104 }
8105 break;
8106 }
8107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008109 /*
8110 * Clear any set TERM_SE bits.
8111 */
8112 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008113
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008114 /*
8115 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
8116 */
8117 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008118
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008119 /*
8120 * Clear Big Endian and Terminator Polarity bits and set possibly
8121 * modified termination control bits in the Microcode SCSI_CFG1
8122 * Register Value.
8123 *
8124 * Big Endian bit is not used even on big endian machines.
8125 */
8126 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008127
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008128 /*
8129 * Set SCSI_CFG1 Microcode Default Value
8130 *
8131 * Set possibly modified termination control bits in the Microcode
8132 * SCSI_CFG1 Register Value.
8133 *
8134 * The microcode will set the SCSI_CFG1 register using this value
8135 * after it is started below.
8136 */
8137 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008138
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008139 /*
8140 * Set MEM_CFG Microcode Default Value
8141 *
8142 * The microcode will set the MEM_CFG register using this value
8143 * after it is started below.
8144 *
8145 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
8146 * are defined.
8147 *
8148 * ASC-38C1600 has 32KB internal memory.
8149 *
8150 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
8151 * out a special 16K Adv Library and Microcode version. After the issue
8152 * resolved, we should turn back to the 32K support. Both a_condor.h and
8153 * mcode.sas files also need to be updated.
8154 *
8155 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8156 * BIOS_EN | RAM_SZ_32KB);
8157 */
8158 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8159 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008161 /*
8162 * Set SEL_MASK Microcode Default Value
8163 *
8164 * The microcode will set the SEL_MASK register using this value
8165 * after it is started below.
8166 */
8167 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
8168 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008169
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06008170 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008171
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008172 /*
8173 * Set-up the Host->RISC Initiator Command Queue (ICQ).
8174 */
8175 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
8176 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8177 return ADV_ERROR;
8178 }
8179 asc_dvc->carr_freelist = (ADV_CARR_T *)
8180 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008181
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008182 /*
8183 * The first command issued will be placed in the stopper carrier.
8184 */
8185 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008186
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008187 /*
8188 * Set RISC ICQ physical address start value. Initialize the
8189 * COMMA register to the same value otherwise the RISC will
8190 * prematurely detect a command is available.
8191 */
8192 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
8193 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
8194 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008195
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008196 /*
8197 * Set-up the RISC->Host Initiator Response Queue (IRQ).
8198 */
8199 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
8200 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8201 return ADV_ERROR;
8202 }
8203 asc_dvc->carr_freelist = (ADV_CARR_T *)
8204 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008205
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008206 /*
8207 * The first command completed by the RISC will be placed in
8208 * the stopper.
8209 *
8210 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
8211 * completed the RISC will set the ASC_RQ_STOPPER bit.
8212 */
8213 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008215 /*
8216 * Set RISC IRQ physical address start value.
8217 */
8218 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
8219 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008221 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
8222 (ADV_INTR_ENABLE_HOST_INTR |
8223 ADV_INTR_ENABLE_GLOBAL_INTR));
8224 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
8225 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008226
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008227 /* finally, finally, gentlemen, start your engine */
8228 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008230 /*
8231 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
8232 * Resets should be performed. The RISC has to be running
8233 * to issue a SCSI Bus Reset.
8234 */
8235 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
8236 /*
8237 * If the BIOS Signature is present in memory, restore the
8238 * per TID microcode operating variables.
8239 */
8240 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
8241 0x55AA) {
8242 /*
8243 * Restore per TID negotiated values.
8244 */
8245 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8246 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8247 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8248 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
8249 tagqng_able);
8250 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
8251 AdvWriteByteLram(iop_base,
8252 ASC_MC_NUMBER_OF_MAX_CMD + tid,
8253 max_cmd[tid]);
8254 }
8255 } else {
8256 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
8257 warn_code = ASC_WARN_BUSRESET_ERROR;
8258 }
8259 }
8260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008262 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008263}
8264
8265/*
Matthew Wilcox51219352007-10-02 21:55:22 -04008266 * Reset chip and SCSI Bus.
8267 *
8268 * Return Value:
8269 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
8270 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
8271 */
8272static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
8273{
8274 int status;
8275 ushort wdtr_able, sdtr_able, tagqng_able;
8276 ushort ppr_able = 0;
8277 uchar tid, max_cmd[ADV_MAX_TID + 1];
8278 AdvPortAddr iop_base;
8279 ushort bios_sig;
8280
8281 iop_base = asc_dvc->iop_base;
8282
8283 /*
8284 * Save current per TID negotiated values.
8285 */
8286 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8287 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8288 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8289 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8290 }
8291 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8292 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8293 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8294 max_cmd[tid]);
8295 }
8296
8297 /*
8298 * Force the AdvInitAsc3550/38C0800Driver() function to
8299 * perform a SCSI Bus Reset by clearing the BIOS signature word.
8300 * The initialization functions assumes a SCSI Bus Reset is not
8301 * needed if the BIOS signature word is present.
8302 */
8303 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8304 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
8305
8306 /*
8307 * Stop chip and reset it.
8308 */
8309 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
8310 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
8311 mdelay(100);
8312 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
8313 ADV_CTRL_REG_CMD_WR_IO_REG);
8314
8315 /*
8316 * Reset Adv Library error code, if any, and try
8317 * re-initializing the chip.
8318 */
8319 asc_dvc->err_code = 0;
8320 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8321 status = AdvInitAsc38C1600Driver(asc_dvc);
8322 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8323 status = AdvInitAsc38C0800Driver(asc_dvc);
8324 } else {
8325 status = AdvInitAsc3550Driver(asc_dvc);
8326 }
8327
8328 /* Translate initialization return value to status value. */
8329 if (status == 0) {
8330 status = ADV_TRUE;
8331 } else {
8332 status = ADV_FALSE;
8333 }
8334
8335 /*
8336 * Restore the BIOS signature word.
8337 */
8338 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8339
8340 /*
8341 * Restore per TID negotiated values.
8342 */
8343 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8344 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8345 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8346 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8347 }
8348 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8349 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8350 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8351 max_cmd[tid]);
8352 }
8353
8354 return status;
8355}
8356
8357/*
8358 * adv_async_callback() - Adv Library asynchronous event callback function.
8359 */
8360static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
8361{
8362 switch (code) {
8363 case ADV_ASYNC_SCSI_BUS_RESET_DET:
8364 /*
8365 * The firmware detected a SCSI Bus reset.
8366 */
8367 ASC_DBG(0,
8368 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
8369 break;
8370
8371 case ADV_ASYNC_RDMA_FAILURE:
8372 /*
8373 * Handle RDMA failure by resetting the SCSI Bus and
8374 * possibly the chip if it is unresponsive. Log the error
8375 * with a unique code.
8376 */
8377 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
8378 AdvResetChipAndSB(adv_dvc_varp);
8379 break;
8380
8381 case ADV_HOST_SCSI_BUS_RESET:
8382 /*
8383 * Host generated SCSI bus reset occurred.
8384 */
8385 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
8386 break;
8387
8388 default:
8389 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
8390 break;
8391 }
8392}
8393
8394/*
8395 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
8396 *
8397 * Callback function for the Wide SCSI Adv Library.
8398 */
8399static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
8400{
8401 asc_board_t *boardp;
8402 adv_req_t *reqp;
8403 adv_sgblk_t *sgblkp;
8404 struct scsi_cmnd *scp;
8405 struct Scsi_Host *shost;
8406 ADV_DCNT resid_cnt;
8407
8408 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
8409 (ulong)adv_dvc_varp, (ulong)scsiqp);
8410 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
8411
8412 /*
8413 * Get the adv_req_t structure for the command that has been
8414 * completed. The adv_req_t structure actually contains the
8415 * completed ADV_SCSI_REQ_Q structure.
8416 */
8417 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
8418 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
8419 if (reqp == NULL) {
8420 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
8421 return;
8422 }
8423
8424 /*
8425 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
8426 * command that has been completed.
8427 *
8428 * Note: The adv_req_t request structure and adv_sgblk_t structure,
8429 * if any, are dropped, because a board structure pointer can not be
8430 * determined.
8431 */
8432 scp = reqp->cmndp;
8433 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
8434 if (scp == NULL) {
8435 ASC_PRINT
8436 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
8437 return;
8438 }
8439 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
8440
8441 shost = scp->device->host;
8442 ASC_STATS(shost, callback);
8443 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
8444
8445 boardp = ASC_BOARDP(shost);
8446 BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
8447
8448 /*
8449 * 'done_status' contains the command's ending status.
8450 */
8451 switch (scsiqp->done_status) {
8452 case QD_NO_ERROR:
8453 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
8454 scp->result = 0;
8455
8456 /*
8457 * Check for an underrun condition.
8458 *
8459 * If there was no error and an underrun condition, then
8460 * then return the number of underrun bytes.
8461 */
8462 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
8463 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
8464 resid_cnt <= scp->request_bufflen) {
8465 ASC_DBG1(1,
8466 "adv_isr_callback: underrun condition %lu bytes\n",
8467 (ulong)resid_cnt);
8468 scp->resid = resid_cnt;
8469 }
8470 break;
8471
8472 case QD_WITH_ERROR:
8473 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
8474 switch (scsiqp->host_status) {
8475 case QHSTA_NO_ERROR:
8476 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
8477 ASC_DBG(2,
8478 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
8479 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
8480 sizeof(scp->sense_buffer));
8481 /*
8482 * Note: The 'status_byte()' macro used by
8483 * target drivers defined in scsi.h shifts the
8484 * status byte returned by host drivers right
8485 * by 1 bit. This is why target drivers also
8486 * use right shifted status byte definitions.
8487 * For instance target drivers use
8488 * CHECK_CONDITION, defined to 0x1, instead of
8489 * the SCSI defined check condition value of
8490 * 0x2. Host drivers are supposed to return
8491 * the status byte as it is defined by SCSI.
8492 */
8493 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
8494 STATUS_BYTE(scsiqp->scsi_status);
8495 } else {
8496 scp->result = STATUS_BYTE(scsiqp->scsi_status);
8497 }
8498 break;
8499
8500 default:
8501 /* Some other QHSTA error occurred. */
8502 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
8503 scsiqp->host_status);
8504 scp->result = HOST_BYTE(DID_BAD_TARGET);
8505 break;
8506 }
8507 break;
8508
8509 case QD_ABORTED_BY_HOST:
8510 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
8511 scp->result =
8512 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
8513 break;
8514
8515 default:
8516 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
8517 scsiqp->done_status);
8518 scp->result =
8519 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
8520 break;
8521 }
8522
8523 /*
8524 * If the 'init_tidmask' bit isn't already set for the target and the
8525 * current request finished normally, then set the bit for the target
8526 * to indicate that a device is present.
8527 */
8528 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
8529 scsiqp->done_status == QD_NO_ERROR &&
8530 scsiqp->host_status == QHSTA_NO_ERROR) {
8531 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
8532 }
8533
8534 asc_scsi_done(scp);
8535
8536 /*
8537 * Free all 'adv_sgblk_t' structures allocated for the request.
8538 */
8539 while ((sgblkp = reqp->sgblkp) != NULL) {
8540 /* Remove 'sgblkp' from the request list. */
8541 reqp->sgblkp = sgblkp->next_sgblkp;
8542
8543 /* Add 'sgblkp' to the board free list. */
8544 sgblkp->next_sgblkp = boardp->adv_sgblkp;
8545 boardp->adv_sgblkp = sgblkp;
8546 }
8547
8548 /*
8549 * Free the adv_req_t structure used with the command by adding
8550 * it back to the board free list.
8551 */
8552 reqp->next_reqp = boardp->adv_reqp;
8553 boardp->adv_reqp = reqp;
8554
8555 ASC_DBG(1, "adv_isr_callback: done\n");
8556
8557 return;
8558}
8559
8560/*
8561 * Adv Library Interrupt Service Routine
8562 *
8563 * This function is called by a driver's interrupt service routine.
8564 * The function disables and re-enables interrupts.
8565 *
8566 * When a microcode idle command is completed, the ADV_DVC_VAR
8567 * 'idle_cmd_done' field is set to ADV_TRUE.
8568 *
8569 * Note: AdvISR() can be called when interrupts are disabled or even
8570 * when there is no hardware interrupt condition present. It will
8571 * always check for completed idle commands and microcode requests.
8572 * This is an important feature that shouldn't be changed because it
8573 * allows commands to be completed from polling mode loops.
8574 *
8575 * Return:
8576 * ADV_TRUE(1) - interrupt was pending
8577 * ADV_FALSE(0) - no interrupt was pending
8578 */
8579static int AdvISR(ADV_DVC_VAR *asc_dvc)
8580{
8581 AdvPortAddr iop_base;
8582 uchar int_stat;
8583 ushort target_bit;
8584 ADV_CARR_T *free_carrp;
8585 ADV_VADDR irq_next_vpa;
8586 ADV_SCSI_REQ_Q *scsiq;
8587
8588 iop_base = asc_dvc->iop_base;
8589
8590 /* Reading the register clears the interrupt. */
8591 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
8592
8593 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
8594 ADV_INTR_STATUS_INTRC)) == 0) {
8595 return ADV_FALSE;
8596 }
8597
8598 /*
8599 * Notify the driver of an asynchronous microcode condition by
8600 * calling the adv_async_callback function. The function
8601 * is passed the microcode ASC_MC_INTRB_CODE byte value.
8602 */
8603 if (int_stat & ADV_INTR_STATUS_INTRB) {
8604 uchar intrb_code;
8605
8606 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
8607
8608 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
8609 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8610 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
8611 asc_dvc->carr_pending_cnt != 0) {
8612 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
8613 ADV_TICKLE_A);
8614 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
8615 AdvWriteByteRegister(iop_base,
8616 IOPB_TICKLE,
8617 ADV_TICKLE_NOP);
8618 }
8619 }
8620 }
8621
8622 adv_async_callback(asc_dvc, intrb_code);
8623 }
8624
8625 /*
8626 * Check if the IRQ stopper carrier contains a completed request.
8627 */
8628 while (((irq_next_vpa =
8629 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
8630 /*
8631 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
8632 * The RISC will have set 'areq_vpa' to a virtual address.
8633 *
8634 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
8635 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
8636 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
8637 * in AdvExeScsiQueue().
8638 */
8639 scsiq = (ADV_SCSI_REQ_Q *)
8640 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
8641
8642 /*
8643 * Request finished with good status and the queue was not
8644 * DMAed to host memory by the firmware. Set all status fields
8645 * to indicate good status.
8646 */
8647 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
8648 scsiq->done_status = QD_NO_ERROR;
8649 scsiq->host_status = scsiq->scsi_status = 0;
8650 scsiq->data_cnt = 0L;
8651 }
8652
8653 /*
8654 * Advance the stopper pointer to the next carrier
8655 * ignoring the lower four bits. Free the previous
8656 * stopper carrier.
8657 */
8658 free_carrp = asc_dvc->irq_sp;
8659 asc_dvc->irq_sp = (ADV_CARR_T *)
8660 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
8661
8662 free_carrp->next_vpa =
8663 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
8664 asc_dvc->carr_freelist = free_carrp;
8665 asc_dvc->carr_pending_cnt--;
8666
8667 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
8668
8669 /*
8670 * Clear request microcode control flag.
8671 */
8672 scsiq->cntl = 0;
8673
8674 /*
8675 * Notify the driver of the completed request by passing
8676 * the ADV_SCSI_REQ_Q pointer to its callback function.
8677 */
8678 scsiq->a_flag |= ADV_SCSIQ_DONE;
8679 adv_isr_callback(asc_dvc, scsiq);
8680 /*
8681 * Note: After the driver callback function is called, 'scsiq'
8682 * can no longer be referenced.
8683 *
8684 * Fall through and continue processing other completed
8685 * requests...
8686 */
8687 }
8688 return ADV_TRUE;
8689}
8690
8691static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
8692{
8693 if (asc_dvc->err_code == 0) {
8694 asc_dvc->err_code = err_code;
8695 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8696 err_code);
8697 }
8698 return err_code;
8699}
8700
8701static void AscAckInterrupt(PortAddr iop_base)
8702{
8703 uchar host_flag;
8704 uchar risc_flag;
8705 ushort loop;
8706
8707 loop = 0;
8708 do {
8709 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8710 if (loop++ > 0x7FFF) {
8711 break;
8712 }
8713 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8714 host_flag =
8715 AscReadLramByte(iop_base,
8716 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8717 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8718 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8719 AscSetChipStatus(iop_base, CIW_INT_ACK);
8720 loop = 0;
8721 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8722 AscSetChipStatus(iop_base, CIW_INT_ACK);
8723 if (loop++ > 3) {
8724 break;
8725 }
8726 }
8727 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8728 return;
8729}
8730
8731static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
8732{
8733 uchar *period_table;
8734 int max_index;
8735 int min_index;
8736 int i;
8737
8738 period_table = asc_dvc->sdtr_period_tbl;
8739 max_index = (int)asc_dvc->max_sdtr_index;
8740 min_index = (int)asc_dvc->host_init_sdtr_index;
8741 if ((syn_time <= period_table[max_index])) {
8742 for (i = min_index; i < (max_index - 1); i++) {
8743 if (syn_time <= period_table[i]) {
8744 return (uchar)i;
8745 }
8746 }
8747 return (uchar)max_index;
8748 } else {
8749 return (uchar)(max_index + 1);
8750 }
8751}
8752
8753static uchar
8754AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
8755{
8756 EXT_MSG sdtr_buf;
8757 uchar sdtr_period_index;
8758 PortAddr iop_base;
8759
8760 iop_base = asc_dvc->iop_base;
8761 sdtr_buf.msg_type = EXTENDED_MESSAGE;
8762 sdtr_buf.msg_len = MS_SDTR_LEN;
8763 sdtr_buf.msg_req = EXTENDED_SDTR;
8764 sdtr_buf.xfer_period = sdtr_period;
8765 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8766 sdtr_buf.req_ack_offset = sdtr_offset;
8767 sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8768 if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
8769 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8770 (uchar *)&sdtr_buf,
8771 sizeof(EXT_MSG) >> 1);
8772 return ((sdtr_period_index << 4) | sdtr_offset);
8773 } else {
8774 sdtr_buf.req_ack_offset = 0;
8775 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8776 (uchar *)&sdtr_buf,
8777 sizeof(EXT_MSG) >> 1);
8778 return 0;
8779 }
8780}
8781
8782static uchar
8783AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
8784{
8785 uchar byte;
8786 uchar sdtr_period_ix;
8787
8788 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8789 if (sdtr_period_ix > asc_dvc->max_sdtr_index) {
8790 return 0xFF;
8791 }
8792 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8793 return byte;
8794}
8795
8796static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
8797{
8798 ASC_SCSI_BIT_ID_TYPE org_id;
8799 int i;
8800 int sta = TRUE;
8801
8802 AscSetBank(iop_base, 1);
8803 org_id = AscReadChipDvcID(iop_base);
8804 for (i = 0; i <= ASC_MAX_TID; i++) {
8805 if (org_id == (0x01 << i))
8806 break;
8807 }
8808 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8809 AscWriteChipDvcID(iop_base, id);
8810 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8811 AscSetBank(iop_base, 0);
8812 AscSetChipSyn(iop_base, sdtr_data);
8813 if (AscGetChipSyn(iop_base) != sdtr_data) {
8814 sta = FALSE;
8815 }
8816 } else {
8817 sta = FALSE;
8818 }
8819 AscSetBank(iop_base, 1);
8820 AscWriteChipDvcID(iop_base, org_id);
8821 AscSetBank(iop_base, 0);
8822 return (sta);
8823}
8824
8825static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
8826{
8827 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8828 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8829}
8830
8831static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
8832{
8833 EXT_MSG ext_msg;
8834 EXT_MSG out_msg;
8835 ushort halt_q_addr;
8836 int sdtr_accept;
8837 ushort int_halt_code;
8838 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8839 ASC_SCSI_BIT_ID_TYPE target_id;
8840 PortAddr iop_base;
8841 uchar tag_code;
8842 uchar q_status;
8843 uchar halt_qp;
8844 uchar sdtr_data;
8845 uchar target_ix;
8846 uchar q_cntl, tid_no;
8847 uchar cur_dvc_qng;
8848 uchar asyn_sdtr;
8849 uchar scsi_status;
8850 asc_board_t *boardp;
8851
8852 BUG_ON(!asc_dvc->drv_ptr);
8853 boardp = asc_dvc->drv_ptr;
8854
8855 iop_base = asc_dvc->iop_base;
8856 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
8857
8858 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8859 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8860 target_ix = AscReadLramByte(iop_base,
8861 (ushort)(halt_q_addr +
8862 (ushort)ASC_SCSIQ_B_TARGET_IX));
8863 q_cntl = AscReadLramByte(iop_base,
8864 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8865 tid_no = ASC_TIX_TO_TID(target_ix);
8866 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8867 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8868 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8869 } else {
8870 asyn_sdtr = 0;
8871 }
8872 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8873 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8874 AscSetChipSDTR(iop_base, 0, tid_no);
8875 boardp->sdtr_data[tid_no] = 0;
8876 }
8877 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8878 return (0);
8879 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8880 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8881 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8882 boardp->sdtr_data[tid_no] = asyn_sdtr;
8883 }
8884 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8885 return (0);
8886 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
8887 AscMemWordCopyPtrFromLram(iop_base,
8888 ASCV_MSGIN_BEG,
8889 (uchar *)&ext_msg,
8890 sizeof(EXT_MSG) >> 1);
8891
8892 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8893 ext_msg.msg_req == EXTENDED_SDTR &&
8894 ext_msg.msg_len == MS_SDTR_LEN) {
8895 sdtr_accept = TRUE;
8896 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
8897
8898 sdtr_accept = FALSE;
8899 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8900 }
8901 if ((ext_msg.xfer_period <
8902 asc_dvc->sdtr_period_tbl[asc_dvc->
8903 host_init_sdtr_index])
8904 || (ext_msg.xfer_period >
8905 asc_dvc->sdtr_period_tbl[asc_dvc->
8906 max_sdtr_index])) {
8907 sdtr_accept = FALSE;
8908 ext_msg.xfer_period =
8909 asc_dvc->sdtr_period_tbl[asc_dvc->
8910 host_init_sdtr_index];
8911 }
8912 if (sdtr_accept) {
8913 sdtr_data =
8914 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8915 ext_msg.req_ack_offset);
8916 if ((sdtr_data == 0xFF)) {
8917
8918 q_cntl |= QC_MSG_OUT;
8919 asc_dvc->init_sdtr &= ~target_id;
8920 asc_dvc->sdtr_done &= ~target_id;
8921 AscSetChipSDTR(iop_base, asyn_sdtr,
8922 tid_no);
8923 boardp->sdtr_data[tid_no] = asyn_sdtr;
8924 }
8925 }
8926 if (ext_msg.req_ack_offset == 0) {
8927
8928 q_cntl &= ~QC_MSG_OUT;
8929 asc_dvc->init_sdtr &= ~target_id;
8930 asc_dvc->sdtr_done &= ~target_id;
8931 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8932 } else {
8933 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
8934
8935 q_cntl &= ~QC_MSG_OUT;
8936 asc_dvc->sdtr_done |= target_id;
8937 asc_dvc->init_sdtr |= target_id;
8938 asc_dvc->pci_fix_asyn_xfer &=
8939 ~target_id;
8940 sdtr_data =
8941 AscCalSDTRData(asc_dvc,
8942 ext_msg.xfer_period,
8943 ext_msg.
8944 req_ack_offset);
8945 AscSetChipSDTR(iop_base, sdtr_data,
8946 tid_no);
8947 boardp->sdtr_data[tid_no] = sdtr_data;
8948 } else {
8949
8950 q_cntl |= QC_MSG_OUT;
8951 AscMsgOutSDTR(asc_dvc,
8952 ext_msg.xfer_period,
8953 ext_msg.req_ack_offset);
8954 asc_dvc->pci_fix_asyn_xfer &=
8955 ~target_id;
8956 sdtr_data =
8957 AscCalSDTRData(asc_dvc,
8958 ext_msg.xfer_period,
8959 ext_msg.
8960 req_ack_offset);
8961 AscSetChipSDTR(iop_base, sdtr_data,
8962 tid_no);
8963 boardp->sdtr_data[tid_no] = sdtr_data;
8964 asc_dvc->sdtr_done |= target_id;
8965 asc_dvc->init_sdtr |= target_id;
8966 }
8967 }
8968
8969 AscWriteLramByte(iop_base,
8970 (ushort)(halt_q_addr +
8971 (ushort)ASC_SCSIQ_B_CNTL),
8972 q_cntl);
8973 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8974 return (0);
8975 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8976 ext_msg.msg_req == EXTENDED_WDTR &&
8977 ext_msg.msg_len == MS_WDTR_LEN) {
8978
8979 ext_msg.wdtr_width = 0;
8980 AscMemWordCopyPtrToLram(iop_base,
8981 ASCV_MSGOUT_BEG,
8982 (uchar *)&ext_msg,
8983 sizeof(EXT_MSG) >> 1);
8984 q_cntl |= QC_MSG_OUT;
8985 AscWriteLramByte(iop_base,
8986 (ushort)(halt_q_addr +
8987 (ushort)ASC_SCSIQ_B_CNTL),
8988 q_cntl);
8989 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8990 return (0);
8991 } else {
8992
8993 ext_msg.msg_type = MESSAGE_REJECT;
8994 AscMemWordCopyPtrToLram(iop_base,
8995 ASCV_MSGOUT_BEG,
8996 (uchar *)&ext_msg,
8997 sizeof(EXT_MSG) >> 1);
8998 q_cntl |= QC_MSG_OUT;
8999 AscWriteLramByte(iop_base,
9000 (ushort)(halt_q_addr +
9001 (ushort)ASC_SCSIQ_B_CNTL),
9002 q_cntl);
9003 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9004 return (0);
9005 }
9006 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
9007
9008 q_cntl |= QC_REQ_SENSE;
9009
9010 if ((asc_dvc->init_sdtr & target_id) != 0) {
9011
9012 asc_dvc->sdtr_done &= ~target_id;
9013
9014 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
9015 q_cntl |= QC_MSG_OUT;
9016 AscMsgOutSDTR(asc_dvc,
9017 asc_dvc->
9018 sdtr_period_tbl[(sdtr_data >> 4) &
9019 (uchar)(asc_dvc->
9020 max_sdtr_index -
9021 1)],
9022 (uchar)(sdtr_data & (uchar)
9023 ASC_SYN_MAX_OFFSET));
9024 }
9025
9026 AscWriteLramByte(iop_base,
9027 (ushort)(halt_q_addr +
9028 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
9029
9030 tag_code = AscReadLramByte(iop_base,
9031 (ushort)(halt_q_addr + (ushort)
9032 ASC_SCSIQ_B_TAG_CODE));
9033 tag_code &= 0xDC;
9034 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
9035 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
9036 ) {
9037
9038 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
9039 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
9040
9041 }
9042 AscWriteLramByte(iop_base,
9043 (ushort)(halt_q_addr +
9044 (ushort)ASC_SCSIQ_B_TAG_CODE),
9045 tag_code);
9046
9047 q_status = AscReadLramByte(iop_base,
9048 (ushort)(halt_q_addr + (ushort)
9049 ASC_SCSIQ_B_STATUS));
9050 q_status |= (QS_READY | QS_BUSY);
9051 AscWriteLramByte(iop_base,
9052 (ushort)(halt_q_addr +
9053 (ushort)ASC_SCSIQ_B_STATUS),
9054 q_status);
9055
9056 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
9057 scsi_busy &= ~target_id;
9058 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
9059
9060 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9061 return (0);
9062 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
9063
9064 AscMemWordCopyPtrFromLram(iop_base,
9065 ASCV_MSGOUT_BEG,
9066 (uchar *)&out_msg,
9067 sizeof(EXT_MSG) >> 1);
9068
9069 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
9070 (out_msg.msg_len == MS_SDTR_LEN) &&
9071 (out_msg.msg_req == EXTENDED_SDTR)) {
9072
9073 asc_dvc->init_sdtr &= ~target_id;
9074 asc_dvc->sdtr_done &= ~target_id;
9075 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
9076 boardp->sdtr_data[tid_no] = asyn_sdtr;
9077 }
9078 q_cntl &= ~QC_MSG_OUT;
9079 AscWriteLramByte(iop_base,
9080 (ushort)(halt_q_addr +
9081 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
9082 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9083 return (0);
9084 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
9085
9086 scsi_status = AscReadLramByte(iop_base,
9087 (ushort)((ushort)halt_q_addr +
9088 (ushort)
9089 ASC_SCSIQ_SCSI_STATUS));
9090 cur_dvc_qng =
9091 AscReadLramByte(iop_base,
9092 (ushort)((ushort)ASC_QADR_BEG +
9093 (ushort)target_ix));
9094 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
9095
9096 scsi_busy = AscReadLramByte(iop_base,
9097 (ushort)ASCV_SCSIBUSY_B);
9098 scsi_busy |= target_id;
9099 AscWriteLramByte(iop_base,
9100 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
9101 asc_dvc->queue_full_or_busy |= target_id;
9102
9103 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
9104 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
9105 cur_dvc_qng -= 1;
9106 asc_dvc->max_dvc_qng[tid_no] =
9107 cur_dvc_qng;
9108
9109 AscWriteLramByte(iop_base,
9110 (ushort)((ushort)
9111 ASCV_MAX_DVC_QNG_BEG
9112 + (ushort)
9113 tid_no),
9114 cur_dvc_qng);
9115
9116 /*
9117 * Set the device queue depth to the
9118 * number of active requests when the
9119 * QUEUE FULL condition was encountered.
9120 */
9121 boardp->queue_full |= target_id;
9122 boardp->queue_full_cnt[tid_no] =
9123 cur_dvc_qng;
9124 }
9125 }
9126 }
9127 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9128 return (0);
9129 }
9130#if CC_VERY_LONG_SG_LIST
9131 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
9132 uchar q_no;
9133 ushort q_addr;
9134 uchar sg_wk_q_no;
9135 uchar first_sg_wk_q_no;
9136 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
9137 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
9138 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
9139 ushort sg_list_dwords;
9140 ushort sg_entry_cnt;
9141 uchar next_qp;
9142 int i;
9143
9144 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
9145 if (q_no == ASC_QLINK_END)
9146 return 0;
9147
9148 q_addr = ASC_QNO_TO_QADDR(q_no);
9149
9150 /*
9151 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
9152 * structure pointer using a macro provided by the driver.
9153 * The ASC_SCSI_REQ pointer provides a pointer to the
9154 * host ASC_SG_HEAD structure.
9155 */
9156 /* Read request's SRB pointer. */
9157 scsiq = (ASC_SCSI_Q *)
9158 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
9159 (ushort)
9160 (q_addr +
9161 ASC_SCSIQ_D_SRBPTR))));
9162
9163 /*
9164 * Get request's first and working SG queue.
9165 */
9166 sg_wk_q_no = AscReadLramByte(iop_base,
9167 (ushort)(q_addr +
9168 ASC_SCSIQ_B_SG_WK_QP));
9169
9170 first_sg_wk_q_no = AscReadLramByte(iop_base,
9171 (ushort)(q_addr +
9172 ASC_SCSIQ_B_FIRST_SG_WK_QP));
9173
9174 /*
9175 * Reset request's working SG queue back to the
9176 * first SG queue.
9177 */
9178 AscWriteLramByte(iop_base,
9179 (ushort)(q_addr +
9180 (ushort)ASC_SCSIQ_B_SG_WK_QP),
9181 first_sg_wk_q_no);
9182
9183 sg_head = scsiq->sg_head;
9184
9185 /*
9186 * Set sg_entry_cnt to the number of SG elements
9187 * that will be completed on this interrupt.
9188 *
9189 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
9190 * SG elements. The data_cnt and data_addr fields which
9191 * add 1 to the SG element capacity are not used when
9192 * restarting SG handling after a halt.
9193 */
9194 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
9195 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
9196
9197 /*
9198 * Keep track of remaining number of SG elements that
9199 * will need to be handled on the next interrupt.
9200 */
9201 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
9202 } else {
9203 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
9204 scsiq->remain_sg_entry_cnt = 0;
9205 }
9206
9207 /*
9208 * Copy SG elements into the list of allocated SG queues.
9209 *
9210 * Last index completed is saved in scsiq->next_sg_index.
9211 */
9212 next_qp = first_sg_wk_q_no;
9213 q_addr = ASC_QNO_TO_QADDR(next_qp);
9214 scsi_sg_q.sg_head_qp = q_no;
9215 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9216 for (i = 0; i < sg_head->queue_cnt; i++) {
9217 scsi_sg_q.seq_no = i + 1;
9218 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9219 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9220 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9221 /*
9222 * After very first SG queue RISC FW uses next
9223 * SG queue first element then checks sg_list_cnt
9224 * against zero and then decrements, so set
9225 * sg_list_cnt 1 less than number of SG elements
9226 * in each SG queue.
9227 */
9228 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
9229 scsi_sg_q.sg_cur_list_cnt =
9230 ASC_SG_LIST_PER_Q - 1;
9231 } else {
9232 /*
9233 * This is the last SG queue in the list of
9234 * allocated SG queues. If there are more
9235 * SG elements than will fit in the allocated
9236 * queues, then set the QCSG_SG_XFER_MORE flag.
9237 */
9238 if (scsiq->remain_sg_entry_cnt != 0) {
9239 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9240 } else {
9241 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
9242 }
9243 /* equals sg_entry_cnt * 2 */
9244 sg_list_dwords = sg_entry_cnt << 1;
9245 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
9246 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
9247 sg_entry_cnt = 0;
9248 }
9249
9250 scsi_sg_q.q_no = next_qp;
9251 AscMemWordCopyPtrToLram(iop_base,
9252 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9253 (uchar *)&scsi_sg_q,
9254 sizeof(ASC_SG_LIST_Q) >> 1);
9255
9256 AscMemDWordCopyPtrToLram(iop_base,
9257 q_addr + ASC_SGQ_LIST_BEG,
9258 (uchar *)&sg_head->
9259 sg_list[scsiq->next_sg_index],
9260 sg_list_dwords);
9261
9262 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
9263
9264 /*
9265 * If the just completed SG queue contained the
9266 * last SG element, then no more SG queues need
9267 * to be written.
9268 */
9269 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
9270 break;
9271 }
9272
9273 next_qp = AscReadLramByte(iop_base,
9274 (ushort)(q_addr +
9275 ASC_SCSIQ_B_FWD));
9276 q_addr = ASC_QNO_TO_QADDR(next_qp);
9277 }
9278
9279 /*
9280 * Clear the halt condition so the RISC will be restarted
9281 * after the return.
9282 */
9283 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9284 return (0);
9285 }
9286#endif /* CC_VERY_LONG_SG_LIST */
9287 return (0);
9288}
9289
9290/*
9291 * void
9292 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9293 *
9294 * Calling/Exit State:
9295 * none
9296 *
9297 * Description:
9298 * Input an ASC_QDONE_INFO structure from the chip
9299 */
9300static void
9301DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9302{
9303 int i;
9304 ushort word;
9305
9306 AscSetChipLramAddr(iop_base, s_addr);
9307 for (i = 0; i < 2 * words; i += 2) {
9308 if (i == 10) {
9309 continue;
9310 }
9311 word = inpw(iop_base + IOP_RAM_DATA);
9312 inbuf[i] = word & 0xff;
9313 inbuf[i + 1] = (word >> 8) & 0xff;
9314 }
9315 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
9316}
9317
9318static uchar
9319_AscCopyLramScsiDoneQ(PortAddr iop_base,
9320 ushort q_addr,
9321 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
9322{
9323 ushort _val;
9324 uchar sg_queue_cnt;
9325
9326 DvcGetQinfo(iop_base,
9327 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
9328 (uchar *)scsiq,
9329 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
9330
9331 _val = AscReadLramWord(iop_base,
9332 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
9333 scsiq->q_status = (uchar)_val;
9334 scsiq->q_no = (uchar)(_val >> 8);
9335 _val = AscReadLramWord(iop_base,
9336 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
9337 scsiq->cntl = (uchar)_val;
9338 sg_queue_cnt = (uchar)(_val >> 8);
9339 _val = AscReadLramWord(iop_base,
9340 (ushort)(q_addr +
9341 (ushort)ASC_SCSIQ_B_SENSE_LEN));
9342 scsiq->sense_len = (uchar)_val;
9343 scsiq->extra_bytes = (uchar)(_val >> 8);
9344
9345 /*
9346 * Read high word of remain bytes from alternate location.
9347 */
9348 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
9349 (ushort)(q_addr +
9350 (ushort)
9351 ASC_SCSIQ_W_ALT_DC1)))
9352 << 16);
9353 /*
9354 * Read low word of remain bytes from original location.
9355 */
9356 scsiq->remain_bytes += AscReadLramWord(iop_base,
9357 (ushort)(q_addr + (ushort)
9358 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
9359
9360 scsiq->remain_bytes &= max_dma_count;
9361 return sg_queue_cnt;
9362}
9363
9364/*
9365 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
9366 *
9367 * Interrupt callback function for the Narrow SCSI Asc Library.
9368 */
9369static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9370{
9371 asc_board_t *boardp;
9372 struct scsi_cmnd *scp;
9373 struct Scsi_Host *shost;
9374
9375 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
9376 (ulong)asc_dvc_varp, (ulong)qdonep);
9377 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
9378
9379 /*
9380 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
9381 * command that has been completed.
9382 */
9383 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
9384 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
9385
9386 if (scp == NULL) {
9387 ASC_PRINT("asc_isr_callback: scp is NULL\n");
9388 return;
9389 }
9390 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
9391
9392 shost = scp->device->host;
9393 ASC_STATS(shost, callback);
9394 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
9395
9396 boardp = ASC_BOARDP(shost);
9397 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
9398
9399 /*
9400 * 'qdonep' contains the command's ending status.
9401 */
9402 switch (qdonep->d3.done_stat) {
9403 case QD_NO_ERROR:
9404 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
9405 scp->result = 0;
9406
9407 /*
9408 * Check for an underrun condition.
9409 *
9410 * If there was no error and an underrun condition, then
9411 * return the number of underrun bytes.
9412 */
9413 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
9414 qdonep->remain_bytes <= scp->request_bufflen) {
9415 ASC_DBG1(1,
9416 "asc_isr_callback: underrun condition %u bytes\n",
9417 (unsigned)qdonep->remain_bytes);
9418 scp->resid = qdonep->remain_bytes;
9419 }
9420 break;
9421
9422 case QD_WITH_ERROR:
9423 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
9424 switch (qdonep->d3.host_stat) {
9425 case QHSTA_NO_ERROR:
9426 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
9427 ASC_DBG(2,
9428 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
9429 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
9430 sizeof(scp->sense_buffer));
9431 /*
9432 * Note: The 'status_byte()' macro used by
9433 * target drivers defined in scsi.h shifts the
9434 * status byte returned by host drivers right
9435 * by 1 bit. This is why target drivers also
9436 * use right shifted status byte definitions.
9437 * For instance target drivers use
9438 * CHECK_CONDITION, defined to 0x1, instead of
9439 * the SCSI defined check condition value of
9440 * 0x2. Host drivers are supposed to return
9441 * the status byte as it is defined by SCSI.
9442 */
9443 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
9444 STATUS_BYTE(qdonep->d3.scsi_stat);
9445 } else {
9446 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
9447 }
9448 break;
9449
9450 default:
9451 /* QHSTA error occurred */
9452 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
9453 qdonep->d3.host_stat);
9454 scp->result = HOST_BYTE(DID_BAD_TARGET);
9455 break;
9456 }
9457 break;
9458
9459 case QD_ABORTED_BY_HOST:
9460 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
9461 scp->result =
9462 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
9463 scsi_msg) |
9464 STATUS_BYTE(qdonep->d3.scsi_stat);
9465 break;
9466
9467 default:
9468 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
9469 qdonep->d3.done_stat);
9470 scp->result =
9471 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
9472 scsi_msg) |
9473 STATUS_BYTE(qdonep->d3.scsi_stat);
9474 break;
9475 }
9476
9477 /*
9478 * If the 'init_tidmask' bit isn't already set for the target and the
9479 * current request finished normally, then set the bit for the target
9480 * to indicate that a device is present.
9481 */
9482 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
9483 qdonep->d3.done_stat == QD_NO_ERROR &&
9484 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
9485 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
9486 }
9487
9488 asc_scsi_done(scp);
9489
9490 return;
9491}
9492
9493static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
9494{
9495 uchar next_qp;
9496 uchar n_q_used;
9497 uchar sg_list_qp;
9498 uchar sg_queue_cnt;
9499 uchar q_cnt;
9500 uchar done_q_tail;
9501 uchar tid_no;
9502 ASC_SCSI_BIT_ID_TYPE scsi_busy;
9503 ASC_SCSI_BIT_ID_TYPE target_id;
9504 PortAddr iop_base;
9505 ushort q_addr;
9506 ushort sg_q_addr;
9507 uchar cur_target_qng;
9508 ASC_QDONE_INFO scsiq_buf;
9509 ASC_QDONE_INFO *scsiq;
9510 int false_overrun;
9511
9512 iop_base = asc_dvc->iop_base;
9513 n_q_used = 1;
9514 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
9515 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
9516 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
9517 next_qp = AscReadLramByte(iop_base,
9518 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
9519 if (next_qp != ASC_QLINK_END) {
9520 AscPutVarDoneQTail(iop_base, next_qp);
9521 q_addr = ASC_QNO_TO_QADDR(next_qp);
9522 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
9523 asc_dvc->max_dma_count);
9524 AscWriteLramByte(iop_base,
9525 (ushort)(q_addr +
9526 (ushort)ASC_SCSIQ_B_STATUS),
9527 (uchar)(scsiq->
9528 q_status & (uchar)~(QS_READY |
9529 QS_ABORTED)));
9530 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
9531 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
9532 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
9533 sg_q_addr = q_addr;
9534 sg_list_qp = next_qp;
9535 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
9536 sg_list_qp = AscReadLramByte(iop_base,
9537 (ushort)(sg_q_addr
9538 + (ushort)
9539 ASC_SCSIQ_B_FWD));
9540 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
9541 if (sg_list_qp == ASC_QLINK_END) {
9542 AscSetLibErrorCode(asc_dvc,
9543 ASCQ_ERR_SG_Q_LINKS);
9544 scsiq->d3.done_stat = QD_WITH_ERROR;
9545 scsiq->d3.host_stat =
9546 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
9547 goto FATAL_ERR_QDONE;
9548 }
9549 AscWriteLramByte(iop_base,
9550 (ushort)(sg_q_addr + (ushort)
9551 ASC_SCSIQ_B_STATUS),
9552 QS_FREE);
9553 }
9554 n_q_used = sg_queue_cnt + 1;
9555 AscPutVarDoneQTail(iop_base, sg_list_qp);
9556 }
9557 if (asc_dvc->queue_full_or_busy & target_id) {
9558 cur_target_qng = AscReadLramByte(iop_base,
9559 (ushort)((ushort)
9560 ASC_QADR_BEG
9561 + (ushort)
9562 scsiq->d2.
9563 target_ix));
9564 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
9565 scsi_busy = AscReadLramByte(iop_base, (ushort)
9566 ASCV_SCSIBUSY_B);
9567 scsi_busy &= ~target_id;
9568 AscWriteLramByte(iop_base,
9569 (ushort)ASCV_SCSIBUSY_B,
9570 scsi_busy);
9571 asc_dvc->queue_full_or_busy &= ~target_id;
9572 }
9573 }
9574 if (asc_dvc->cur_total_qng >= n_q_used) {
9575 asc_dvc->cur_total_qng -= n_q_used;
9576 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
9577 asc_dvc->cur_dvc_qng[tid_no]--;
9578 }
9579 } else {
9580 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
9581 scsiq->d3.done_stat = QD_WITH_ERROR;
9582 goto FATAL_ERR_QDONE;
9583 }
9584 if ((scsiq->d2.srb_ptr == 0UL) ||
9585 ((scsiq->q_status & QS_ABORTED) != 0)) {
9586 return (0x11);
9587 } else if (scsiq->q_status == QS_DONE) {
9588 false_overrun = FALSE;
9589 if (scsiq->extra_bytes != 0) {
9590 scsiq->remain_bytes +=
9591 (ADV_DCNT)scsiq->extra_bytes;
9592 }
9593 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
9594 if (scsiq->d3.host_stat ==
9595 QHSTA_M_DATA_OVER_RUN) {
9596 if ((scsiq->
9597 cntl & (QC_DATA_IN | QC_DATA_OUT))
9598 == 0) {
9599 scsiq->d3.done_stat =
9600 QD_NO_ERROR;
9601 scsiq->d3.host_stat =
9602 QHSTA_NO_ERROR;
9603 } else if (false_overrun) {
9604 scsiq->d3.done_stat =
9605 QD_NO_ERROR;
9606 scsiq->d3.host_stat =
9607 QHSTA_NO_ERROR;
9608 }
9609 } else if (scsiq->d3.host_stat ==
9610 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
9611 AscStopChip(iop_base);
9612 AscSetChipControl(iop_base,
9613 (uchar)(CC_SCSI_RESET
9614 | CC_HALT));
9615 udelay(60);
9616 AscSetChipControl(iop_base, CC_HALT);
9617 AscSetChipStatus(iop_base,
9618 CIW_CLR_SCSI_RESET_INT);
9619 AscSetChipStatus(iop_base, 0);
9620 AscSetChipControl(iop_base, 0);
9621 }
9622 }
9623 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9624 asc_isr_callback(asc_dvc, scsiq);
9625 } else {
9626 if ((AscReadLramByte(iop_base,
9627 (ushort)(q_addr + (ushort)
9628 ASC_SCSIQ_CDB_BEG))
9629 == START_STOP)) {
9630 asc_dvc->unit_not_ready &= ~target_id;
9631 if (scsiq->d3.done_stat != QD_NO_ERROR) {
9632 asc_dvc->start_motor &=
9633 ~target_id;
9634 }
9635 }
9636 }
9637 return (1);
9638 } else {
9639 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
9640 FATAL_ERR_QDONE:
9641 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9642 asc_isr_callback(asc_dvc, scsiq);
9643 }
9644 return (0x80);
9645 }
9646 }
9647 return (0);
9648}
9649
9650static int AscISR(ASC_DVC_VAR *asc_dvc)
9651{
9652 ASC_CS_TYPE chipstat;
9653 PortAddr iop_base;
9654 ushort saved_ram_addr;
9655 uchar ctrl_reg;
9656 uchar saved_ctrl_reg;
9657 int int_pending;
9658 int status;
9659 uchar host_flag;
9660
9661 iop_base = asc_dvc->iop_base;
9662 int_pending = FALSE;
9663
9664 if (AscIsIntPending(iop_base) == 0)
9665 return int_pending;
9666
9667 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
9668 return ERR;
9669 }
9670 if (asc_dvc->in_critical_cnt != 0) {
9671 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
9672 return ERR;
9673 }
9674 if (asc_dvc->is_in_int) {
9675 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
9676 return ERR;
9677 }
9678 asc_dvc->is_in_int = TRUE;
9679 ctrl_reg = AscGetChipControl(iop_base);
9680 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
9681 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
9682 chipstat = AscGetChipStatus(iop_base);
9683 if (chipstat & CSW_SCSI_RESET_LATCH) {
9684 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
9685 int i = 10;
9686 int_pending = TRUE;
9687 asc_dvc->sdtr_done = 0;
9688 saved_ctrl_reg &= (uchar)(~CC_HALT);
9689 while ((AscGetChipStatus(iop_base) &
9690 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
9691 mdelay(100);
9692 }
9693 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
9694 AscSetChipControl(iop_base, CC_HALT);
9695 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9696 AscSetChipStatus(iop_base, 0);
9697 chipstat = AscGetChipStatus(iop_base);
9698 }
9699 }
9700 saved_ram_addr = AscGetChipLramAddr(iop_base);
9701 host_flag = AscReadLramByte(iop_base,
9702 ASCV_HOST_FLAG_B) &
9703 (uchar)(~ASC_HOST_FLAG_IN_ISR);
9704 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
9705 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
9706 if ((chipstat & CSW_INT_PENDING) || (int_pending)) {
9707 AscAckInterrupt(iop_base);
9708 int_pending = TRUE;
9709 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
9710 if (AscIsrChipHalted(asc_dvc) == ERR) {
9711 goto ISR_REPORT_QDONE_FATAL_ERROR;
9712 } else {
9713 saved_ctrl_reg &= (uchar)(~CC_HALT);
9714 }
9715 } else {
9716 ISR_REPORT_QDONE_FATAL_ERROR:
9717 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
9718 while (((status =
9719 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
9720 }
9721 } else {
9722 do {
9723 if ((status =
9724 AscIsrQDone(asc_dvc)) == 1) {
9725 break;
9726 }
9727 } while (status == 0x11);
9728 }
9729 if ((status & 0x80) != 0)
9730 int_pending = ERR;
9731 }
9732 }
9733 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9734 AscSetChipLramAddr(iop_base, saved_ram_addr);
9735 AscSetChipControl(iop_base, saved_ctrl_reg);
9736 asc_dvc->is_in_int = FALSE;
9737 return int_pending;
9738}
9739
9740/*
9741 * advansys_reset()
9742 *
9743 * Reset the bus associated with the command 'scp'.
9744 *
9745 * This function runs its own thread. Interrupts must be blocked but
9746 * sleeping is allowed and no locking other than for host structures is
9747 * required. Returns SUCCESS or FAILED.
9748 */
9749static int advansys_reset(struct scsi_cmnd *scp)
9750{
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009751 struct Scsi_Host *shost = scp->device->host;
9752 struct asc_board *boardp = ASC_BOARDP(shost);
9753 unsigned long flags;
Matthew Wilcox51219352007-10-02 21:55:22 -04009754 int status;
9755 int ret = SUCCESS;
9756
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009757 ASC_DBG1(1, "advansys_reset: 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009758
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009759 ASC_STATS(shost, reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04009760
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009761 scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009762
9763 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009764 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009765
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009766 /* Reset the chip and SCSI bus. */
Matthew Wilcox51219352007-10-02 21:55:22 -04009767 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009768 status = AscInitAsc1000Driver(asc_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009769
9770 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009771 if (asc_dvc->err_code) {
9772 scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
9773 "0x%x\n", asc_dvc->err_code);
Matthew Wilcox51219352007-10-02 21:55:22 -04009774 ret = FAILED;
9775 } else if (status) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009776 scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
9777 "0x%x\n", status);
Matthew Wilcox51219352007-10-02 21:55:22 -04009778 } else {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009779 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9780 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009781 }
9782
9783 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
9784 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009785 } else {
9786 /*
Matthew Wilcox51219352007-10-02 21:55:22 -04009787 * If the suggest reset bus flags are set, then reset the bus.
9788 * Otherwise only reset the device.
9789 */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009790 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009791
9792 /*
9793 * Reset the target's SCSI bus.
9794 */
9795 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009796 switch (AdvResetChipAndSB(adv_dvc)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04009797 case ASC_TRUE:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009798 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9799 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009800 break;
9801 case ASC_FALSE:
9802 default:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009803 scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009804 ret = FAILED;
9805 break;
9806 }
9807 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009808 AdvISR(adv_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009809 }
Matthew Wilcox51219352007-10-02 21:55:22 -04009810
9811 /* Save the time of the most recently completed reset. */
9812 boardp->last_reset = jiffies;
Matthew Wilcox51219352007-10-02 21:55:22 -04009813 spin_unlock_irqrestore(&boardp->lock, flags);
9814
9815 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
9816
9817 return ret;
9818}
9819
9820/*
9821 * advansys_biosparam()
9822 *
9823 * Translate disk drive geometry if the "BIOS greater than 1 GB"
9824 * support is enabled for a drive.
9825 *
9826 * ip (information pointer) is an int array with the following definition:
9827 * ip[0]: heads
9828 * ip[1]: sectors
9829 * ip[2]: cylinders
9830 */
9831static int
9832advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
9833 sector_t capacity, int ip[])
9834{
9835 asc_board_t *boardp;
9836
9837 ASC_DBG(1, "advansys_biosparam: begin\n");
9838 ASC_STATS(sdev->host, biosparam);
9839 boardp = ASC_BOARDP(sdev->host);
9840 if (ASC_NARROW_BOARD(boardp)) {
9841 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
9842 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
9843 ip[0] = 255;
9844 ip[1] = 63;
9845 } else {
9846 ip[0] = 64;
9847 ip[1] = 32;
9848 }
9849 } else {
9850 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
9851 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
9852 ip[0] = 255;
9853 ip[1] = 63;
9854 } else {
9855 ip[0] = 64;
9856 ip[1] = 32;
9857 }
9858 }
9859 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
9860 ASC_DBG(1, "advansys_biosparam: end\n");
9861 return 0;
9862}
9863
9864/*
9865 * First-level interrupt handler.
9866 *
9867 * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host.
9868 */
9869static irqreturn_t advansys_interrupt(int irq, void *dev_id)
9870{
9871 unsigned long flags;
9872 struct Scsi_Host *shost = dev_id;
9873 asc_board_t *boardp = ASC_BOARDP(shost);
9874 irqreturn_t result = IRQ_NONE;
9875
9876 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
9877 spin_lock_irqsave(&boardp->lock, flags);
9878 if (ASC_NARROW_BOARD(boardp)) {
9879 if (AscIsIntPending(shost->io_port)) {
9880 result = IRQ_HANDLED;
9881 ASC_STATS(shost, interrupt);
9882 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
9883 AscISR(&boardp->dvc_var.asc_dvc_var);
9884 }
9885 } else {
9886 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
9887 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
9888 result = IRQ_HANDLED;
9889 ASC_STATS(shost, interrupt);
9890 }
9891 }
9892 spin_unlock_irqrestore(&boardp->lock, flags);
9893
9894 ASC_DBG(1, "advansys_interrupt: end\n");
9895 return result;
9896}
9897
9898static int AscHostReqRiscHalt(PortAddr iop_base)
9899{
9900 int count = 0;
9901 int sta = 0;
9902 uchar saved_stop_code;
9903
9904 if (AscIsChipHalted(iop_base))
9905 return (1);
9906 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
9907 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9908 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
9909 do {
9910 if (AscIsChipHalted(iop_base)) {
9911 sta = 1;
9912 break;
9913 }
9914 mdelay(100);
9915 } while (count++ < 20);
9916 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
9917 return (sta);
9918}
9919
9920static int
9921AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
9922{
9923 int sta = FALSE;
9924
9925 if (AscHostReqRiscHalt(iop_base)) {
9926 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9927 AscStartChip(iop_base);
9928 }
9929 return sta;
9930}
9931
9932static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
9933{
9934 char type = sdev->type;
9935 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
9936
9937 if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN))
9938 return;
9939 if (asc_dvc->init_sdtr & tid_bits)
9940 return;
9941
9942 if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0))
9943 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9944
9945 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
9946 if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) ||
9947 (type == TYPE_ROM) || (type == TYPE_TAPE))
9948 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9949
9950 if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
9951 AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id,
9952 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
9953}
9954
9955static void
9956advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
9957{
9958 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
9959 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
9960
9961 if (sdev->lun == 0) {
9962 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
9963 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
9964 asc_dvc->init_sdtr |= tid_bit;
9965 } else {
9966 asc_dvc->init_sdtr &= ~tid_bit;
9967 }
9968
9969 if (orig_init_sdtr != asc_dvc->init_sdtr)
9970 AscAsyncFix(asc_dvc, sdev);
9971 }
9972
9973 if (sdev->tagged_supported) {
9974 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
9975 if (sdev->lun == 0) {
9976 asc_dvc->cfg->can_tagged_qng |= tid_bit;
9977 asc_dvc->use_tagged_qng |= tid_bit;
9978 }
9979 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9980 asc_dvc->max_dvc_qng[sdev->id]);
9981 }
9982 } else {
9983 if (sdev->lun == 0) {
9984 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
9985 asc_dvc->use_tagged_qng &= ~tid_bit;
9986 }
9987 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9988 }
9989
9990 if ((sdev->lun == 0) &&
9991 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
9992 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
9993 asc_dvc->cfg->disc_enable);
9994 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
9995 asc_dvc->use_tagged_qng);
9996 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
9997 asc_dvc->cfg->can_tagged_qng);
9998
9999 asc_dvc->max_dvc_qng[sdev->id] =
10000 asc_dvc->cfg->max_tag_qng[sdev->id];
10001 AscWriteLramByte(asc_dvc->iop_base,
10002 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
10003 asc_dvc->max_dvc_qng[sdev->id]);
10004 }
10005}
10006
10007/*
10008 * Wide Transfers
10009 *
10010 * If the EEPROM enabled WDTR for the device and the device supports wide
10011 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
10012 * write the new value to the microcode.
10013 */
10014static void
10015advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
10016{
10017 unsigned short cfg_word;
10018 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
10019 if ((cfg_word & tidmask) != 0)
10020 return;
10021
10022 cfg_word |= tidmask;
10023 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
10024
10025 /*
10026 * Clear the microcode SDTR and WDTR negotiation done indicators for
10027 * the target to cause it to negotiate with the new setting set above.
10028 * WDTR when accepted causes the target to enter asynchronous mode, so
10029 * SDTR must be negotiated.
10030 */
10031 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10032 cfg_word &= ~tidmask;
10033 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10034 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
10035 cfg_word &= ~tidmask;
10036 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
10037}
10038
10039/*
10040 * Synchronous Transfers
10041 *
10042 * If the EEPROM enabled SDTR for the device and the device
10043 * supports synchronous transfers, then turn on the device's
10044 * 'sdtr_able' bit. Write the new value to the microcode.
10045 */
10046static void
10047advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
10048{
10049 unsigned short cfg_word;
10050 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
10051 if ((cfg_word & tidmask) != 0)
10052 return;
10053
10054 cfg_word |= tidmask;
10055 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
10056
10057 /*
10058 * Clear the microcode "SDTR negotiation" done indicator for the
10059 * target to cause it to negotiate with the new setting set above.
10060 */
10061 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10062 cfg_word &= ~tidmask;
10063 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10064}
10065
10066/*
10067 * PPR (Parallel Protocol Request) Capable
10068 *
10069 * If the device supports DT mode, then it must be PPR capable.
10070 * The PPR message will be used in place of the SDTR and WDTR
10071 * messages to negotiate synchronous speed and offset, transfer
10072 * width, and protocol options.
10073 */
10074static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
10075 AdvPortAddr iop_base, unsigned short tidmask)
10076{
10077 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
10078 adv_dvc->ppr_able |= tidmask;
10079 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
10080}
10081
10082static void
10083advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
10084{
10085 AdvPortAddr iop_base = adv_dvc->iop_base;
10086 unsigned short tidmask = 1 << sdev->id;
10087
10088 if (sdev->lun == 0) {
10089 /*
10090 * Handle WDTR, SDTR, and Tag Queuing. If the feature
10091 * is enabled in the EEPROM and the device supports the
10092 * feature, then enable it in the microcode.
10093 */
10094
10095 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
10096 advansys_wide_enable_wdtr(iop_base, tidmask);
10097 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
10098 advansys_wide_enable_sdtr(iop_base, tidmask);
10099 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
10100 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
10101
10102 /*
10103 * Tag Queuing is disabled for the BIOS which runs in polled
10104 * mode and would see no benefit from Tag Queuing. Also by
10105 * disabling Tag Queuing in the BIOS devices with Tag Queuing
10106 * bugs will at least work with the BIOS.
10107 */
10108 if ((adv_dvc->tagqng_able & tidmask) &&
10109 sdev->tagged_supported) {
10110 unsigned short cfg_word;
10111 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
10112 cfg_word |= tidmask;
10113 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
10114 cfg_word);
10115 AdvWriteByteLram(iop_base,
10116 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
10117 adv_dvc->max_dvc_qng);
10118 }
10119 }
10120
10121 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
10122 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
10123 adv_dvc->max_dvc_qng);
10124 } else {
10125 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
10126 }
10127}
10128
10129/*
10130 * Set the number of commands to queue per device for the
10131 * specified host adapter.
10132 */
10133static int advansys_slave_configure(struct scsi_device *sdev)
10134{
10135 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040010136
Matthew Wilcox51219352007-10-02 21:55:22 -040010137 if (ASC_NARROW_BOARD(boardp))
10138 advansys_narrow_slave_configure(sdev,
10139 &boardp->dvc_var.asc_dvc_var);
10140 else
10141 advansys_wide_slave_configure(sdev,
10142 &boardp->dvc_var.adv_dvc_var);
10143
10144 return 0;
10145}
10146
Matthew Wilcox05848b62007-10-02 21:55:25 -040010147static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
10148 struct asc_scsi_q *asc_scsi_q)
Matthew Wilcox51219352007-10-02 21:55:22 -040010149{
Matthew Wilcox05848b62007-10-02 21:55:25 -040010150 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
Matthew Wilcox51219352007-10-02 21:55:22 -040010151
10152 /*
10153 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
10154 */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010155 asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040010156
10157 /*
10158 * Build the ASC_SCSI_Q request.
10159 */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010160 asc_scsi_q->cdbptr = &scp->cmnd[0];
10161 asc_scsi_q->q2.cdb_len = scp->cmd_len;
10162 asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
10163 asc_scsi_q->q1.target_lun = scp->device->lun;
10164 asc_scsi_q->q2.target_ix =
Matthew Wilcox51219352007-10-02 21:55:22 -040010165 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
Matthew Wilcox05848b62007-10-02 21:55:25 -040010166 asc_scsi_q->q1.sense_addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010167 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010168 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
Matthew Wilcox51219352007-10-02 21:55:22 -040010169
10170 /*
10171 * If there are any outstanding requests for the current target,
10172 * then every 255th request send an ORDERED request. This heuristic
10173 * tries to retain the benefit of request sorting while preventing
10174 * request starvation. 255 is the max number of tags or pending commands
10175 * a device may have outstanding.
10176 *
10177 * The request count is incremented below for every successfully
10178 * started request.
10179 *
10180 */
10181 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
10182 (boardp->reqcnt[scp->device->id] % 255) == 0) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010183 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010184 } else {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010185 asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010186 }
10187
10188 /*
10189 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
10190 * buffer command.
10191 */
10192 if (scp->use_sg == 0) {
10193 /*
10194 * CDB request of single contiguous buffer.
10195 */
10196 ASC_STATS(scp->device->host, cont_cnt);
10197 scp->SCp.dma_handle = scp->request_bufflen ?
10198 dma_map_single(boardp->dev, scp->request_buffer,
10199 scp->request_bufflen,
10200 scp->sc_data_direction) : 0;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010201 asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
10202 asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen);
Matthew Wilcox51219352007-10-02 21:55:22 -040010203 ASC_STATS_ADD(scp->device->host, cont_xfer,
10204 ASC_CEILING(scp->request_bufflen, 512));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010205 asc_scsi_q->q1.sg_queue_cnt = 0;
10206 asc_scsi_q->sg_head = NULL;
Matthew Wilcox51219352007-10-02 21:55:22 -040010207 } else {
10208 /*
10209 * CDB scatter-gather request list.
10210 */
10211 int sgcnt;
10212 int use_sg;
10213 struct scatterlist *slp;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010214 struct asc_sg_head *asc_sg_head;
Matthew Wilcox51219352007-10-02 21:55:22 -040010215
10216 slp = (struct scatterlist *)scp->request_buffer;
10217 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10218 scp->sc_data_direction);
10219
10220 if (use_sg > scp->device->host->sg_tablesize) {
10221 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
10222 "sg_tablesize %d\n", boardp->id, use_sg,
10223 scp->device->host->sg_tablesize);
10224 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10225 scp->sc_data_direction);
10226 scp->result = HOST_BYTE(DID_ERROR);
10227 return ASC_ERROR;
10228 }
10229
10230 ASC_STATS(scp->device->host, sg_cnt);
10231
Matthew Wilcox05848b62007-10-02 21:55:25 -040010232 asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
10233 use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
10234 if (!asc_sg_head) {
10235 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10236 scp->sc_data_direction);
10237 scp->result = HOST_BYTE(DID_SOFT_ERROR);
10238 return ASC_ERROR;
10239 }
Matthew Wilcox51219352007-10-02 21:55:22 -040010240
Matthew Wilcox05848b62007-10-02 21:55:25 -040010241 asc_scsi_q->q1.cntl |= QC_SG_HEAD;
10242 asc_scsi_q->sg_head = asc_sg_head;
10243 asc_scsi_q->q1.data_cnt = 0;
10244 asc_scsi_q->q1.data_addr = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040010245 /* This is a byte value, otherwise it would need to be swapped. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010246 asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
Matthew Wilcox51219352007-10-02 21:55:22 -040010247 ASC_STATS_ADD(scp->device->host, sg_elem,
Matthew Wilcox05848b62007-10-02 21:55:25 -040010248 asc_sg_head->entry_cnt);
Matthew Wilcox51219352007-10-02 21:55:22 -040010249
10250 /*
10251 * Convert scatter-gather list into ASC_SG_HEAD list.
10252 */
10253 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010254 asc_sg_head->sg_list[sgcnt].addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010255 cpu_to_le32(sg_dma_address(slp));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010256 asc_sg_head->sg_list[sgcnt].bytes =
Matthew Wilcox51219352007-10-02 21:55:22 -040010257 cpu_to_le32(sg_dma_len(slp));
10258 ASC_STATS_ADD(scp->device->host, sg_xfer,
10259 ASC_CEILING(sg_dma_len(slp), 512));
10260 }
10261 }
10262
10263 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
10264 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10265
10266 return ASC_NOERROR;
10267}
10268
10269/*
10270 * Build scatter-gather list for Adv Library (Wide Board).
10271 *
10272 * Additional ADV_SG_BLOCK structures will need to be allocated
10273 * if the total number of scatter-gather elements exceeds
10274 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
10275 * assumed to be physically contiguous.
10276 *
10277 * Return:
10278 * ADV_SUCCESS(1) - SG List successfully created
10279 * ADV_ERROR(-1) - SG List creation failed
10280 */
10281static int
10282adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
10283 int use_sg)
10284{
10285 adv_sgblk_t *sgblkp;
10286 ADV_SCSI_REQ_Q *scsiqp;
10287 struct scatterlist *slp;
10288 int sg_elem_cnt;
10289 ADV_SG_BLOCK *sg_block, *prev_sg_block;
10290 ADV_PADDR sg_block_paddr;
10291 int i;
10292
10293 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10294 slp = (struct scatterlist *)scp->request_buffer;
10295 sg_elem_cnt = use_sg;
10296 prev_sg_block = NULL;
10297 reqp->sgblkp = NULL;
10298
10299 for (;;) {
10300 /*
10301 * Allocate a 'adv_sgblk_t' structure from the board free
10302 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
10303 * (15) scatter-gather elements.
10304 */
10305 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
10306 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
10307 ASC_STATS(scp->device->host, adv_build_nosg);
10308
10309 /*
10310 * Allocation failed. Free 'adv_sgblk_t' structures
10311 * already allocated for the request.
10312 */
10313 while ((sgblkp = reqp->sgblkp) != NULL) {
10314 /* Remove 'sgblkp' from the request list. */
10315 reqp->sgblkp = sgblkp->next_sgblkp;
10316
10317 /* Add 'sgblkp' to the board free list. */
10318 sgblkp->next_sgblkp = boardp->adv_sgblkp;
10319 boardp->adv_sgblkp = sgblkp;
10320 }
10321 return ASC_BUSY;
10322 }
10323
10324 /* Complete 'adv_sgblk_t' board allocation. */
10325 boardp->adv_sgblkp = sgblkp->next_sgblkp;
10326 sgblkp->next_sgblkp = NULL;
10327
10328 /*
10329 * Get 8 byte aligned virtual and physical addresses
10330 * for the allocated ADV_SG_BLOCK structure.
10331 */
10332 sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
10333 sg_block_paddr = virt_to_bus(sg_block);
10334
10335 /*
10336 * Check if this is the first 'adv_sgblk_t' for the
10337 * request.
10338 */
10339 if (reqp->sgblkp == NULL) {
10340 /* Request's first scatter-gather block. */
10341 reqp->sgblkp = sgblkp;
10342
10343 /*
10344 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
10345 * address pointers.
10346 */
10347 scsiqp->sg_list_ptr = sg_block;
10348 scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
10349 } else {
10350 /* Request's second or later scatter-gather block. */
10351 sgblkp->next_sgblkp = reqp->sgblkp;
10352 reqp->sgblkp = sgblkp;
10353
10354 /*
10355 * Point the previous ADV_SG_BLOCK structure to
10356 * the newly allocated ADV_SG_BLOCK structure.
10357 */
10358 prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
10359 }
10360
10361 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
10362 sg_block->sg_list[i].sg_addr =
10363 cpu_to_le32(sg_dma_address(slp));
10364 sg_block->sg_list[i].sg_count =
10365 cpu_to_le32(sg_dma_len(slp));
10366 ASC_STATS_ADD(scp->device->host, sg_xfer,
10367 ASC_CEILING(sg_dma_len(slp), 512));
10368
10369 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
10370 sg_block->sg_cnt = i + 1;
10371 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
10372 return ADV_SUCCESS;
10373 }
10374 slp++;
10375 }
10376 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
10377 prev_sg_block = sg_block;
10378 }
10379}
10380
10381/*
10382 * Build a request structure for the Adv Library (Wide Board).
10383 *
10384 * If an adv_req_t can not be allocated to issue the request,
10385 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
10386 *
10387 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
10388 * microcode for DMA addresses or math operations are byte swapped
10389 * to little-endian order.
10390 */
10391static int
10392adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
10393 ADV_SCSI_REQ_Q **adv_scsiqpp)
10394{
10395 adv_req_t *reqp;
10396 ADV_SCSI_REQ_Q *scsiqp;
10397 int i;
10398 int ret;
10399
10400 /*
10401 * Allocate an adv_req_t structure from the board to execute
10402 * the command.
10403 */
10404 if (boardp->adv_reqp == NULL) {
10405 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
10406 ASC_STATS(scp->device->host, adv_build_noreq);
10407 return ASC_BUSY;
10408 } else {
10409 reqp = boardp->adv_reqp;
10410 boardp->adv_reqp = reqp->next_reqp;
10411 reqp->next_reqp = NULL;
10412 }
10413
10414 /*
10415 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
10416 */
10417 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10418
10419 /*
10420 * Initialize the structure.
10421 */
10422 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
10423
10424 /*
10425 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
10426 */
10427 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
10428
10429 /*
10430 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
10431 */
10432 reqp->cmndp = scp;
10433
10434 /*
10435 * Build the ADV_SCSI_REQ_Q request.
10436 */
10437
10438 /* Set CDB length and copy it to the request structure. */
10439 scsiqp->cdb_len = scp->cmd_len;
10440 /* Copy first 12 CDB bytes to cdb[]. */
10441 for (i = 0; i < scp->cmd_len && i < 12; i++) {
10442 scsiqp->cdb[i] = scp->cmnd[i];
10443 }
10444 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
10445 for (; i < scp->cmd_len; i++) {
10446 scsiqp->cdb16[i - 12] = scp->cmnd[i];
10447 }
10448
10449 scsiqp->target_id = scp->device->id;
10450 scsiqp->target_lun = scp->device->lun;
10451
10452 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
10453 scsiqp->sense_len = sizeof(scp->sense_buffer);
10454
10455 /*
10456 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
10457 * buffer command.
10458 */
10459
10460 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10461 scsiqp->vdata_addr = scp->request_buffer;
10462 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
10463
10464 if (scp->use_sg == 0) {
10465 /*
10466 * CDB request of single contiguous buffer.
10467 */
10468 reqp->sgblkp = NULL;
10469 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10470 if (scp->request_bufflen) {
10471 scsiqp->vdata_addr = scp->request_buffer;
10472 scp->SCp.dma_handle =
10473 dma_map_single(boardp->dev, scp->request_buffer,
10474 scp->request_bufflen,
10475 scp->sc_data_direction);
10476 } else {
10477 scsiqp->vdata_addr = NULL;
10478 scp->SCp.dma_handle = 0;
10479 }
10480 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
10481 scsiqp->sg_list_ptr = NULL;
10482 scsiqp->sg_real_addr = 0;
10483 ASC_STATS(scp->device->host, cont_cnt);
10484 ASC_STATS_ADD(scp->device->host, cont_xfer,
10485 ASC_CEILING(scp->request_bufflen, 512));
10486 } else {
10487 /*
10488 * CDB scatter-gather request list.
10489 */
10490 struct scatterlist *slp;
10491 int use_sg;
10492
10493 slp = (struct scatterlist *)scp->request_buffer;
10494 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10495 scp->sc_data_direction);
10496
10497 if (use_sg > ADV_MAX_SG_LIST) {
10498 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
10499 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
10500 scp->device->host->sg_tablesize);
10501 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10502 scp->sc_data_direction);
10503 scp->result = HOST_BYTE(DID_ERROR);
10504
10505 /*
10506 * Free the 'adv_req_t' structure by adding it back
10507 * to the board free list.
10508 */
10509 reqp->next_reqp = boardp->adv_reqp;
10510 boardp->adv_reqp = reqp;
10511
10512 return ASC_ERROR;
10513 }
10514
10515 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
10516 if (ret != ADV_SUCCESS) {
10517 /*
10518 * Free the adv_req_t structure by adding it back to
10519 * the board free list.
10520 */
10521 reqp->next_reqp = boardp->adv_reqp;
10522 boardp->adv_reqp = reqp;
10523
10524 return ret;
10525 }
10526
10527 ASC_STATS(scp->device->host, sg_cnt);
10528 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
10529 }
10530
10531 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
10532 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10533
10534 *adv_scsiqpp = scsiqp;
10535
10536 return ASC_NOERROR;
10537}
10538
10539static int AscSgListToQueue(int sg_list)
10540{
10541 int n_sg_list_qs;
10542
10543 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
10544 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
10545 n_sg_list_qs++;
10546 return n_sg_list_qs + 1;
10547}
10548
10549static uint
10550AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
10551{
10552 uint cur_used_qs;
10553 uint cur_free_qs;
10554 ASC_SCSI_BIT_ID_TYPE target_id;
10555 uchar tid_no;
10556
10557 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
10558 tid_no = ASC_TIX_TO_TID(target_ix);
10559 if ((asc_dvc->unit_not_ready & target_id) ||
10560 (asc_dvc->queue_full_or_busy & target_id)) {
10561 return 0;
10562 }
10563 if (n_qs == 1) {
10564 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10565 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
10566 } else {
10567 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10568 (uint) ASC_MIN_FREE_Q;
10569 }
10570 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
10571 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
10572 if (asc_dvc->cur_dvc_qng[tid_no] >=
10573 asc_dvc->max_dvc_qng[tid_no]) {
10574 return 0;
10575 }
10576 return cur_free_qs;
10577 }
10578 if (n_qs > 1) {
10579 if ((n_qs > asc_dvc->last_q_shortage)
10580 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
10581 asc_dvc->last_q_shortage = n_qs;
10582 }
10583 }
10584 return 0;
10585}
10586
10587static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
10588{
10589 ushort q_addr;
10590 uchar next_qp;
10591 uchar q_status;
10592
10593 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10594 q_status = (uchar)AscReadLramByte(iop_base,
10595 (ushort)(q_addr +
10596 ASC_SCSIQ_B_STATUS));
10597 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10598 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END))
10599 return next_qp;
10600 return ASC_QLINK_END;
10601}
10602
10603static uchar
10604AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
10605{
10606 uchar i;
10607
10608 for (i = 0; i < n_free_q; i++) {
10609 free_q_head = AscAllocFreeQueue(iop_base, free_q_head);
10610 if (free_q_head == ASC_QLINK_END)
10611 break;
10612 }
10613 return free_q_head;
10614}
10615
10616/*
10617 * void
10618 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10619 *
10620 * Calling/Exit State:
10621 * none
10622 *
10623 * Description:
10624 * Output an ASC_SCSI_Q structure to the chip
10625 */
10626static void
10627DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10628{
10629 int i;
10630
10631 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
10632 AscSetChipLramAddr(iop_base, s_addr);
10633 for (i = 0; i < 2 * words; i += 2) {
10634 if (i == 4 || i == 20) {
10635 continue;
10636 }
10637 outpw(iop_base + IOP_RAM_DATA,
10638 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
10639 }
10640}
10641
10642static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10643{
10644 ushort q_addr;
10645 uchar tid_no;
10646 uchar sdtr_data;
10647 uchar syn_period_ix;
10648 uchar syn_offset;
10649 PortAddr iop_base;
10650
10651 iop_base = asc_dvc->iop_base;
10652 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
10653 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
10654 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
10655 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10656 syn_period_ix =
10657 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
10658 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
10659 AscMsgOutSDTR(asc_dvc,
10660 asc_dvc->sdtr_period_tbl[syn_period_ix],
10661 syn_offset);
10662 scsiq->q1.cntl |= QC_MSG_OUT;
10663 }
10664 q_addr = ASC_QNO_TO_QADDR(q_no);
10665 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
10666 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10667 }
10668 scsiq->q1.status = QS_FREE;
10669 AscMemWordCopyPtrToLram(iop_base,
10670 q_addr + ASC_SCSIQ_CDB_BEG,
10671 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
10672
10673 DvcPutScsiQ(iop_base,
10674 q_addr + ASC_SCSIQ_CPY_BEG,
10675 (uchar *)&scsiq->q1.cntl,
10676 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
10677 AscWriteLramWord(iop_base,
10678 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
10679 (ushort)(((ushort)scsiq->q1.
10680 q_no << 8) | (ushort)QS_READY));
10681 return 1;
10682}
10683
10684static int
10685AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10686{
10687 int sta;
10688 int i;
10689 ASC_SG_HEAD *sg_head;
10690 ASC_SG_LIST_Q scsi_sg_q;
10691 ASC_DCNT saved_data_addr;
10692 ASC_DCNT saved_data_cnt;
10693 PortAddr iop_base;
10694 ushort sg_list_dwords;
10695 ushort sg_index;
10696 ushort sg_entry_cnt;
10697 ushort q_addr;
10698 uchar next_qp;
10699
10700 iop_base = asc_dvc->iop_base;
10701 sg_head = scsiq->sg_head;
10702 saved_data_addr = scsiq->q1.data_addr;
10703 saved_data_cnt = scsiq->q1.data_cnt;
10704 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
10705 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
10706#if CC_VERY_LONG_SG_LIST
10707 /*
10708 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
10709 * then not all SG elements will fit in the allocated queues.
10710 * The rest of the SG elements will be copied when the RISC
10711 * completes the SG elements that fit and halts.
10712 */
10713 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10714 /*
10715 * Set sg_entry_cnt to be the number of SG elements that
10716 * will fit in the allocated SG queues. It is minus 1, because
10717 * the first SG element is handled above. ASC_MAX_SG_LIST is
10718 * already inflated by 1 to account for this. For example it
10719 * may be 50 which is 1 + 7 queues * 7 SG elements.
10720 */
10721 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
10722
10723 /*
10724 * Keep track of remaining number of SG elements that will
10725 * need to be handled from a_isr.c.
10726 */
10727 scsiq->remain_sg_entry_cnt =
10728 sg_head->entry_cnt - ASC_MAX_SG_LIST;
10729 } else {
10730#endif /* CC_VERY_LONG_SG_LIST */
10731 /*
10732 * Set sg_entry_cnt to be the number of SG elements that
10733 * will fit in the allocated SG queues. It is minus 1, because
10734 * the first SG element is handled above.
10735 */
10736 sg_entry_cnt = sg_head->entry_cnt - 1;
10737#if CC_VERY_LONG_SG_LIST
10738 }
10739#endif /* CC_VERY_LONG_SG_LIST */
10740 if (sg_entry_cnt != 0) {
10741 scsiq->q1.cntl |= QC_SG_HEAD;
10742 q_addr = ASC_QNO_TO_QADDR(q_no);
10743 sg_index = 1;
10744 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
10745 scsi_sg_q.sg_head_qp = q_no;
10746 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
10747 for (i = 0; i < sg_head->queue_cnt; i++) {
10748 scsi_sg_q.seq_no = i + 1;
10749 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
10750 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
10751 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
10752 if (i == 0) {
10753 scsi_sg_q.sg_list_cnt =
10754 ASC_SG_LIST_PER_Q;
10755 scsi_sg_q.sg_cur_list_cnt =
10756 ASC_SG_LIST_PER_Q;
10757 } else {
10758 scsi_sg_q.sg_list_cnt =
10759 ASC_SG_LIST_PER_Q - 1;
10760 scsi_sg_q.sg_cur_list_cnt =
10761 ASC_SG_LIST_PER_Q - 1;
10762 }
10763 } else {
10764#if CC_VERY_LONG_SG_LIST
10765 /*
10766 * This is the last SG queue in the list of
10767 * allocated SG queues. If there are more
10768 * SG elements than will fit in the allocated
10769 * queues, then set the QCSG_SG_XFER_MORE flag.
10770 */
10771 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10772 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
10773 } else {
10774#endif /* CC_VERY_LONG_SG_LIST */
10775 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
10776#if CC_VERY_LONG_SG_LIST
10777 }
10778#endif /* CC_VERY_LONG_SG_LIST */
10779 sg_list_dwords = sg_entry_cnt << 1;
10780 if (i == 0) {
10781 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
10782 scsi_sg_q.sg_cur_list_cnt =
10783 sg_entry_cnt;
10784 } else {
10785 scsi_sg_q.sg_list_cnt =
10786 sg_entry_cnt - 1;
10787 scsi_sg_q.sg_cur_list_cnt =
10788 sg_entry_cnt - 1;
10789 }
10790 sg_entry_cnt = 0;
10791 }
10792 next_qp = AscReadLramByte(iop_base,
10793 (ushort)(q_addr +
10794 ASC_SCSIQ_B_FWD));
10795 scsi_sg_q.q_no = next_qp;
10796 q_addr = ASC_QNO_TO_QADDR(next_qp);
10797 AscMemWordCopyPtrToLram(iop_base,
10798 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
10799 (uchar *)&scsi_sg_q,
10800 sizeof(ASC_SG_LIST_Q) >> 1);
10801 AscMemDWordCopyPtrToLram(iop_base,
10802 q_addr + ASC_SGQ_LIST_BEG,
10803 (uchar *)&sg_head->
10804 sg_list[sg_index],
10805 sg_list_dwords);
10806 sg_index += ASC_SG_LIST_PER_Q;
10807 scsiq->next_sg_index = sg_index;
10808 }
10809 } else {
10810 scsiq->q1.cntl &= ~QC_SG_HEAD;
10811 }
10812 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
10813 scsiq->q1.data_addr = saved_data_addr;
10814 scsiq->q1.data_cnt = saved_data_cnt;
10815 return (sta);
10816}
10817
10818static int
10819AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
10820{
10821 PortAddr iop_base;
10822 uchar free_q_head;
10823 uchar next_qp;
10824 uchar tid_no;
10825 uchar target_ix;
10826 int sta;
10827
10828 iop_base = asc_dvc->iop_base;
10829 target_ix = scsiq->q2.target_ix;
10830 tid_no = ASC_TIX_TO_TID(target_ix);
10831 sta = 0;
10832 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
10833 if (n_q_required > 1) {
10834 next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head,
10835 (uchar)n_q_required);
10836 if (next_qp != ASC_QLINK_END) {
10837 asc_dvc->last_q_shortage = 0;
10838 scsiq->sg_head->queue_cnt = n_q_required - 1;
10839 scsiq->q1.q_no = free_q_head;
10840 sta = AscPutReadySgListQueue(asc_dvc, scsiq,
10841 free_q_head);
10842 }
10843 } else if (n_q_required == 1) {
10844 next_qp = AscAllocFreeQueue(iop_base, free_q_head);
10845 if (next_qp != ASC_QLINK_END) {
10846 scsiq->q1.q_no = free_q_head;
10847 sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head);
10848 }
10849 }
10850 if (sta == 1) {
10851 AscPutVarFreeQHead(iop_base, next_qp);
10852 asc_dvc->cur_total_qng += n_q_required;
10853 asc_dvc->cur_dvc_qng[tid_no]++;
10854 }
10855 return sta;
10856}
10857
10858#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
10859static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
10860 INQUIRY,
10861 REQUEST_SENSE,
10862 READ_CAPACITY,
10863 READ_TOC,
10864 MODE_SELECT,
10865 MODE_SENSE,
10866 MODE_SELECT_10,
10867 MODE_SENSE_10,
10868 0xFF,
10869 0xFF,
10870 0xFF,
10871 0xFF,
10872 0xFF,
10873 0xFF,
10874 0xFF,
10875 0xFF
10876};
10877
10878static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
10879{
10880 PortAddr iop_base;
10881 int sta;
10882 int n_q_required;
10883 int disable_syn_offset_one_fix;
10884 int i;
10885 ASC_PADDR addr;
10886 ushort sg_entry_cnt = 0;
10887 ushort sg_entry_cnt_minus_one = 0;
10888 uchar target_ix;
10889 uchar tid_no;
10890 uchar sdtr_data;
10891 uchar extra_bytes;
10892 uchar scsi_cmd;
10893 uchar disable_cmd;
10894 ASC_SG_HEAD *sg_head;
10895 ASC_DCNT data_cnt;
10896
10897 iop_base = asc_dvc->iop_base;
10898 sg_head = scsiq->sg_head;
10899 if (asc_dvc->err_code != 0)
10900 return (ERR);
10901 scsiq->q1.q_no = 0;
10902 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
10903 scsiq->q1.extra_bytes = 0;
10904 }
10905 sta = 0;
10906 target_ix = scsiq->q2.target_ix;
10907 tid_no = ASC_TIX_TO_TID(target_ix);
10908 n_q_required = 1;
10909 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
10910 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
10911 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
10912 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10913 AscMsgOutSDTR(asc_dvc,
10914 asc_dvc->
10915 sdtr_period_tbl[(sdtr_data >> 4) &
10916 (uchar)(asc_dvc->
10917 max_sdtr_index -
10918 1)],
10919 (uchar)(sdtr_data & (uchar)
10920 ASC_SYN_MAX_OFFSET));
10921 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
10922 }
10923 }
10924 if (asc_dvc->in_critical_cnt != 0) {
10925 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
10926 return (ERR);
10927 }
10928 asc_dvc->in_critical_cnt++;
10929 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10930 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
10931 asc_dvc->in_critical_cnt--;
10932 return (ERR);
10933 }
10934#if !CC_VERY_LONG_SG_LIST
10935 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10936 asc_dvc->in_critical_cnt--;
10937 return (ERR);
10938 }
10939#endif /* !CC_VERY_LONG_SG_LIST */
10940 if (sg_entry_cnt == 1) {
10941 scsiq->q1.data_addr =
10942 (ADV_PADDR)sg_head->sg_list[0].addr;
10943 scsiq->q1.data_cnt =
10944 (ADV_DCNT)sg_head->sg_list[0].bytes;
10945 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
10946 }
10947 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
10948 }
10949 scsi_cmd = scsiq->cdbptr[0];
10950 disable_syn_offset_one_fix = FALSE;
10951 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
10952 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
10953 if (scsiq->q1.cntl & QC_SG_HEAD) {
10954 data_cnt = 0;
10955 for (i = 0; i < sg_entry_cnt; i++) {
10956 data_cnt +=
10957 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
10958 bytes);
10959 }
10960 } else {
10961 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
10962 }
10963 if (data_cnt != 0UL) {
10964 if (data_cnt < 512UL) {
10965 disable_syn_offset_one_fix = TRUE;
10966 } else {
10967 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
10968 i++) {
10969 disable_cmd =
10970 _syn_offset_one_disable_cmd[i];
10971 if (disable_cmd == 0xFF) {
10972 break;
10973 }
10974 if (scsi_cmd == disable_cmd) {
10975 disable_syn_offset_one_fix =
10976 TRUE;
10977 break;
10978 }
10979 }
10980 }
10981 }
10982 }
10983 if (disable_syn_offset_one_fix) {
10984 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10985 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
10986 ASC_TAG_FLAG_DISABLE_DISCONNECT);
10987 } else {
10988 scsiq->q2.tag_code &= 0x27;
10989 }
10990 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10991 if (asc_dvc->bug_fix_cntl) {
10992 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10993 if ((scsi_cmd == READ_6) ||
10994 (scsi_cmd == READ_10)) {
10995 addr =
10996 (ADV_PADDR)le32_to_cpu(sg_head->
10997 sg_list
10998 [sg_entry_cnt_minus_one].
10999 addr) +
11000 (ADV_DCNT)le32_to_cpu(sg_head->
11001 sg_list
11002 [sg_entry_cnt_minus_one].
11003 bytes);
11004 extra_bytes =
11005 (uchar)((ushort)addr & 0x0003);
11006 if ((extra_bytes != 0)
11007 &&
11008 ((scsiq->q2.
11009 tag_code &
11010 ASC_TAG_FLAG_EXTRA_BYTES)
11011 == 0)) {
11012 scsiq->q2.tag_code |=
11013 ASC_TAG_FLAG_EXTRA_BYTES;
11014 scsiq->q1.extra_bytes =
11015 extra_bytes;
11016 data_cnt =
11017 le32_to_cpu(sg_head->
11018 sg_list
11019 [sg_entry_cnt_minus_one].
11020 bytes);
11021 data_cnt -=
11022 (ASC_DCNT) extra_bytes;
11023 sg_head->
11024 sg_list
11025 [sg_entry_cnt_minus_one].
11026 bytes =
11027 cpu_to_le32(data_cnt);
11028 }
11029 }
11030 }
11031 }
11032 sg_head->entry_to_copy = sg_head->entry_cnt;
11033#if CC_VERY_LONG_SG_LIST
11034 /*
11035 * Set the sg_entry_cnt to the maximum possible. The rest of
11036 * the SG elements will be copied when the RISC completes the
11037 * SG elements that fit and halts.
11038 */
11039 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
11040 sg_entry_cnt = ASC_MAX_SG_LIST;
11041 }
11042#endif /* CC_VERY_LONG_SG_LIST */
11043 n_q_required = AscSgListToQueue(sg_entry_cnt);
11044 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
11045 (uint) n_q_required)
11046 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11047 if ((sta =
11048 AscSendScsiQueue(asc_dvc, scsiq,
11049 n_q_required)) == 1) {
11050 asc_dvc->in_critical_cnt--;
11051 return (sta);
11052 }
11053 }
11054 } else {
11055 if (asc_dvc->bug_fix_cntl) {
11056 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11057 if ((scsi_cmd == READ_6) ||
11058 (scsi_cmd == READ_10)) {
11059 addr =
11060 le32_to_cpu(scsiq->q1.data_addr) +
11061 le32_to_cpu(scsiq->q1.data_cnt);
11062 extra_bytes =
11063 (uchar)((ushort)addr & 0x0003);
11064 if ((extra_bytes != 0)
11065 &&
11066 ((scsiq->q2.
11067 tag_code &
11068 ASC_TAG_FLAG_EXTRA_BYTES)
11069 == 0)) {
11070 data_cnt =
11071 le32_to_cpu(scsiq->q1.
11072 data_cnt);
11073 if (((ushort)data_cnt & 0x01FF)
11074 == 0) {
11075 scsiq->q2.tag_code |=
11076 ASC_TAG_FLAG_EXTRA_BYTES;
11077 data_cnt -= (ASC_DCNT)
11078 extra_bytes;
11079 scsiq->q1.data_cnt =
11080 cpu_to_le32
11081 (data_cnt);
11082 scsiq->q1.extra_bytes =
11083 extra_bytes;
11084 }
11085 }
11086 }
11087 }
11088 }
11089 n_q_required = 1;
11090 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
11091 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11092 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11093 n_q_required)) == 1) {
11094 asc_dvc->in_critical_cnt--;
11095 return (sta);
11096 }
11097 }
11098 }
11099 asc_dvc->in_critical_cnt--;
11100 return (sta);
11101}
11102
11103/*
11104 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
11105 *
11106 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
11107 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
11108 * RISC to notify it a new command is ready to be executed.
11109 *
11110 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
11111 * set to SCSI_MAX_RETRY.
11112 *
11113 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
11114 * for DMA addresses or math operations are byte swapped to little-endian
11115 * order.
11116 *
11117 * Return:
11118 * ADV_SUCCESS(1) - The request was successfully queued.
11119 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
11120 * request completes.
11121 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
11122 * host IC error.
11123 */
11124static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
11125{
11126 AdvPortAddr iop_base;
11127 ADV_DCNT req_size;
11128 ADV_PADDR req_paddr;
11129 ADV_CARR_T *new_carrp;
11130
11131 /*
11132 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
11133 */
11134 if (scsiq->target_id > ADV_MAX_TID) {
11135 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
11136 scsiq->done_status = QD_WITH_ERROR;
11137 return ADV_ERROR;
11138 }
11139
11140 iop_base = asc_dvc->iop_base;
11141
11142 /*
11143 * Allocate a carrier ensuring at least one carrier always
11144 * remains on the freelist and initialize fields.
11145 */
11146 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
11147 return ADV_BUSY;
11148 }
11149 asc_dvc->carr_freelist = (ADV_CARR_T *)
11150 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
11151 asc_dvc->carr_pending_cnt++;
11152
11153 /*
11154 * Set the carrier to be a stopper by setting 'next_vpa'
11155 * to the stopper value. The current stopper will be changed
11156 * below to point to the new stopper.
11157 */
11158 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
11159
11160 /*
11161 * Clear the ADV_SCSI_REQ_Q done flag.
11162 */
11163 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
11164
11165 req_size = sizeof(ADV_SCSI_REQ_Q);
11166 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
11167 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
11168
11169 BUG_ON(req_paddr & 31);
11170 BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q));
11171
11172 /* Wait for assertion before making little-endian */
11173 req_paddr = cpu_to_le32(req_paddr);
11174
11175 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
11176 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
11177 scsiq->scsiq_rptr = req_paddr;
11178
11179 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
11180 /*
11181 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
11182 * order during initialization.
11183 */
11184 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
11185
11186 /*
11187 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
11188 * the microcode. The newly allocated stopper will become the new
11189 * stopper.
11190 */
11191 asc_dvc->icq_sp->areq_vpa = req_paddr;
11192
11193 /*
11194 * Set the 'next_vpa' pointer for the old stopper to be the
11195 * physical address of the new stopper. The RISC can only
11196 * follow physical addresses.
11197 */
11198 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
11199
11200 /*
11201 * Set the host adapter stopper pointer to point to the new carrier.
11202 */
11203 asc_dvc->icq_sp = new_carrp;
11204
11205 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
11206 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
11207 /*
11208 * Tickle the RISC to tell it to read its Command Queue Head pointer.
11209 */
11210 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
11211 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
11212 /*
11213 * Clear the tickle value. In the ASC-3550 the RISC flag
11214 * command 'clr_tickle_a' does not work unless the host
11215 * value is cleared.
11216 */
11217 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
11218 ADV_TICKLE_NOP);
11219 }
11220 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
11221 /*
11222 * Notify the RISC a carrier is ready by writing the physical
11223 * address of the new carrier stopper to the COMMA register.
11224 */
11225 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
11226 le32_to_cpu(new_carrp->carr_pa));
11227 }
11228
11229 return ADV_SUCCESS;
11230}
11231
11232/*
11233 * Execute a single 'Scsi_Cmnd'.
11234 *
11235 * The function 'done' is called when the request has been completed.
11236 *
11237 * Scsi_Cmnd:
11238 *
11239 * host - board controlling device
11240 * device - device to send command
11241 * target - target of device
11242 * lun - lun of device
11243 * cmd_len - length of SCSI CDB
11244 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
11245 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
11246 *
11247 * if (use_sg == 0) {
11248 * request_buffer - buffer address for request
11249 * request_bufflen - length of request buffer
11250 * } else {
11251 * request_buffer - pointer to scatterlist structure
11252 * }
11253 *
11254 * sense_buffer - sense command buffer
11255 *
11256 * result (4 bytes of an int):
11257 * Byte Meaning
11258 * 0 SCSI Status Byte Code
11259 * 1 SCSI One Byte Message Code
11260 * 2 Host Error Code
11261 * 3 Mid-Level Error Code
11262 *
11263 * host driver fields:
11264 * SCp - Scsi_Pointer used for command processing status
11265 * scsi_done - used to save caller's done function
11266 * host_scribble - used for pointer to another struct scsi_cmnd
11267 *
11268 * If this function returns ASC_NOERROR the request will be completed
11269 * from the interrupt handler.
11270 *
11271 * If this function returns ASC_ERROR the host error code has been set,
11272 * and the called must call asc_scsi_done.
11273 *
11274 * If ASC_BUSY is returned the request will be returned to the midlayer
11275 * and re-tried later.
11276 */
11277static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
11278{
Matthew Wilcox41d24932007-10-02 21:55:24 -040011279 int ret, err_code;
11280 asc_board_t *boardp = ASC_BOARDP(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040011281
Matthew Wilcox41d24932007-10-02 21:55:24 -040011282 ASC_DBG1(1, "asc_execute_scsi_cmnd: scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011283
11284 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011285 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox05848b62007-10-02 21:55:25 -040011286 struct asc_scsi_q asc_scsi_q;
Matthew Wilcox51219352007-10-02 21:55:22 -040011287
Matthew Wilcox41d24932007-10-02 21:55:24 -040011288 /* asc_build_req() can not return ASC_BUSY. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040011289 ret = asc_build_req(boardp, scp, &asc_scsi_q);
11290 if (ret == ASC_ERROR) {
Matthew Wilcox51219352007-10-02 21:55:22 -040011291 ASC_STATS(scp->device->host, build_error);
11292 return ASC_ERROR;
11293 }
11294
Matthew Wilcox41d24932007-10-02 21:55:24 -040011295 ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
Matthew Wilcox05848b62007-10-02 21:55:25 -040011296 kfree(asc_scsi_q.sg_head);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011297 err_code = asc_dvc->err_code;
Matthew Wilcox51219352007-10-02 21:55:22 -040011298 } else {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011299 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
11300 ADV_SCSI_REQ_Q *adv_scsiqp;
Matthew Wilcox51219352007-10-02 21:55:22 -040011301
Matthew Wilcox51219352007-10-02 21:55:22 -040011302 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
11303 case ASC_NOERROR:
11304 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
11305 "ASC_NOERROR\n");
11306 break;
11307 case ASC_BUSY:
11308 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
11309 "ASC_BUSY\n");
11310 /*
11311 * The asc_stats fields 'adv_build_noreq' and
11312 * 'adv_build_nosg' count wide board busy conditions.
11313 * They are updated in adv_build_req and
11314 * adv_get_sglist, respectively.
11315 */
11316 return ASC_BUSY;
11317 case ASC_ERROR:
11318 default:
11319 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
11320 "ASC_ERROR\n");
11321 ASC_STATS(scp->device->host, build_error);
11322 return ASC_ERROR;
11323 }
11324
Matthew Wilcox41d24932007-10-02 21:55:24 -040011325 ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp);
11326 err_code = adv_dvc->err_code;
11327 }
11328
11329 switch (ret) {
11330 case ASC_NOERROR:
11331 ASC_STATS(scp->device->host, exe_noerror);
11332 /*
11333 * Increment monotonically increasing per device
11334 * successful request counter. Wrapping doesn't matter.
11335 */
11336 boardp->reqcnt[scp->device->id]++;
11337 ASC_DBG(1, "asc_execute_scsi_cmnd: ExeScsiQueue(), "
11338 "ASC_NOERROR\n");
11339 break;
11340 case ASC_BUSY:
11341 ASC_STATS(scp->device->host, exe_busy);
11342 break;
11343 case ASC_ERROR:
11344 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11345 "ASC_ERROR, err_code 0x%x\n", boardp->id, err_code);
11346 ASC_STATS(scp->device->host, exe_error);
11347 scp->result = HOST_BYTE(DID_ERROR);
11348 break;
11349 default:
11350 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11351 "unknown, err_code 0x%x\n", boardp->id, err_code);
11352 ASC_STATS(scp->device->host, exe_unknown);
11353 scp->result = HOST_BYTE(DID_ERROR);
11354 break;
Matthew Wilcox51219352007-10-02 21:55:22 -040011355 }
11356
11357 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
11358 return ret;
11359}
11360
11361/*
11362 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
11363 *
11364 * This function always returns 0. Command return status is saved
11365 * in the 'scp' result field.
11366 */
11367static int
11368advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
11369{
11370 struct Scsi_Host *shost = scp->device->host;
11371 asc_board_t *boardp = ASC_BOARDP(shost);
11372 unsigned long flags;
11373 int asc_res, result = 0;
11374
11375 ASC_STATS(shost, queuecommand);
11376 scp->scsi_done = done;
11377
11378 /*
11379 * host_lock taken by mid-level prior to call, but need
11380 * to protect against own ISR
11381 */
11382 spin_lock_irqsave(&boardp->lock, flags);
11383 asc_res = asc_execute_scsi_cmnd(scp);
11384 spin_unlock_irqrestore(&boardp->lock, flags);
11385
11386 switch (asc_res) {
11387 case ASC_NOERROR:
11388 break;
11389 case ASC_BUSY:
11390 result = SCSI_MLQUEUE_HOST_BUSY;
11391 break;
11392 case ASC_ERROR:
11393 default:
11394 asc_scsi_done(scp);
11395 break;
11396 }
11397
11398 return result;
11399}
11400
11401static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
11402{
11403 PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11404 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
11405 return inpw(eisa_cfg_iop);
11406}
11407
11408/*
11409 * Return the BIOS address of the adapter at the specified
11410 * I/O port and with the specified bus type.
11411 */
11412static unsigned short __devinit
11413AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
11414{
11415 unsigned short cfg_lsw;
11416 unsigned short bios_addr;
11417
11418 /*
11419 * The PCI BIOS is re-located by the motherboard BIOS. Because
11420 * of this the driver can not determine where a PCI BIOS is
11421 * loaded and executes.
11422 */
11423 if (bus_type & ASC_IS_PCI)
11424 return 0;
11425
11426 if ((bus_type & ASC_IS_EISA) != 0) {
11427 cfg_lsw = AscGetEisaChipCfg(iop_base);
11428 cfg_lsw &= 0x000F;
11429 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
11430 return bios_addr;
11431 }
11432
11433 cfg_lsw = AscGetChipCfgLsw(iop_base);
11434
11435 /*
11436 * ISA PnP uses the top bit as the 32K BIOS flag
11437 */
11438 if (bus_type == ASC_IS_ISAPNP)
11439 cfg_lsw &= 0x7FFF;
11440 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
11441 return bios_addr;
11442}
11443
11444static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
11445{
11446 ushort cfg_lsw;
11447
11448 if (AscGetChipScsiID(iop_base) == new_host_id) {
11449 return (new_host_id);
11450 }
11451 cfg_lsw = AscGetChipCfgLsw(iop_base);
11452 cfg_lsw &= 0xF8FF;
11453 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
11454 AscSetChipCfgLsw(iop_base, cfg_lsw);
11455 return (AscGetChipScsiID(iop_base));
11456}
11457
11458static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
11459{
11460 unsigned char sc;
11461
11462 AscSetBank(iop_base, 1);
11463 sc = inp(iop_base + IOP_REG_SC);
11464 AscSetBank(iop_base, 0);
11465 return sc;
11466}
11467
11468static unsigned char __devinit
11469AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
11470{
11471 if (bus_type & ASC_IS_EISA) {
11472 PortAddr eisa_iop;
11473 unsigned char revision;
11474 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11475 (PortAddr) ASC_EISA_REV_IOP_MASK;
11476 revision = inp(eisa_iop);
11477 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
11478 }
11479 return AscGetChipVerNo(iop_base);
11480}
11481
11482static void __devinit AscToggleIRQAct(PortAddr iop_base)
11483{
11484 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
11485 AscSetChipStatus(iop_base, 0);
11486 return;
11487}
11488
11489static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
11490{
11491 ushort cfg_lsw;
11492 uchar chip_irq;
11493
11494 if ((bus_type & ASC_IS_EISA) != 0) {
11495 cfg_lsw = AscGetEisaChipCfg(iop_base);
11496 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
11497 if ((chip_irq == 13) || (chip_irq > 15)) {
11498 return (0);
11499 }
11500 return (chip_irq);
11501 }
11502 if ((bus_type & ASC_IS_VL) != 0) {
11503 cfg_lsw = AscGetChipCfgLsw(iop_base);
11504 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
11505 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
11506 return (0);
11507 }
11508 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
11509 }
11510 cfg_lsw = AscGetChipCfgLsw(iop_base);
11511 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
11512 if (chip_irq == 3)
11513 chip_irq += (uchar)2;
11514 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
11515}
11516
11517static uchar __devinit
11518AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
11519{
11520 ushort cfg_lsw;
11521
11522 if ((bus_type & ASC_IS_VL) != 0) {
11523 if (irq_no != 0) {
11524 if ((irq_no < ASC_MIN_IRQ_NO)
11525 || (irq_no > ASC_MAX_IRQ_NO)) {
11526 irq_no = 0;
11527 } else {
11528 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
11529 }
11530 }
11531 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
11532 cfg_lsw |= (ushort)0x0010;
11533 AscSetChipCfgLsw(iop_base, cfg_lsw);
11534 AscToggleIRQAct(iop_base);
11535 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
11536 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
11537 AscSetChipCfgLsw(iop_base, cfg_lsw);
11538 AscToggleIRQAct(iop_base);
11539 return (AscGetChipIRQ(iop_base, bus_type));
11540 }
11541 if ((bus_type & (ASC_IS_ISA)) != 0) {
11542 if (irq_no == 15)
11543 irq_no -= (uchar)2;
11544 irq_no -= (uchar)ASC_MIN_IRQ_NO;
11545 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
11546 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
11547 AscSetChipCfgLsw(iop_base, cfg_lsw);
11548 return (AscGetChipIRQ(iop_base, bus_type));
11549 }
11550 return (0);
11551}
11552
11553#ifdef CONFIG_ISA
11554static void __devinit AscEnableIsaDma(uchar dma_channel)
11555{
11556 if (dma_channel < 4) {
11557 outp(0x000B, (ushort)(0xC0 | dma_channel));
11558 outp(0x000A, dma_channel);
11559 } else if (dma_channel < 8) {
11560 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
11561 outp(0x00D4, (ushort)(dma_channel - 4));
11562 }
11563 return;
11564}
11565#endif /* CONFIG_ISA */
11566
11567static int AscStopQueueExe(PortAddr iop_base)
11568{
11569 int count = 0;
11570
11571 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
11572 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
11573 ASC_STOP_REQ_RISC_STOP);
11574 do {
11575 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
11576 ASC_STOP_ACK_RISC_STOP) {
11577 return (1);
11578 }
11579 mdelay(100);
11580 } while (count++ < 20);
11581 }
11582 return (0);
11583}
11584
11585static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
11586{
11587 if (bus_type & ASC_IS_ISA)
11588 return ASC_MAX_ISA_DMA_COUNT;
11589 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
11590 return ASC_MAX_VL_DMA_COUNT;
11591 return ASC_MAX_PCI_DMA_COUNT;
11592}
11593
11594#ifdef CONFIG_ISA
11595static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
11596{
11597 ushort channel;
11598
11599 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
11600 if (channel == 0x03)
11601 return (0);
11602 else if (channel == 0x00)
11603 return (7);
11604 return (channel + 4);
11605}
11606
11607static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
11608{
11609 ushort cfg_lsw;
11610 uchar value;
11611
11612 if ((dma_channel >= 5) && (dma_channel <= 7)) {
11613 if (dma_channel == 7)
11614 value = 0x00;
11615 else
11616 value = dma_channel - 4;
11617 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
11618 cfg_lsw |= value;
11619 AscSetChipCfgLsw(iop_base, cfg_lsw);
11620 return (AscGetIsaDmaChannel(iop_base));
11621 }
11622 return 0;
11623}
11624
11625static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
11626{
11627 uchar speed_value;
11628
11629 AscSetBank(iop_base, 1);
11630 speed_value = AscReadChipDmaSpeed(iop_base);
11631 speed_value &= 0x07;
11632 AscSetBank(iop_base, 0);
11633 return speed_value;
11634}
11635
11636static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
11637{
11638 speed_value &= 0x07;
11639 AscSetBank(iop_base, 1);
11640 AscWriteChipDmaSpeed(iop_base, speed_value);
11641 AscSetBank(iop_base, 0);
11642 return AscGetIsaDmaSpeed(iop_base);
11643}
11644#endif /* CONFIG_ISA */
11645
11646static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
11647{
11648 int i;
11649 PortAddr iop_base;
11650 ushort warn_code;
11651 uchar chip_version;
11652
11653 iop_base = asc_dvc->iop_base;
11654 warn_code = 0;
11655 asc_dvc->err_code = 0;
11656 if ((asc_dvc->bus_type &
11657 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
11658 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
11659 }
11660 AscSetChipControl(iop_base, CC_HALT);
11661 AscSetChipStatus(iop_base, 0);
11662 asc_dvc->bug_fix_cntl = 0;
11663 asc_dvc->pci_fix_asyn_xfer = 0;
11664 asc_dvc->pci_fix_asyn_xfer_always = 0;
11665 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
11666 asc_dvc->sdtr_done = 0;
11667 asc_dvc->cur_total_qng = 0;
11668 asc_dvc->is_in_int = 0;
11669 asc_dvc->in_critical_cnt = 0;
11670 asc_dvc->last_q_shortage = 0;
11671 asc_dvc->use_tagged_qng = 0;
11672 asc_dvc->no_scam = 0;
11673 asc_dvc->unit_not_ready = 0;
11674 asc_dvc->queue_full_or_busy = 0;
11675 asc_dvc->redo_scam = 0;
11676 asc_dvc->res2 = 0;
11677 asc_dvc->host_init_sdtr_index = 0;
11678 asc_dvc->cfg->can_tagged_qng = 0;
11679 asc_dvc->cfg->cmd_qng_enabled = 0;
11680 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
11681 asc_dvc->init_sdtr = 0;
11682 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
11683 asc_dvc->scsi_reset_wait = 3;
11684 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
11685 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
11686 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
11687 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
11688 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
11689 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
11690 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
11691 ASC_LIB_VERSION_MINOR;
11692 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
11693 asc_dvc->cfg->chip_version = chip_version;
11694 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
11695 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
11696 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
11697 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
11698 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
11699 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
11700 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
11701 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
11702 asc_dvc->max_sdtr_index = 7;
11703 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
11704 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
11705 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
11706 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
11707 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
11708 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
11709 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
11710 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
11711 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
11712 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
11713 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
11714 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
11715 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
11716 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
11717 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
11718 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
11719 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
11720 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
11721 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
11722 asc_dvc->max_sdtr_index = 15;
11723 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
11724 AscSetExtraControl(iop_base,
11725 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11726 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
11727 AscSetExtraControl(iop_base,
11728 (SEC_ACTIVE_NEGATE |
11729 SEC_ENABLE_FILTER));
11730 }
11731 }
11732 if (asc_dvc->bus_type == ASC_IS_PCI) {
11733 AscSetExtraControl(iop_base,
11734 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11735 }
11736
11737 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
11738#ifdef CONFIG_ISA
11739 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
11740 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
11741 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
11742 asc_dvc->bus_type = ASC_IS_ISAPNP;
11743 }
11744 asc_dvc->cfg->isa_dma_channel =
11745 (uchar)AscGetIsaDmaChannel(iop_base);
11746 }
11747#endif /* CONFIG_ISA */
11748 for (i = 0; i <= ASC_MAX_TID; i++) {
11749 asc_dvc->cur_dvc_qng[i] = 0;
11750 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
11751 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
11752 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
11753 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
11754 }
11755 return warn_code;
11756}
11757
11758static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
11759{
11760 int retry;
11761
11762 for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) {
11763 unsigned char read_back;
11764 AscSetChipEEPCmd(iop_base, cmd_reg);
11765 mdelay(1);
11766 read_back = AscGetChipEEPCmd(iop_base);
11767 if (read_back == cmd_reg)
11768 return 1;
11769 }
11770 return 0;
11771}
11772
11773static void __devinit AscWaitEEPRead(void)
11774{
11775 mdelay(1);
11776}
11777
11778static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
11779{
11780 ushort read_wval;
11781 uchar cmd_reg;
11782
11783 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11784 AscWaitEEPRead();
11785 cmd_reg = addr | ASC_EEP_CMD_READ;
11786 AscWriteEEPCmdReg(iop_base, cmd_reg);
11787 AscWaitEEPRead();
11788 read_wval = AscGetChipEEPData(iop_base);
11789 AscWaitEEPRead();
11790 return read_wval;
11791}
11792
11793static ushort __devinit
11794AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11795{
11796 ushort wval;
11797 ushort sum;
11798 ushort *wbuf;
11799 int cfg_beg;
11800 int cfg_end;
11801 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11802 int s_addr;
11803
11804 wbuf = (ushort *)cfg_buf;
11805 sum = 0;
11806 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
11807 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11808 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11809 sum += *wbuf;
11810 }
11811 if (bus_type & ASC_IS_VL) {
11812 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11813 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11814 } else {
11815 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11816 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11817 }
11818 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11819 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11820 if (s_addr <= uchar_end_in_config) {
11821 /*
11822 * Swap all char fields - must unswap bytes already swapped
11823 * by AscReadEEPWord().
11824 */
11825 *wbuf = le16_to_cpu(wval);
11826 } else {
11827 /* Don't swap word field at the end - cntl field. */
11828 *wbuf = wval;
11829 }
11830 sum += wval; /* Checksum treats all EEPROM data as words. */
11831 }
11832 /*
11833 * Read the checksum word which will be compared against 'sum'
11834 * by the caller. Word field already swapped.
11835 */
11836 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11837 return sum;
11838}
11839
11840static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
11841{
11842 PortAddr iop_base;
11843 ushort q_addr;
11844 ushort saved_word;
11845 int sta;
11846
11847 iop_base = asc_dvc->iop_base;
11848 sta = 0;
11849 q_addr = ASC_QNO_TO_QADDR(241);
11850 saved_word = AscReadLramWord(iop_base, q_addr);
11851 AscSetChipLramAddr(iop_base, q_addr);
11852 AscSetChipLramData(iop_base, 0x55AA);
11853 mdelay(10);
11854 AscSetChipLramAddr(iop_base, q_addr);
11855 if (AscGetChipLramData(iop_base) == 0x55AA) {
11856 sta = 1;
11857 AscWriteLramWord(iop_base, q_addr, saved_word);
11858 }
11859 return (sta);
11860}
11861
11862static void __devinit AscWaitEEPWrite(void)
11863{
11864 mdelay(20);
11865 return;
11866}
11867
11868static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
11869{
11870 ushort read_back;
11871 int retry;
11872
11873 retry = 0;
11874 while (TRUE) {
11875 AscSetChipEEPData(iop_base, data_reg);
11876 mdelay(1);
11877 read_back = AscGetChipEEPData(iop_base);
11878 if (read_back == data_reg) {
11879 return (1);
11880 }
11881 if (retry++ > ASC_EEP_MAX_RETRY) {
11882 return (0);
11883 }
11884 }
11885}
11886
11887static ushort __devinit
11888AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
11889{
11890 ushort read_wval;
11891
11892 read_wval = AscReadEEPWord(iop_base, addr);
11893 if (read_wval != word_val) {
11894 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
11895 AscWaitEEPRead();
11896 AscWriteEEPDataReg(iop_base, word_val);
11897 AscWaitEEPRead();
11898 AscWriteEEPCmdReg(iop_base,
11899 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
11900 AscWaitEEPWrite();
11901 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11902 AscWaitEEPRead();
11903 return (AscReadEEPWord(iop_base, addr));
11904 }
11905 return (read_wval);
11906}
11907
11908static int __devinit
11909AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11910{
11911 int n_error;
11912 ushort *wbuf;
11913 ushort word;
11914 ushort sum;
11915 int s_addr;
11916 int cfg_beg;
11917 int cfg_end;
11918 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11919
11920 wbuf = (ushort *)cfg_buf;
11921 n_error = 0;
11922 sum = 0;
11923 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11924 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11925 sum += *wbuf;
11926 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11927 n_error++;
11928 }
11929 }
11930 if (bus_type & ASC_IS_VL) {
11931 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11932 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11933 } else {
11934 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11935 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11936 }
11937 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11938 if (s_addr <= uchar_end_in_config) {
11939 /*
11940 * This is a char field. Swap char fields before they are
11941 * swapped again by AscWriteEEPWord().
11942 */
11943 word = cpu_to_le16(*wbuf);
11944 if (word !=
11945 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11946 n_error++;
11947 }
11948 } else {
11949 /* Don't swap word field at the end - cntl field. */
11950 if (*wbuf !=
11951 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11952 n_error++;
11953 }
11954 }
11955 sum += *wbuf; /* Checksum calculated from word values. */
11956 }
11957 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11958 *wbuf = sum;
11959 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11960 n_error++;
11961 }
11962
11963 /* Read EEPROM back again. */
11964 wbuf = (ushort *)cfg_buf;
11965 /*
11966 * Read two config words; Byte-swapping done by AscReadEEPWord().
11967 */
11968 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11969 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11970 n_error++;
11971 }
11972 }
11973 if (bus_type & ASC_IS_VL) {
11974 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11975 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11976 } else {
11977 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11978 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11979 }
11980 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11981 if (s_addr <= uchar_end_in_config) {
11982 /*
11983 * Swap all char fields. Must unswap bytes already swapped
11984 * by AscReadEEPWord().
11985 */
11986 word =
11987 le16_to_cpu(AscReadEEPWord
11988 (iop_base, (uchar)s_addr));
11989 } else {
11990 /* Don't swap word field at the end - cntl field. */
11991 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11992 }
11993 if (*wbuf != word) {
11994 n_error++;
11995 }
11996 }
11997 /* Read checksum; Byte swapping not needed. */
11998 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11999 n_error++;
12000 }
12001 return n_error;
12002}
12003
12004static int __devinit
12005AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
12006{
12007 int retry;
12008 int n_error;
12009
12010 retry = 0;
12011 while (TRUE) {
12012 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
12013 bus_type)) == 0) {
12014 break;
12015 }
12016 if (++retry > ASC_EEP_MAX_RETRY) {
12017 break;
12018 }
12019 }
12020 return n_error;
12021}
12022
12023static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
12024{
12025 ASCEEP_CONFIG eep_config_buf;
12026 ASCEEP_CONFIG *eep_config;
12027 PortAddr iop_base;
12028 ushort chksum;
12029 ushort warn_code;
12030 ushort cfg_msw, cfg_lsw;
12031 int i;
12032 int write_eep = 0;
12033
12034 iop_base = asc_dvc->iop_base;
12035 warn_code = 0;
12036 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
12037 AscStopQueueExe(iop_base);
12038 if ((AscStopChip(iop_base) == FALSE) ||
12039 (AscGetChipScsiCtrl(iop_base) != 0)) {
12040 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
12041 AscResetChipAndScsiBus(asc_dvc);
12042 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
12043 }
12044 if (AscIsChipHalted(iop_base) == FALSE) {
12045 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
12046 return (warn_code);
12047 }
12048 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
12049 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
12050 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
12051 return (warn_code);
12052 }
12053 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
12054 cfg_msw = AscGetChipCfgMsw(iop_base);
12055 cfg_lsw = AscGetChipCfgLsw(iop_base);
12056 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12057 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
12058 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12059 AscSetChipCfgMsw(iop_base, cfg_msw);
12060 }
12061 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
12062 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
12063 if (chksum == 0) {
12064 chksum = 0xaa55;
12065 }
12066 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12067 warn_code |= ASC_WARN_AUTO_CONFIG;
12068 if (asc_dvc->cfg->chip_version == 3) {
12069 if (eep_config->cfg_lsw != cfg_lsw) {
12070 warn_code |= ASC_WARN_EEPROM_RECOVER;
12071 eep_config->cfg_lsw =
12072 AscGetChipCfgLsw(iop_base);
12073 }
12074 if (eep_config->cfg_msw != cfg_msw) {
12075 warn_code |= ASC_WARN_EEPROM_RECOVER;
12076 eep_config->cfg_msw =
12077 AscGetChipCfgMsw(iop_base);
12078 }
12079 }
12080 }
12081 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
12082 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
12083 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
12084 eep_config->chksum);
12085 if (chksum != eep_config->chksum) {
12086 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
12087 ASC_CHIP_VER_PCI_ULTRA_3050) {
12088 ASC_DBG(1,
12089 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
12090 eep_config->init_sdtr = 0xFF;
12091 eep_config->disc_enable = 0xFF;
12092 eep_config->start_motor = 0xFF;
12093 eep_config->use_cmd_qng = 0;
12094 eep_config->max_total_qng = 0xF0;
12095 eep_config->max_tag_qng = 0x20;
12096 eep_config->cntl = 0xBFFF;
12097 ASC_EEP_SET_CHIP_ID(eep_config, 7);
12098 eep_config->no_scam = 0;
12099 eep_config->adapter_info[0] = 0;
12100 eep_config->adapter_info[1] = 0;
12101 eep_config->adapter_info[2] = 0;
12102 eep_config->adapter_info[3] = 0;
12103 eep_config->adapter_info[4] = 0;
12104 /* Indicate EEPROM-less board. */
12105 eep_config->adapter_info[5] = 0xBB;
12106 } else {
12107 ASC_PRINT
12108 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
12109 write_eep = 1;
12110 warn_code |= ASC_WARN_EEPROM_CHKSUM;
12111 }
12112 }
12113 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
12114 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
12115 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
12116 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
12117 asc_dvc->start_motor = eep_config->start_motor;
12118 asc_dvc->dvc_cntl = eep_config->cntl;
12119 asc_dvc->no_scam = eep_config->no_scam;
12120 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
12121 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
12122 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
12123 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
12124 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
12125 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
12126 if (!AscTestExternalLram(asc_dvc)) {
12127 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
12128 ASC_IS_PCI_ULTRA)) {
12129 eep_config->max_total_qng =
12130 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
12131 eep_config->max_tag_qng =
12132 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
12133 } else {
12134 eep_config->cfg_msw |= 0x0800;
12135 cfg_msw |= 0x0800;
12136 AscSetChipCfgMsw(iop_base, cfg_msw);
12137 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
12138 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
12139 }
12140 } else {
12141 }
12142 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
12143 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
12144 }
12145 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
12146 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
12147 }
12148 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
12149 eep_config->max_tag_qng = eep_config->max_total_qng;
12150 }
12151 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
12152 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
12153 }
12154 asc_dvc->max_total_qng = eep_config->max_total_qng;
12155 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
12156 eep_config->use_cmd_qng) {
12157 eep_config->disc_enable = eep_config->use_cmd_qng;
12158 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12159 }
12160 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
12161 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
12162 }
12163 ASC_EEP_SET_CHIP_ID(eep_config,
12164 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
12165 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
12166 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
12167 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
12168 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
12169 }
12170
12171 for (i = 0; i <= ASC_MAX_TID; i++) {
12172 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
12173 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
12174 asc_dvc->cfg->sdtr_period_offset[i] =
12175 (uchar)(ASC_DEF_SDTR_OFFSET |
12176 (asc_dvc->host_init_sdtr_index << 4));
12177 }
12178 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
12179 if (write_eep) {
12180 if ((i = AscSetEEPConfig(iop_base, eep_config,
12181 asc_dvc->bus_type)) != 0) {
12182 ASC_PRINT1
12183 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
12184 i);
12185 } else {
12186 ASC_PRINT
12187 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
12188 }
12189 }
12190 return (warn_code);
12191}
12192
12193static int __devinit AscInitGetConfig(asc_board_t *boardp)
12194{
12195 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
12196 unsigned short warn_code = 0;
12197
12198 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
12199 if (asc_dvc->err_code != 0)
12200 return asc_dvc->err_code;
12201
12202 if (AscFindSignature(asc_dvc->iop_base)) {
12203 warn_code |= AscInitAscDvcVar(asc_dvc);
12204 warn_code |= AscInitFromEEP(asc_dvc);
12205 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
12206 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
12207 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
12208 } else {
12209 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12210 }
12211
12212 switch (warn_code) {
12213 case 0: /* No error */
12214 break;
12215 case ASC_WARN_IO_PORT_ROTATE:
12216 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
12217 "modified\n", boardp->id);
12218 break;
12219 case ASC_WARN_AUTO_CONFIG:
12220 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
12221 "switch enabled\n", boardp->id);
12222 break;
12223 case ASC_WARN_EEPROM_CHKSUM:
12224 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
12225 "error\n", boardp->id);
12226 break;
12227 case ASC_WARN_IRQ_MODIFIED:
12228 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
12229 boardp->id);
12230 break;
12231 case ASC_WARN_CMD_QNG_CONFLICT:
12232 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
12233 "w/o disconnects\n", boardp->id);
12234 break;
12235 default:
12236 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
12237 "0x%x\n", boardp->id, warn_code);
12238 break;
12239 }
12240
12241 if (asc_dvc->err_code != 0) {
12242 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
12243 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12244 asc_dvc->err_code);
12245 }
12246
12247 return asc_dvc->err_code;
12248}
12249
12250static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
12251{
12252 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
12253 PortAddr iop_base = asc_dvc->iop_base;
12254 unsigned short cfg_msw;
12255 unsigned short warn_code = 0;
12256
12257 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12258 if (asc_dvc->err_code != 0)
12259 return asc_dvc->err_code;
12260 if (!AscFindSignature(asc_dvc->iop_base)) {
12261 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12262 return asc_dvc->err_code;
12263 }
12264
12265 cfg_msw = AscGetChipCfgMsw(iop_base);
12266 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12267 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
12268 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12269 AscSetChipCfgMsw(iop_base, cfg_msw);
12270 }
12271 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12272 asc_dvc->cfg->cmd_qng_enabled) {
12273 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12274 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12275 }
12276 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12277 warn_code |= ASC_WARN_AUTO_CONFIG;
12278 }
12279 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
12280 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
12281 != asc_dvc->irq_no) {
12282 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
12283 }
12284 }
12285#ifdef CONFIG_PCI
12286 if (asc_dvc->bus_type & ASC_IS_PCI) {
12287 cfg_msw &= 0xFFC0;
12288 AscSetChipCfgMsw(iop_base, cfg_msw);
12289 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12290 } else {
12291 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
12292 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
12293 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12294 asc_dvc->bug_fix_cntl |=
12295 ASC_BUG_FIX_ASYN_USE_SYN;
12296 }
12297 }
12298 } else
12299#endif /* CONFIG_PCI */
12300 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12301 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12302 == ASC_CHIP_VER_ASYN_BUG) {
12303 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12304 }
12305 }
12306 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12307 asc_dvc->cfg->chip_scsi_id) {
12308 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12309 }
12310#ifdef CONFIG_ISA
12311 if (asc_dvc->bus_type & ASC_IS_ISA) {
12312 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12313 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12314 }
12315#endif /* CONFIG_ISA */
12316
12317 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12318
12319 switch (warn_code) {
12320 case 0: /* No error. */
12321 break;
12322 case ASC_WARN_IO_PORT_ROTATE:
12323 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
12324 "modified\n", boardp->id);
12325 break;
12326 case ASC_WARN_AUTO_CONFIG:
12327 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
12328 "switch enabled\n", boardp->id);
12329 break;
12330 case ASC_WARN_EEPROM_CHKSUM:
12331 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
12332 "error\n", boardp->id);
12333 break;
12334 case ASC_WARN_IRQ_MODIFIED:
12335 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
12336 boardp->id);
12337 break;
12338 case ASC_WARN_CMD_QNG_CONFLICT:
12339 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
12340 "disconnects\n",
12341 boardp->id);
12342 break;
12343 default:
12344 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
12345 "0x%x\n", boardp->id, warn_code);
12346 break;
12347 }
12348
12349 if (asc_dvc->err_code != 0) {
12350 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
12351 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12352 asc_dvc->err_code);
12353 }
12354
12355 return asc_dvc->err_code;
12356}
12357
12358/*
12359 * EEPROM Configuration.
12360 *
12361 * All drivers should use this structure to set the default EEPROM
12362 * configuration. The BIOS now uses this structure when it is built.
12363 * Additional structure information can be found in a_condor.h where
12364 * the structure is defined.
12365 *
12366 * The *_Field_IsChar structs are needed to correct for endianness.
12367 * These values are read from the board 16 bits at a time directly
12368 * into the structs. Because some fields are char, the values will be
12369 * in the wrong order. The *_Field_IsChar tells when to flip the
12370 * bytes. Data read and written to PCI memory is automatically swapped
12371 * on big-endian platforms so char fields read as words are actually being
12372 * unswapped on big-endian platforms.
12373 */
12374static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
12375 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
12376 0x0000, /* cfg_msw */
12377 0xFFFF, /* disc_enable */
12378 0xFFFF, /* wdtr_able */
12379 0xFFFF, /* sdtr_able */
12380 0xFFFF, /* start_motor */
12381 0xFFFF, /* tagqng_able */
12382 0xFFFF, /* bios_scan */
12383 0, /* scam_tolerant */
12384 7, /* adapter_scsi_id */
12385 0, /* bios_boot_delay */
12386 3, /* scsi_reset_delay */
12387 0, /* bios_id_lun */
12388 0, /* termination */
12389 0, /* reserved1 */
12390 0xFFE7, /* bios_ctrl */
12391 0xFFFF, /* ultra_able */
12392 0, /* reserved2 */
12393 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
12394 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12395 0, /* dvc_cntl */
12396 0, /* bug_fix */
12397 0, /* serial_number_word1 */
12398 0, /* serial_number_word2 */
12399 0, /* serial_number_word3 */
12400 0, /* check_sum */
12401 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12402 , /* oem_name[16] */
12403 0, /* dvc_err_code */
12404 0, /* adv_err_code */
12405 0, /* adv_err_addr */
12406 0, /* saved_dvc_err_code */
12407 0, /* saved_adv_err_code */
12408 0, /* saved_adv_err_addr */
12409 0 /* num_of_err */
12410};
12411
12412static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
12413 0, /* cfg_lsw */
12414 0, /* cfg_msw */
12415 0, /* -disc_enable */
12416 0, /* wdtr_able */
12417 0, /* sdtr_able */
12418 0, /* start_motor */
12419 0, /* tagqng_able */
12420 0, /* bios_scan */
12421 0, /* scam_tolerant */
12422 1, /* adapter_scsi_id */
12423 1, /* bios_boot_delay */
12424 1, /* scsi_reset_delay */
12425 1, /* bios_id_lun */
12426 1, /* termination */
12427 1, /* reserved1 */
12428 0, /* bios_ctrl */
12429 0, /* ultra_able */
12430 0, /* reserved2 */
12431 1, /* max_host_qng */
12432 1, /* max_dvc_qng */
12433 0, /* dvc_cntl */
12434 0, /* bug_fix */
12435 0, /* serial_number_word1 */
12436 0, /* serial_number_word2 */
12437 0, /* serial_number_word3 */
12438 0, /* check_sum */
12439 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12440 , /* oem_name[16] */
12441 0, /* dvc_err_code */
12442 0, /* adv_err_code */
12443 0, /* adv_err_addr */
12444 0, /* saved_dvc_err_code */
12445 0, /* saved_adv_err_code */
12446 0, /* saved_adv_err_addr */
12447 0 /* num_of_err */
12448};
12449
12450static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
12451 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12452 0x0000, /* 01 cfg_msw */
12453 0xFFFF, /* 02 disc_enable */
12454 0xFFFF, /* 03 wdtr_able */
12455 0x4444, /* 04 sdtr_speed1 */
12456 0xFFFF, /* 05 start_motor */
12457 0xFFFF, /* 06 tagqng_able */
12458 0xFFFF, /* 07 bios_scan */
12459 0, /* 08 scam_tolerant */
12460 7, /* 09 adapter_scsi_id */
12461 0, /* bios_boot_delay */
12462 3, /* 10 scsi_reset_delay */
12463 0, /* bios_id_lun */
12464 0, /* 11 termination_se */
12465 0, /* termination_lvd */
12466 0xFFE7, /* 12 bios_ctrl */
12467 0x4444, /* 13 sdtr_speed2 */
12468 0x4444, /* 14 sdtr_speed3 */
12469 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12470 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12471 0, /* 16 dvc_cntl */
12472 0x4444, /* 17 sdtr_speed4 */
12473 0, /* 18 serial_number_word1 */
12474 0, /* 19 serial_number_word2 */
12475 0, /* 20 serial_number_word3 */
12476 0, /* 21 check_sum */
12477 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12478 , /* 22-29 oem_name[16] */
12479 0, /* 30 dvc_err_code */
12480 0, /* 31 adv_err_code */
12481 0, /* 32 adv_err_addr */
12482 0, /* 33 saved_dvc_err_code */
12483 0, /* 34 saved_adv_err_code */
12484 0, /* 35 saved_adv_err_addr */
12485 0, /* 36 reserved */
12486 0, /* 37 reserved */
12487 0, /* 38 reserved */
12488 0, /* 39 reserved */
12489 0, /* 40 reserved */
12490 0, /* 41 reserved */
12491 0, /* 42 reserved */
12492 0, /* 43 reserved */
12493 0, /* 44 reserved */
12494 0, /* 45 reserved */
12495 0, /* 46 reserved */
12496 0, /* 47 reserved */
12497 0, /* 48 reserved */
12498 0, /* 49 reserved */
12499 0, /* 50 reserved */
12500 0, /* 51 reserved */
12501 0, /* 52 reserved */
12502 0, /* 53 reserved */
12503 0, /* 54 reserved */
12504 0, /* 55 reserved */
12505 0, /* 56 cisptr_lsw */
12506 0, /* 57 cisprt_msw */
12507 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12508 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
12509 0, /* 60 reserved */
12510 0, /* 61 reserved */
12511 0, /* 62 reserved */
12512 0 /* 63 reserved */
12513};
12514
12515static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
12516 0, /* 00 cfg_lsw */
12517 0, /* 01 cfg_msw */
12518 0, /* 02 disc_enable */
12519 0, /* 03 wdtr_able */
12520 0, /* 04 sdtr_speed1 */
12521 0, /* 05 start_motor */
12522 0, /* 06 tagqng_able */
12523 0, /* 07 bios_scan */
12524 0, /* 08 scam_tolerant */
12525 1, /* 09 adapter_scsi_id */
12526 1, /* bios_boot_delay */
12527 1, /* 10 scsi_reset_delay */
12528 1, /* bios_id_lun */
12529 1, /* 11 termination_se */
12530 1, /* termination_lvd */
12531 0, /* 12 bios_ctrl */
12532 0, /* 13 sdtr_speed2 */
12533 0, /* 14 sdtr_speed3 */
12534 1, /* 15 max_host_qng */
12535 1, /* max_dvc_qng */
12536 0, /* 16 dvc_cntl */
12537 0, /* 17 sdtr_speed4 */
12538 0, /* 18 serial_number_word1 */
12539 0, /* 19 serial_number_word2 */
12540 0, /* 20 serial_number_word3 */
12541 0, /* 21 check_sum */
12542 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12543 , /* 22-29 oem_name[16] */
12544 0, /* 30 dvc_err_code */
12545 0, /* 31 adv_err_code */
12546 0, /* 32 adv_err_addr */
12547 0, /* 33 saved_dvc_err_code */
12548 0, /* 34 saved_adv_err_code */
12549 0, /* 35 saved_adv_err_addr */
12550 0, /* 36 reserved */
12551 0, /* 37 reserved */
12552 0, /* 38 reserved */
12553 0, /* 39 reserved */
12554 0, /* 40 reserved */
12555 0, /* 41 reserved */
12556 0, /* 42 reserved */
12557 0, /* 43 reserved */
12558 0, /* 44 reserved */
12559 0, /* 45 reserved */
12560 0, /* 46 reserved */
12561 0, /* 47 reserved */
12562 0, /* 48 reserved */
12563 0, /* 49 reserved */
12564 0, /* 50 reserved */
12565 0, /* 51 reserved */
12566 0, /* 52 reserved */
12567 0, /* 53 reserved */
12568 0, /* 54 reserved */
12569 0, /* 55 reserved */
12570 0, /* 56 cisptr_lsw */
12571 0, /* 57 cisprt_msw */
12572 0, /* 58 subsysvid */
12573 0, /* 59 subsysid */
12574 0, /* 60 reserved */
12575 0, /* 61 reserved */
12576 0, /* 62 reserved */
12577 0 /* 63 reserved */
12578};
12579
12580static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
12581 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12582 0x0000, /* 01 cfg_msw */
12583 0xFFFF, /* 02 disc_enable */
12584 0xFFFF, /* 03 wdtr_able */
12585 0x5555, /* 04 sdtr_speed1 */
12586 0xFFFF, /* 05 start_motor */
12587 0xFFFF, /* 06 tagqng_able */
12588 0xFFFF, /* 07 bios_scan */
12589 0, /* 08 scam_tolerant */
12590 7, /* 09 adapter_scsi_id */
12591 0, /* bios_boot_delay */
12592 3, /* 10 scsi_reset_delay */
12593 0, /* bios_id_lun */
12594 0, /* 11 termination_se */
12595 0, /* termination_lvd */
12596 0xFFE7, /* 12 bios_ctrl */
12597 0x5555, /* 13 sdtr_speed2 */
12598 0x5555, /* 14 sdtr_speed3 */
12599 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12600 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12601 0, /* 16 dvc_cntl */
12602 0x5555, /* 17 sdtr_speed4 */
12603 0, /* 18 serial_number_word1 */
12604 0, /* 19 serial_number_word2 */
12605 0, /* 20 serial_number_word3 */
12606 0, /* 21 check_sum */
12607 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12608 , /* 22-29 oem_name[16] */
12609 0, /* 30 dvc_err_code */
12610 0, /* 31 adv_err_code */
12611 0, /* 32 adv_err_addr */
12612 0, /* 33 saved_dvc_err_code */
12613 0, /* 34 saved_adv_err_code */
12614 0, /* 35 saved_adv_err_addr */
12615 0, /* 36 reserved */
12616 0, /* 37 reserved */
12617 0, /* 38 reserved */
12618 0, /* 39 reserved */
12619 0, /* 40 reserved */
12620 0, /* 41 reserved */
12621 0, /* 42 reserved */
12622 0, /* 43 reserved */
12623 0, /* 44 reserved */
12624 0, /* 45 reserved */
12625 0, /* 46 reserved */
12626 0, /* 47 reserved */
12627 0, /* 48 reserved */
12628 0, /* 49 reserved */
12629 0, /* 50 reserved */
12630 0, /* 51 reserved */
12631 0, /* 52 reserved */
12632 0, /* 53 reserved */
12633 0, /* 54 reserved */
12634 0, /* 55 reserved */
12635 0, /* 56 cisptr_lsw */
12636 0, /* 57 cisprt_msw */
12637 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12638 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
12639 0, /* 60 reserved */
12640 0, /* 61 reserved */
12641 0, /* 62 reserved */
12642 0 /* 63 reserved */
12643};
12644
12645static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
12646 0, /* 00 cfg_lsw */
12647 0, /* 01 cfg_msw */
12648 0, /* 02 disc_enable */
12649 0, /* 03 wdtr_able */
12650 0, /* 04 sdtr_speed1 */
12651 0, /* 05 start_motor */
12652 0, /* 06 tagqng_able */
12653 0, /* 07 bios_scan */
12654 0, /* 08 scam_tolerant */
12655 1, /* 09 adapter_scsi_id */
12656 1, /* bios_boot_delay */
12657 1, /* 10 scsi_reset_delay */
12658 1, /* bios_id_lun */
12659 1, /* 11 termination_se */
12660 1, /* termination_lvd */
12661 0, /* 12 bios_ctrl */
12662 0, /* 13 sdtr_speed2 */
12663 0, /* 14 sdtr_speed3 */
12664 1, /* 15 max_host_qng */
12665 1, /* max_dvc_qng */
12666 0, /* 16 dvc_cntl */
12667 0, /* 17 sdtr_speed4 */
12668 0, /* 18 serial_number_word1 */
12669 0, /* 19 serial_number_word2 */
12670 0, /* 20 serial_number_word3 */
12671 0, /* 21 check_sum */
12672 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12673 , /* 22-29 oem_name[16] */
12674 0, /* 30 dvc_err_code */
12675 0, /* 31 adv_err_code */
12676 0, /* 32 adv_err_addr */
12677 0, /* 33 saved_dvc_err_code */
12678 0, /* 34 saved_adv_err_code */
12679 0, /* 35 saved_adv_err_addr */
12680 0, /* 36 reserved */
12681 0, /* 37 reserved */
12682 0, /* 38 reserved */
12683 0, /* 39 reserved */
12684 0, /* 40 reserved */
12685 0, /* 41 reserved */
12686 0, /* 42 reserved */
12687 0, /* 43 reserved */
12688 0, /* 44 reserved */
12689 0, /* 45 reserved */
12690 0, /* 46 reserved */
12691 0, /* 47 reserved */
12692 0, /* 48 reserved */
12693 0, /* 49 reserved */
12694 0, /* 50 reserved */
12695 0, /* 51 reserved */
12696 0, /* 52 reserved */
12697 0, /* 53 reserved */
12698 0, /* 54 reserved */
12699 0, /* 55 reserved */
12700 0, /* 56 cisptr_lsw */
12701 0, /* 57 cisprt_msw */
12702 0, /* 58 subsysvid */
12703 0, /* 59 subsysid */
12704 0, /* 60 reserved */
12705 0, /* 61 reserved */
12706 0, /* 62 reserved */
12707 0 /* 63 reserved */
12708};
12709
12710#ifdef CONFIG_PCI
12711/*
12712 * Wait for EEPROM command to complete
12713 */
12714static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
12715{
12716 int eep_delay_ms;
12717
12718 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
12719 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
12720 ASC_EEP_CMD_DONE) {
12721 break;
12722 }
12723 mdelay(1);
12724 }
12725 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
12726 0)
12727 BUG();
12728}
12729
12730/*
12731 * Read the EEPROM from specified location
12732 */
12733static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
12734{
12735 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12736 ASC_EEP_CMD_READ | eep_word_addr);
12737 AdvWaitEEPCmd(iop_base);
12738 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
12739}
12740
12741/*
12742 * Write the EEPROM from 'cfg_buf'.
12743 */
12744void __devinit
12745AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12746{
12747 ushort *wbuf;
12748 ushort addr, chksum;
12749 ushort *charfields;
12750
12751 wbuf = (ushort *)cfg_buf;
12752 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12753 chksum = 0;
12754
12755 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12756 AdvWaitEEPCmd(iop_base);
12757
12758 /*
12759 * Write EEPROM from word 0 to word 20.
12760 */
12761 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12762 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12763 ushort word;
12764
12765 if (*charfields++) {
12766 word = cpu_to_le16(*wbuf);
12767 } else {
12768 word = *wbuf;
12769 }
12770 chksum += *wbuf; /* Checksum is calculated from word values. */
12771 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12772 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12773 ASC_EEP_CMD_WRITE | addr);
12774 AdvWaitEEPCmd(iop_base);
12775 mdelay(ADV_EEP_DELAY_MS);
12776 }
12777
12778 /*
12779 * Write EEPROM checksum at word 21.
12780 */
12781 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12782 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12783 AdvWaitEEPCmd(iop_base);
12784 wbuf++;
12785 charfields++;
12786
12787 /*
12788 * Write EEPROM OEM name at words 22 to 29.
12789 */
12790 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12791 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12792 ushort word;
12793
12794 if (*charfields++) {
12795 word = cpu_to_le16(*wbuf);
12796 } else {
12797 word = *wbuf;
12798 }
12799 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12800 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12801 ASC_EEP_CMD_WRITE | addr);
12802 AdvWaitEEPCmd(iop_base);
12803 }
12804 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12805 AdvWaitEEPCmd(iop_base);
12806}
12807
12808/*
12809 * Write the EEPROM from 'cfg_buf'.
12810 */
12811void __devinit
12812AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12813{
12814 ushort *wbuf;
12815 ushort *charfields;
12816 ushort addr, chksum;
12817
12818 wbuf = (ushort *)cfg_buf;
12819 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12820 chksum = 0;
12821
12822 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12823 AdvWaitEEPCmd(iop_base);
12824
12825 /*
12826 * Write EEPROM from word 0 to word 20.
12827 */
12828 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12829 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12830 ushort word;
12831
12832 if (*charfields++) {
12833 word = cpu_to_le16(*wbuf);
12834 } else {
12835 word = *wbuf;
12836 }
12837 chksum += *wbuf; /* Checksum is calculated from word values. */
12838 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12839 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12840 ASC_EEP_CMD_WRITE | addr);
12841 AdvWaitEEPCmd(iop_base);
12842 mdelay(ADV_EEP_DELAY_MS);
12843 }
12844
12845 /*
12846 * Write EEPROM checksum at word 21.
12847 */
12848 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12849 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12850 AdvWaitEEPCmd(iop_base);
12851 wbuf++;
12852 charfields++;
12853
12854 /*
12855 * Write EEPROM OEM name at words 22 to 29.
12856 */
12857 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12858 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12859 ushort word;
12860
12861 if (*charfields++) {
12862 word = cpu_to_le16(*wbuf);
12863 } else {
12864 word = *wbuf;
12865 }
12866 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12867 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12868 ASC_EEP_CMD_WRITE | addr);
12869 AdvWaitEEPCmd(iop_base);
12870 }
12871 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12872 AdvWaitEEPCmd(iop_base);
12873}
12874
12875/*
12876 * Write the EEPROM from 'cfg_buf'.
12877 */
12878void __devinit
12879AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12880{
12881 ushort *wbuf;
12882 ushort *charfields;
12883 ushort addr, chksum;
12884
12885 wbuf = (ushort *)cfg_buf;
12886 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12887 chksum = 0;
12888
12889 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12890 AdvWaitEEPCmd(iop_base);
12891
12892 /*
12893 * Write EEPROM from word 0 to word 20.
12894 */
12895 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12896 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12897 ushort word;
12898
12899 if (*charfields++) {
12900 word = cpu_to_le16(*wbuf);
12901 } else {
12902 word = *wbuf;
12903 }
12904 chksum += *wbuf; /* Checksum is calculated from word values. */
12905 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12906 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12907 ASC_EEP_CMD_WRITE | addr);
12908 AdvWaitEEPCmd(iop_base);
12909 mdelay(ADV_EEP_DELAY_MS);
12910 }
12911
12912 /*
12913 * Write EEPROM checksum at word 21.
12914 */
12915 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12916 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12917 AdvWaitEEPCmd(iop_base);
12918 wbuf++;
12919 charfields++;
12920
12921 /*
12922 * Write EEPROM OEM name at words 22 to 29.
12923 */
12924 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12925 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12926 ushort word;
12927
12928 if (*charfields++) {
12929 word = cpu_to_le16(*wbuf);
12930 } else {
12931 word = *wbuf;
12932 }
12933 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12934 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12935 ASC_EEP_CMD_WRITE | addr);
12936 AdvWaitEEPCmd(iop_base);
12937 }
12938 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12939 AdvWaitEEPCmd(iop_base);
12940}
12941
12942/*
12943 * Read EEPROM configuration into the specified buffer.
12944 *
12945 * Return a checksum based on the EEPROM configuration read.
12946 */
12947static ushort __devinit
12948AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12949{
12950 ushort wval, chksum;
12951 ushort *wbuf;
12952 int eep_addr;
12953 ushort *charfields;
12954
12955 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12956 wbuf = (ushort *)cfg_buf;
12957 chksum = 0;
12958
12959 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12960 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12961 wval = AdvReadEEPWord(iop_base, eep_addr);
12962 chksum += wval; /* Checksum is calculated from word values. */
12963 if (*charfields++) {
12964 *wbuf = le16_to_cpu(wval);
12965 } else {
12966 *wbuf = wval;
12967 }
12968 }
12969 /* Read checksum word. */
12970 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12971 wbuf++;
12972 charfields++;
12973
12974 /* Read rest of EEPROM not covered by the checksum. */
12975 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12976 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12977 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12978 if (*charfields++) {
12979 *wbuf = le16_to_cpu(*wbuf);
12980 }
12981 }
12982 return chksum;
12983}
12984
12985/*
12986 * Read EEPROM configuration into the specified buffer.
12987 *
12988 * Return a checksum based on the EEPROM configuration read.
12989 */
12990static ushort __devinit
12991AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12992{
12993 ushort wval, chksum;
12994 ushort *wbuf;
12995 int eep_addr;
12996 ushort *charfields;
12997
12998 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12999 wbuf = (ushort *)cfg_buf;
13000 chksum = 0;
13001
13002 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13003 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13004 wval = AdvReadEEPWord(iop_base, eep_addr);
13005 chksum += wval; /* Checksum is calculated from word values. */
13006 if (*charfields++) {
13007 *wbuf = le16_to_cpu(wval);
13008 } else {
13009 *wbuf = wval;
13010 }
13011 }
13012 /* Read checksum word. */
13013 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13014 wbuf++;
13015 charfields++;
13016
13017 /* Read rest of EEPROM not covered by the checksum. */
13018 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13019 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13020 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13021 if (*charfields++) {
13022 *wbuf = le16_to_cpu(*wbuf);
13023 }
13024 }
13025 return chksum;
13026}
13027
13028/*
13029 * Read EEPROM configuration into the specified buffer.
13030 *
13031 * Return a checksum based on the EEPROM configuration read.
13032 */
13033static ushort __devinit
13034AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
13035{
13036 ushort wval, chksum;
13037 ushort *wbuf;
13038 int eep_addr;
13039 ushort *charfields;
13040
13041 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13042 wbuf = (ushort *)cfg_buf;
13043 chksum = 0;
13044
13045 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13046 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13047 wval = AdvReadEEPWord(iop_base, eep_addr);
13048 chksum += wval; /* Checksum is calculated from word values. */
13049 if (*charfields++) {
13050 *wbuf = le16_to_cpu(wval);
13051 } else {
13052 *wbuf = wval;
13053 }
13054 }
13055 /* Read checksum word. */
13056 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13057 wbuf++;
13058 charfields++;
13059
13060 /* Read rest of EEPROM not covered by the checksum. */
13061 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13062 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13063 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13064 if (*charfields++) {
13065 *wbuf = le16_to_cpu(*wbuf);
13066 }
13067 }
13068 return chksum;
13069}
13070
13071/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070013072 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13073 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13074 * all of this is done.
13075 *
13076 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13077 *
13078 * For a non-fatal error return a warning code. If there are no warnings
13079 * then 0 is returned.
13080 *
13081 * Note: Chip is stopped on entry.
13082 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013083static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013084{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013085 AdvPortAddr iop_base;
13086 ushort warn_code;
13087 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013088
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013089 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013090
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013091 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013092
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013093 /*
13094 * Read the board's EEPROM configuration.
13095 *
13096 * Set default values if a bad checksum is found.
13097 */
13098 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
13099 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013100
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013101 /*
13102 * Set EEPROM default values.
13103 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013104 memcpy(&eep_config, &Default_3550_EEPROM_Config,
13105 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013106
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013107 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013108 * Assume the 6 byte board serial number that was read from
13109 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013110 */
13111 eep_config.serial_number_word3 =
13112 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013113
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013114 eep_config.serial_number_word2 =
13115 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013116
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013117 eep_config.serial_number_word1 =
13118 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013119
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013120 AdvSet3550EEPConfig(iop_base, &eep_config);
13121 }
13122 /*
13123 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13124 * EEPROM configuration that was read.
13125 *
13126 * This is the mapping of EEPROM fields to Adv Library fields.
13127 */
13128 asc_dvc->wdtr_able = eep_config.wdtr_able;
13129 asc_dvc->sdtr_able = eep_config.sdtr_able;
13130 asc_dvc->ultra_able = eep_config.ultra_able;
13131 asc_dvc->tagqng_able = eep_config.tagqng_able;
13132 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13133 asc_dvc->max_host_qng = eep_config.max_host_qng;
13134 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13135 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13136 asc_dvc->start_motor = eep_config.start_motor;
13137 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13138 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13139 asc_dvc->no_scam = eep_config.scam_tolerant;
13140 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13141 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13142 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013144 /*
13145 * Set the host maximum queuing (max. 253, min. 16) and the per device
13146 * maximum queuing (max. 63, min. 4).
13147 */
13148 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13149 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13150 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13151 /* If the value is zero, assume it is uninitialized. */
13152 if (eep_config.max_host_qng == 0) {
13153 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13154 } else {
13155 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13156 }
13157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013158
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013159 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13160 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13161 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13162 /* If the value is zero, assume it is uninitialized. */
13163 if (eep_config.max_dvc_qng == 0) {
13164 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13165 } else {
13166 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13167 }
13168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013169
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013170 /*
13171 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13172 * set 'max_dvc_qng' to 'max_host_qng'.
13173 */
13174 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13175 eep_config.max_dvc_qng = eep_config.max_host_qng;
13176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013177
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013178 /*
13179 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13180 * values based on possibly adjusted EEPROM values.
13181 */
13182 asc_dvc->max_host_qng = eep_config.max_host_qng;
13183 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013184
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013185 /*
13186 * If the EEPROM 'termination' field is set to automatic (0), then set
13187 * the ADV_DVC_CFG 'termination' field to automatic also.
13188 *
13189 * If the termination is specified with a non-zero 'termination'
13190 * value check that a legal value is set and set the ADV_DVC_CFG
13191 * 'termination' field appropriately.
13192 */
13193 if (eep_config.termination == 0) {
13194 asc_dvc->cfg->termination = 0; /* auto termination */
13195 } else {
13196 /* Enable manual control with low off / high off. */
13197 if (eep_config.termination == 1) {
13198 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013200 /* Enable manual control with low off / high on. */
13201 } else if (eep_config.termination == 2) {
13202 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013203
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013204 /* Enable manual control with low on / high on. */
13205 } else if (eep_config.termination == 3) {
13206 asc_dvc->cfg->termination =
13207 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
13208 } else {
13209 /*
13210 * The EEPROM 'termination' field contains a bad value. Use
13211 * automatic termination instead.
13212 */
13213 asc_dvc->cfg->termination = 0;
13214 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13215 }
13216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013217
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013218 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013219}
13220
13221/*
13222 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13223 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13224 * all of this is done.
13225 *
13226 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13227 *
13228 * For a non-fatal error return a warning code. If there are no warnings
13229 * then 0 is returned.
13230 *
13231 * Note: Chip is stopped on entry.
13232 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013233static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013234{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013235 AdvPortAddr iop_base;
13236 ushort warn_code;
13237 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013238 uchar tid, termination;
13239 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013241 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013242
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013243 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013244
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013245 /*
13246 * Read the board's EEPROM configuration.
13247 *
13248 * Set default values if a bad checksum is found.
13249 */
13250 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13251 eep_config.check_sum) {
13252 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013254 /*
13255 * Set EEPROM default values.
13256 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013257 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13258 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013259
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013260 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013261 * Assume the 6 byte board serial number that was read from
13262 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013263 */
13264 eep_config.serial_number_word3 =
13265 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013266
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013267 eep_config.serial_number_word2 =
13268 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013269
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013270 eep_config.serial_number_word1 =
13271 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013272
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013273 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13274 }
13275 /*
13276 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13277 * EEPROM configuration that was read.
13278 *
13279 * This is the mapping of EEPROM fields to Adv Library fields.
13280 */
13281 asc_dvc->wdtr_able = eep_config.wdtr_able;
13282 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13283 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13284 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13285 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13286 asc_dvc->tagqng_able = eep_config.tagqng_able;
13287 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13288 asc_dvc->max_host_qng = eep_config.max_host_qng;
13289 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13290 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13291 asc_dvc->start_motor = eep_config.start_motor;
13292 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13293 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13294 asc_dvc->no_scam = eep_config.scam_tolerant;
13295 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13296 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13297 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013298
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013299 /*
13300 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13301 * are set, then set an 'sdtr_able' bit for it.
13302 */
13303 asc_dvc->sdtr_able = 0;
13304 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13305 if (tid == 0) {
13306 sdtr_speed = asc_dvc->sdtr_speed1;
13307 } else if (tid == 4) {
13308 sdtr_speed = asc_dvc->sdtr_speed2;
13309 } else if (tid == 8) {
13310 sdtr_speed = asc_dvc->sdtr_speed3;
13311 } else if (tid == 12) {
13312 sdtr_speed = asc_dvc->sdtr_speed4;
13313 }
13314 if (sdtr_speed & ADV_MAX_TID) {
13315 asc_dvc->sdtr_able |= (1 << tid);
13316 }
13317 sdtr_speed >>= 4;
13318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013319
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013320 /*
13321 * Set the host maximum queuing (max. 253, min. 16) and the per device
13322 * maximum queuing (max. 63, min. 4).
13323 */
13324 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13325 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13326 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13327 /* If the value is zero, assume it is uninitialized. */
13328 if (eep_config.max_host_qng == 0) {
13329 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13330 } else {
13331 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13332 }
13333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013334
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013335 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13336 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13337 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13338 /* If the value is zero, assume it is uninitialized. */
13339 if (eep_config.max_dvc_qng == 0) {
13340 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13341 } else {
13342 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13343 }
13344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013345
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013346 /*
13347 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13348 * set 'max_dvc_qng' to 'max_host_qng'.
13349 */
13350 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13351 eep_config.max_dvc_qng = eep_config.max_host_qng;
13352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013353
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013354 /*
13355 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13356 * values based on possibly adjusted EEPROM values.
13357 */
13358 asc_dvc->max_host_qng = eep_config.max_host_qng;
13359 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013360
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013361 /*
13362 * If the EEPROM 'termination' field is set to automatic (0), then set
13363 * the ADV_DVC_CFG 'termination' field to automatic also.
13364 *
13365 * If the termination is specified with a non-zero 'termination'
13366 * value check that a legal value is set and set the ADV_DVC_CFG
13367 * 'termination' field appropriately.
13368 */
13369 if (eep_config.termination_se == 0) {
13370 termination = 0; /* auto termination for SE */
13371 } else {
13372 /* Enable manual control with low off / high off. */
13373 if (eep_config.termination_se == 1) {
13374 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013375
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013376 /* Enable manual control with low off / high on. */
13377 } else if (eep_config.termination_se == 2) {
13378 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013379
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013380 /* Enable manual control with low on / high on. */
13381 } else if (eep_config.termination_se == 3) {
13382 termination = TERM_SE;
13383 } else {
13384 /*
13385 * The EEPROM 'termination_se' field contains a bad value.
13386 * Use automatic termination instead.
13387 */
13388 termination = 0;
13389 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13390 }
13391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013392
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013393 if (eep_config.termination_lvd == 0) {
13394 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13395 } else {
13396 /* Enable manual control with low off / high off. */
13397 if (eep_config.termination_lvd == 1) {
13398 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013399
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013400 /* Enable manual control with low off / high on. */
13401 } else if (eep_config.termination_lvd == 2) {
13402 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013403
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013404 /* Enable manual control with low on / high on. */
13405 } else if (eep_config.termination_lvd == 3) {
13406 asc_dvc->cfg->termination = termination | TERM_LVD;
13407 } else {
13408 /*
13409 * The EEPROM 'termination_lvd' field contains a bad value.
13410 * Use automatic termination instead.
13411 */
13412 asc_dvc->cfg->termination = termination;
13413 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13414 }
13415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013416
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013417 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013418}
13419
13420/*
13421 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13422 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13423 * all of this is done.
13424 *
13425 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13426 *
13427 * For a non-fatal error return a warning code. If there are no warnings
13428 * then 0 is returned.
13429 *
13430 * Note: Chip is stopped on entry.
13431 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013432static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013433{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013434 AdvPortAddr iop_base;
13435 ushort warn_code;
13436 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013437 uchar tid, termination;
13438 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013439
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013440 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013442 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013443
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013444 /*
13445 * Read the board's EEPROM configuration.
13446 *
13447 * Set default values if a bad checksum is found.
13448 */
13449 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13450 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013451 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013452 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013453
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013454 /*
13455 * Set EEPROM default values.
13456 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013457 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13458 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013459
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013460 if (PCI_FUNC(pdev->devfn) != 0) {
13461 u8 ints;
13462 /*
13463 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13464 * and old Mac system booting problem. The Expansion
13465 * ROM must be disabled in Function 1 for these systems
13466 */
13467 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13468 /*
13469 * Clear the INTAB (bit 11) if the GPIO 0 input
13470 * indicates the Function 1 interrupt line is wired
13471 * to INTB.
13472 *
13473 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13474 * 1 - Function 1 interrupt line wired to INT A.
13475 * 0 - Function 1 interrupt line wired to INT B.
13476 *
13477 * Note: Function 0 is always wired to INTA.
13478 * Put all 5 GPIO bits in input mode and then read
13479 * their input values.
13480 */
13481 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13482 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13483 if ((ints & 0x01) == 0)
13484 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013486
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013487 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013488 * Assume the 6 byte board serial number that was read from
13489 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013490 */
13491 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013492 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013493 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013494 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013495 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013496 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013497
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013498 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013500
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013501 /*
13502 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13503 * EEPROM configuration that was read.
13504 *
13505 * This is the mapping of EEPROM fields to Adv Library fields.
13506 */
13507 asc_dvc->wdtr_able = eep_config.wdtr_able;
13508 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13509 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13510 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13511 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13512 asc_dvc->ppr_able = 0;
13513 asc_dvc->tagqng_able = eep_config.tagqng_able;
13514 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13515 asc_dvc->max_host_qng = eep_config.max_host_qng;
13516 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13517 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13518 asc_dvc->start_motor = eep_config.start_motor;
13519 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13520 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13521 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013522
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013523 /*
13524 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13525 * are set, then set an 'sdtr_able' bit for it.
13526 */
13527 asc_dvc->sdtr_able = 0;
13528 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13529 if (tid == 0) {
13530 sdtr_speed = asc_dvc->sdtr_speed1;
13531 } else if (tid == 4) {
13532 sdtr_speed = asc_dvc->sdtr_speed2;
13533 } else if (tid == 8) {
13534 sdtr_speed = asc_dvc->sdtr_speed3;
13535 } else if (tid == 12) {
13536 sdtr_speed = asc_dvc->sdtr_speed4;
13537 }
13538 if (sdtr_speed & ASC_MAX_TID) {
13539 asc_dvc->sdtr_able |= (1 << tid);
13540 }
13541 sdtr_speed >>= 4;
13542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013543
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013544 /*
13545 * Set the host maximum queuing (max. 253, min. 16) and the per device
13546 * maximum queuing (max. 63, min. 4).
13547 */
13548 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13549 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13550 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13551 /* If the value is zero, assume it is uninitialized. */
13552 if (eep_config.max_host_qng == 0) {
13553 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13554 } else {
13555 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13556 }
13557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013558
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013559 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13560 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13561 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13562 /* If the value is zero, assume it is uninitialized. */
13563 if (eep_config.max_dvc_qng == 0) {
13564 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13565 } else {
13566 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13567 }
13568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013569
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013570 /*
13571 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13572 * set 'max_dvc_qng' to 'max_host_qng'.
13573 */
13574 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13575 eep_config.max_dvc_qng = eep_config.max_host_qng;
13576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013577
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013578 /*
13579 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13580 * values based on possibly adjusted EEPROM values.
13581 */
13582 asc_dvc->max_host_qng = eep_config.max_host_qng;
13583 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013584
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013585 /*
13586 * If the EEPROM 'termination' field is set to automatic (0), then set
13587 * the ASC_DVC_CFG 'termination' field to automatic also.
13588 *
13589 * If the termination is specified with a non-zero 'termination'
13590 * value check that a legal value is set and set the ASC_DVC_CFG
13591 * 'termination' field appropriately.
13592 */
13593 if (eep_config.termination_se == 0) {
13594 termination = 0; /* auto termination for SE */
13595 } else {
13596 /* Enable manual control with low off / high off. */
13597 if (eep_config.termination_se == 1) {
13598 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013599
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013600 /* Enable manual control with low off / high on. */
13601 } else if (eep_config.termination_se == 2) {
13602 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013603
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013604 /* Enable manual control with low on / high on. */
13605 } else if (eep_config.termination_se == 3) {
13606 termination = TERM_SE;
13607 } else {
13608 /*
13609 * The EEPROM 'termination_se' field contains a bad value.
13610 * Use automatic termination instead.
13611 */
13612 termination = 0;
13613 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13614 }
13615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013616
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013617 if (eep_config.termination_lvd == 0) {
13618 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13619 } else {
13620 /* Enable manual control with low off / high off. */
13621 if (eep_config.termination_lvd == 1) {
13622 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013623
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013624 /* Enable manual control with low off / high on. */
13625 } else if (eep_config.termination_lvd == 2) {
13626 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013627
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013628 /* Enable manual control with low on / high on. */
13629 } else if (eep_config.termination_lvd == 3) {
13630 asc_dvc->cfg->termination = termination | TERM_LVD;
13631 } else {
13632 /*
13633 * The EEPROM 'termination_lvd' field contains a bad value.
13634 * Use automatic termination instead.
13635 */
13636 asc_dvc->cfg->termination = termination;
13637 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13638 }
13639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013640
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013641 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013642}
13643
13644/*
Matthew Wilcox51219352007-10-02 21:55:22 -040013645 * Initialize the ADV_DVC_VAR structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013646 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013647 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013648 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013649 * For a non-fatal error return a warning code. If there are no warnings
13650 * then 0 is returned.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013651 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013652static int __devinit
13653AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013654{
Matthew Wilcox51219352007-10-02 21:55:22 -040013655 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
13656 unsigned short warn_code = 0;
13657 AdvPortAddr iop_base = asc_dvc->iop_base;
13658 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013659 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013660
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013661 asc_dvc->err_code = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040013662
13663 /*
13664 * Save the state of the PCI Configuration Command Register
13665 * "Parity Error Response Control" Bit. If the bit is clear (0),
13666 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13667 * DMA parity errors.
13668 */
13669 asc_dvc->cfg->control_flag = 0;
13670 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
13671 if ((cmd & PCI_COMMAND_PARITY) == 0)
13672 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
13673
13674 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
13675 ADV_LIB_VERSION_MINOR;
13676 asc_dvc->cfg->chip_version =
13677 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
13678
13679 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
13680 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13681 (ushort)ADV_CHIP_ID_BYTE);
13682
13683 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
13684 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13685 (ushort)ADV_CHIP_ID_WORD);
13686
13687 /*
13688 * Reset the chip to start and allow register writes.
13689 */
13690 if (AdvFindSignature(iop_base) == 0) {
13691 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13692 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013693 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013694 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013695 * The caller must set 'chip_type' to a valid setting.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013696 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013697 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13698 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13699 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13700 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13701 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013703
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013704 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013705 * Reset Chip.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013706 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013707 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13708 ADV_CTRL_REG_CMD_RESET);
13709 mdelay(100);
13710 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13711 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013712
Matthew Wilcox51219352007-10-02 21:55:22 -040013713 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13714 status = AdvInitFrom38C1600EEP(asc_dvc);
13715 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13716 status = AdvInitFrom38C0800EEP(asc_dvc);
13717 } else {
13718 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013719 }
Matthew Wilcox51219352007-10-02 21:55:22 -040013720 warn_code |= status;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013722
Matthew Wilcox51219352007-10-02 21:55:22 -040013723 if (warn_code != 0) {
13724 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
13725 boardp->id, warn_code);
13726 }
13727
13728 if (asc_dvc->err_code) {
13729 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
13730 boardp->id, asc_dvc->err_code);
13731 }
13732
13733 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013734}
Matthew Wilcox51219352007-10-02 21:55:22 -040013735#endif
13736
13737static struct scsi_host_template advansys_template = {
13738 .proc_name = DRV_NAME,
13739#ifdef CONFIG_PROC_FS
13740 .proc_info = advansys_proc_info,
13741#endif
13742 .name = DRV_NAME,
13743 .info = advansys_info,
13744 .queuecommand = advansys_queuecommand,
13745 .eh_bus_reset_handler = advansys_reset,
13746 .bios_param = advansys_biosparam,
13747 .slave_configure = advansys_slave_configure,
13748 /*
13749 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
13750 * must be set. The flag will be cleared in advansys_board_found
13751 * for non-ISA adapters.
13752 */
13753 .unchecked_isa_dma = 1,
13754 /*
13755 * All adapters controlled by this driver are capable of large
13756 * scatter-gather lists. According to the mid-level SCSI documentation
13757 * this obviates any performance gain provided by setting
13758 * 'use_clustering'. But empirically while CPU utilization is increased
13759 * by enabling clustering, I/O throughput increases as well.
13760 */
13761 .use_clustering = ENABLE_CLUSTERING,
13762};
Linus Torvalds1da177e2005-04-16 15:20:36 -070013763
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013764static int __devinit
13765advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
13766{
13767 int req_cnt = 0;
13768 adv_req_t *reqp = NULL;
13769 int sg_cnt = 0;
13770 adv_sgblk_t *sgp;
13771 int warn_code, err_code;
13772
13773 /*
13774 * Allocate buffer carrier structures. The total size
13775 * is about 4 KB, so allocate all at once.
13776 */
13777 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
13778 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
13779
13780 if (!boardp->carrp)
13781 goto kmalloc_failed;
13782
13783 /*
13784 * Allocate up to 'max_host_qng' request structures for the Wide
13785 * board. The total size is about 16 KB, so allocate all at once.
13786 * If the allocation fails decrement and try again.
13787 */
13788 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
13789 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
13790
13791 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
13792 "bytes %lu\n", reqp, req_cnt,
13793 (ulong)sizeof(adv_req_t) * req_cnt);
13794
13795 if (reqp)
13796 break;
13797 }
13798
13799 if (!reqp)
13800 goto kmalloc_failed;
13801
13802 boardp->orig_reqp = reqp;
13803
13804 /*
13805 * Allocate up to ADV_TOT_SG_BLOCK request structures for
13806 * the Wide board. Each structure is about 136 bytes.
13807 */
13808 boardp->adv_sgblkp = NULL;
13809 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
13810 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
13811
13812 if (!sgp)
13813 break;
13814
13815 sgp->next_sgblkp = boardp->adv_sgblkp;
13816 boardp->adv_sgblkp = sgp;
13817
13818 }
13819
13820 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
13821 sg_cnt, sizeof(adv_sgblk_t),
13822 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
13823
13824 if (!boardp->adv_sgblkp)
13825 goto kmalloc_failed;
13826
13827 adv_dvc_varp->carrier_buf = boardp->carrp;
13828
13829 /*
13830 * Point 'adv_reqp' to the request structures and
13831 * link them together.
13832 */
13833 req_cnt--;
13834 reqp[req_cnt].next_reqp = NULL;
13835 for (; req_cnt > 0; req_cnt--) {
13836 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
13837 }
13838 boardp->adv_reqp = &reqp[0];
13839
13840 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
13841 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
13842 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
13843 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
13844 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
13845 "\n");
13846 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
13847 } else {
13848 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
13849 "\n");
13850 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
13851 }
13852 err_code = adv_dvc_varp->err_code;
13853
13854 if (warn_code || err_code) {
13855 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
13856 " error 0x%x\n", boardp->id, warn_code, err_code);
13857 }
13858
13859 goto exit;
13860
13861 kmalloc_failed:
13862 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
13863 "failed\n", boardp->id);
13864 err_code = ADV_ERROR;
13865 exit:
13866 return err_code;
13867}
13868
13869static void advansys_wide_free_mem(asc_board_t *boardp)
13870{
13871 kfree(boardp->carrp);
13872 boardp->carrp = NULL;
13873 kfree(boardp->orig_reqp);
13874 boardp->orig_reqp = boardp->adv_reqp = NULL;
13875 while (boardp->adv_sgblkp) {
13876 adv_sgblk_t *sgp = boardp->adv_sgblkp;
13877 boardp->adv_sgblkp = sgp->next_sgblkp;
13878 kfree(sgp);
13879 }
13880}
13881
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013882static struct Scsi_Host *__devinit
13883advansys_board_found(int iop, struct device *dev, int bus_type)
13884{
13885 struct Scsi_Host *shost;
13886 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
13887 asc_board_t *boardp;
13888 ASC_DVC_VAR *asc_dvc_varp = NULL;
13889 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013890 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013891 int warn_code, err_code;
13892 int ret;
13893
13894 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013895 * Register the adapter, get its configuration, and
13896 * initialize it.
13897 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060013898 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
13899 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013900 if (!shost)
13901 return NULL;
13902
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013903 /* Initialize private per board data */
13904 boardp = ASC_BOARDP(shost);
13905 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013906 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013907 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040013908 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013909
13910 /*
13911 * Handle both narrow and wide boards.
13912 *
13913 * If a Wide board was detected, set the board structure
13914 * wide board flag. Set-up the board structure based on
13915 * the board type.
13916 */
13917#ifdef CONFIG_PCI
13918 if (bus_type == ASC_IS_PCI &&
13919 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
13920 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
13921 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
13922 boardp->flags |= ASC_IS_WIDE_BOARD;
13923 }
13924#endif /* CONFIG_PCI */
13925
13926 if (ASC_NARROW_BOARD(boardp)) {
13927 ASC_DBG(1, "advansys_board_found: narrow board\n");
13928 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
13929 asc_dvc_varp->bus_type = bus_type;
13930 asc_dvc_varp->drv_ptr = boardp;
13931 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
13932 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
13933 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013934 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013935#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013936 ASC_DBG(1, "advansys_board_found: wide board\n");
13937 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
13938 adv_dvc_varp->drv_ptr = boardp;
13939 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013940 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
13941 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
13942 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
13943 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
13944 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
13945 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
13946 } else {
13947 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
13948 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
13949 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013950
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013951 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
13952 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
13953 boardp->asc_n_io_port);
13954 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013955 ASC_PRINT3
13956 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013957 boardp->id, pci_resource_start(pdev, 1),
13958 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013959 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013960 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013961 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060013962 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013963 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013964
13965 /*
13966 * Even though it isn't used to access wide boards, other
13967 * than for the debug line below, save I/O Port address so
13968 * that it can be reported.
13969 */
13970 boardp->ioport = iop;
13971
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013972 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
13973 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
13974 (ushort)inpw(iop));
13975#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013976 }
13977
13978#ifdef CONFIG_PROC_FS
13979 /*
13980 * Allocate buffer for printing information from
13981 * /proc/scsi/advansys/[0...].
13982 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013983 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
13984 if (!boardp->prtbuf) {
13985 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
13986 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
13987 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013988 }
13989#endif /* CONFIG_PROC_FS */
13990
13991 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013992 /*
13993 * Set the board bus type and PCI IRQ before
13994 * calling AscInitGetConfig().
13995 */
13996 switch (asc_dvc_varp->bus_type) {
13997#ifdef CONFIG_ISA
13998 case ASC_IS_ISA:
13999 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014000 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014001 break;
14002 case ASC_IS_VL:
14003 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014004 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014005 break;
14006 case ASC_IS_EISA:
14007 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014008 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014009 break;
14010#endif /* CONFIG_ISA */
14011#ifdef CONFIG_PCI
14012 case ASC_IS_PCI:
14013 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014014 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014015 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014016 break;
14017#endif /* CONFIG_PCI */
14018 default:
14019 ASC_PRINT2
14020 ("advansys_board_found: board %d: unknown adapter type: %d\n",
14021 boardp->id, asc_dvc_varp->bus_type);
14022 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014023 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014024 break;
14025 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014026
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014027 /*
14028 * NOTE: AscInitGetConfig() may change the board's
14029 * bus_type value. The bus_type value should no
14030 * longer be used. If the bus_type field must be
14031 * referenced only use the bit-wise AND operator "&".
14032 */
14033 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014034 err_code = AscInitGetConfig(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014035 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014036#ifdef CONFIG_PCI
14037 /*
14038 * For Wide boards set PCI information before calling
14039 * AdvInitGetConfig().
14040 */
14041 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
14042 shost->unchecked_isa_dma = FALSE;
14043 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014044 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014045
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014046 err_code = AdvInitGetConfig(pdev, boardp);
14047#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014048 }
14049
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014050 if (err_code != 0)
14051 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014052
14053 /*
14054 * Save the EEPROM configuration so that it can be displayed
14055 * from /proc/scsi/advansys/[0...].
14056 */
14057 if (ASC_NARROW_BOARD(boardp)) {
14058
14059 ASCEEP_CONFIG *ep;
14060
14061 /*
14062 * Set the adapter's target id bit in the 'init_tidmask' field.
14063 */
14064 boardp->init_tidmask |=
14065 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
14066
14067 /*
14068 * Save EEPROM settings for the board.
14069 */
14070 ep = &boardp->eep_config.asc_eep;
14071
14072 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
14073 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
14074 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
14075 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
14076 ep->start_motor = asc_dvc_varp->start_motor;
14077 ep->cntl = asc_dvc_varp->dvc_cntl;
14078 ep->no_scam = asc_dvc_varp->no_scam;
14079 ep->max_total_qng = asc_dvc_varp->max_total_qng;
14080 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
14081 /* 'max_tag_qng' is set to the same value for every device. */
14082 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
14083 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
14084 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
14085 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
14086 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
14087 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
14088 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
14089
14090 /*
14091 * Modify board configuration.
14092 */
14093 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014094 err_code = AscInitSetConfig(pdev, boardp);
14095 if (err_code)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014096 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014097
14098 /*
14099 * Finish initializing the 'Scsi_Host' structure.
14100 */
14101 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
14102 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
14103 shost->irq = asc_dvc_varp->irq_no;
14104 }
14105 } else {
14106 ADVEEP_3550_CONFIG *ep_3550;
14107 ADVEEP_38C0800_CONFIG *ep_38C0800;
14108 ADVEEP_38C1600_CONFIG *ep_38C1600;
14109
14110 /*
14111 * Save Wide EEP Configuration Information.
14112 */
14113 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14114 ep_3550 = &boardp->eep_config.adv_3550_eep;
14115
14116 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
14117 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
14118 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14119 ep_3550->termination = adv_dvc_varp->cfg->termination;
14120 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
14121 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
14122 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
14123 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
14124 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
14125 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
14126 ep_3550->start_motor = adv_dvc_varp->start_motor;
14127 ep_3550->scsi_reset_delay =
14128 adv_dvc_varp->scsi_reset_wait;
14129 ep_3550->serial_number_word1 =
14130 adv_dvc_varp->cfg->serial1;
14131 ep_3550->serial_number_word2 =
14132 adv_dvc_varp->cfg->serial2;
14133 ep_3550->serial_number_word3 =
14134 adv_dvc_varp->cfg->serial3;
14135 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14136 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
14137
14138 ep_38C0800->adapter_scsi_id =
14139 adv_dvc_varp->chip_scsi_id;
14140 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
14141 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14142 ep_38C0800->termination_lvd =
14143 adv_dvc_varp->cfg->termination;
14144 ep_38C0800->disc_enable =
14145 adv_dvc_varp->cfg->disc_enable;
14146 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
14147 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
14148 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14149 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14150 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14151 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14152 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14153 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14154 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
14155 ep_38C0800->scsi_reset_delay =
14156 adv_dvc_varp->scsi_reset_wait;
14157 ep_38C0800->serial_number_word1 =
14158 adv_dvc_varp->cfg->serial1;
14159 ep_38C0800->serial_number_word2 =
14160 adv_dvc_varp->cfg->serial2;
14161 ep_38C0800->serial_number_word3 =
14162 adv_dvc_varp->cfg->serial3;
14163 } else {
14164 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
14165
14166 ep_38C1600->adapter_scsi_id =
14167 adv_dvc_varp->chip_scsi_id;
14168 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
14169 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14170 ep_38C1600->termination_lvd =
14171 adv_dvc_varp->cfg->termination;
14172 ep_38C1600->disc_enable =
14173 adv_dvc_varp->cfg->disc_enable;
14174 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
14175 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
14176 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14177 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14178 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14179 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14180 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14181 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14182 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
14183 ep_38C1600->scsi_reset_delay =
14184 adv_dvc_varp->scsi_reset_wait;
14185 ep_38C1600->serial_number_word1 =
14186 adv_dvc_varp->cfg->serial1;
14187 ep_38C1600->serial_number_word2 =
14188 adv_dvc_varp->cfg->serial2;
14189 ep_38C1600->serial_number_word3 =
14190 adv_dvc_varp->cfg->serial3;
14191 }
14192
14193 /*
14194 * Set the adapter's target id bit in the 'init_tidmask' field.
14195 */
14196 boardp->init_tidmask |=
14197 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014198 }
14199
14200 /*
14201 * Channels are numbered beginning with 0. For AdvanSys one host
14202 * structure supports one channel. Multi-channel boards have a
14203 * separate host structure for each channel.
14204 */
14205 shost->max_channel = 0;
14206 if (ASC_NARROW_BOARD(boardp)) {
14207 shost->max_id = ASC_MAX_TID + 1;
14208 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014209 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014210
14211 shost->io_port = asc_dvc_varp->iop_base;
14212 boardp->asc_n_io_port = ASC_IOADR_GAP;
14213 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
14214
14215 /* Set maximum number of queues the adapter can handle. */
14216 shost->can_queue = asc_dvc_varp->max_total_qng;
14217 } else {
14218 shost->max_id = ADV_MAX_TID + 1;
14219 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014220 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014221
14222 /*
14223 * Save the I/O Port address and length even though
14224 * I/O ports are not used to access Wide boards.
14225 * Instead the Wide boards are accessed with
14226 * PCI Memory Mapped I/O.
14227 */
14228 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014229
14230 shost->this_id = adv_dvc_varp->chip_scsi_id;
14231
14232 /* Set maximum number of queues the adapter can handle. */
14233 shost->can_queue = adv_dvc_varp->max_host_qng;
14234 }
14235
14236 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014237 * Following v1.3.89, 'cmd_per_lun' is no longer needed
14238 * and should be set to zero.
14239 *
14240 * But because of a bug introduced in v1.3.89 if the driver is
14241 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
14242 * SCSI function 'allocate_device' will panic. To allow the driver
14243 * to work as a module in these kernels set 'cmd_per_lun' to 1.
14244 *
14245 * Note: This is wrong. cmd_per_lun should be set to the depth
14246 * you want on untagged devices always.
14247 #ifdef MODULE
14248 */
14249 shost->cmd_per_lun = 1;
14250/* #else
14251 shost->cmd_per_lun = 0;
14252#endif */
14253
14254 /*
14255 * Set the maximum number of scatter-gather elements the
14256 * adapter can handle.
14257 */
14258 if (ASC_NARROW_BOARD(boardp)) {
14259 /*
14260 * Allow two commands with 'sg_tablesize' scatter-gather
14261 * elements to be executed simultaneously. This value is
14262 * the theoretical hardware limit. It may be decreased
14263 * below.
14264 */
14265 shost->sg_tablesize =
14266 (((asc_dvc_varp->max_total_qng - 2) / 2) *
14267 ASC_SG_LIST_PER_Q) + 1;
14268 } else {
14269 shost->sg_tablesize = ADV_MAX_SG_LIST;
14270 }
14271
14272 /*
14273 * The value of 'sg_tablesize' can not exceed the SCSI
14274 * mid-level driver definition of SG_ALL. SG_ALL also
14275 * must not be exceeded, because it is used to define the
14276 * size of the scatter-gather table in 'struct asc_sg_head'.
14277 */
14278 if (shost->sg_tablesize > SG_ALL) {
14279 shost->sg_tablesize = SG_ALL;
14280 }
14281
14282 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
14283
14284 /* BIOS start address. */
14285 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014286 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
14287 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014288 } else {
14289 /*
14290 * Fill-in BIOS board variables. The Wide BIOS saves
14291 * information in LRAM that is used by the driver.
14292 */
14293 AdvReadWordLram(adv_dvc_varp->iop_base,
14294 BIOS_SIGNATURE, boardp->bios_signature);
14295 AdvReadWordLram(adv_dvc_varp->iop_base,
14296 BIOS_VERSION, boardp->bios_version);
14297 AdvReadWordLram(adv_dvc_varp->iop_base,
14298 BIOS_CODESEG, boardp->bios_codeseg);
14299 AdvReadWordLram(adv_dvc_varp->iop_base,
14300 BIOS_CODELEN, boardp->bios_codelen);
14301
14302 ASC_DBG2(1,
14303 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
14304 boardp->bios_signature, boardp->bios_version);
14305
14306 ASC_DBG2(1,
14307 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
14308 boardp->bios_codeseg, boardp->bios_codelen);
14309
14310 /*
14311 * If the BIOS saved a valid signature, then fill in
14312 * the BIOS code segment base address.
14313 */
14314 if (boardp->bios_signature == 0x55AA) {
14315 /*
14316 * Convert x86 realmode code segment to a linear
14317 * address by shifting left 4.
14318 */
14319 shost->base = ((ulong)boardp->bios_codeseg << 4);
14320 } else {
14321 shost->base = 0;
14322 }
14323 }
14324
14325 /*
14326 * Register Board Resources - I/O Port, DMA, IRQ
14327 */
14328
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014329 /* Register DMA Channel for Narrow boards. */
14330 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14331#ifdef CONFIG_ISA
14332 if (ASC_NARROW_BOARD(boardp)) {
14333 /* Register DMA channel for ISA bus. */
14334 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14335 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014336 ret = request_dma(shost->dma_channel, DRV_NAME);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014337 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014338 ASC_PRINT3
14339 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14340 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014341 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014342 }
14343 AscEnableIsaDma(shost->dma_channel);
14344 }
14345 }
14346#endif /* CONFIG_ISA */
14347
14348 /* Register IRQ Number. */
14349 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014350
14351 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014352 DRV_NAME, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014353
14354 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014355 if (ret == -EBUSY) {
14356 ASC_PRINT2
14357 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
14358 boardp->id, shost->irq);
14359 } else if (ret == -EINVAL) {
14360 ASC_PRINT2
14361 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
14362 boardp->id, shost->irq);
14363 } else {
14364 ASC_PRINT3
14365 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
14366 boardp->id, shost->irq, ret);
14367 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014368 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014369 }
14370
14371 /*
14372 * Initialize board RISC chip and enable interrupts.
14373 */
14374 if (ASC_NARROW_BOARD(boardp)) {
14375 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
14376 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
14377 err_code = asc_dvc_varp->err_code;
14378
14379 if (warn_code || err_code) {
14380 ASC_PRINT4
14381 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
14382 boardp->id,
14383 asc_dvc_varp->init_state, warn_code, err_code);
14384 }
14385 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014386 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014387 }
14388
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014389 if (err_code != 0)
14390 goto err_free_wide_mem;
14391
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014392 ASC_DBG_PRT_SCSI_HOST(2, shost);
14393
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014394 ret = scsi_add_host(shost, dev);
14395 if (ret)
14396 goto err_free_wide_mem;
14397
14398 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014399 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014400
14401 err_free_wide_mem:
14402 advansys_wide_free_mem(boardp);
14403 free_irq(shost->irq, shost);
14404 err_free_dma:
14405 if (shost->dma_channel != NO_ISA_DMA)
14406 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014407 err_free_proc:
14408 kfree(boardp->prtbuf);
14409 err_unmap:
14410 if (boardp->ioremap_addr)
14411 iounmap(boardp->ioremap_addr);
14412 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014413 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014414 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014415}
14416
14417/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014418 * advansys_release()
14419 *
14420 * Release resources allocated for a single AdvanSys adapter.
14421 */
14422static int advansys_release(struct Scsi_Host *shost)
14423{
14424 asc_board_t *boardp;
14425
14426 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014427 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014428 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014429 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014430 if (shost->dma_channel != NO_ISA_DMA) {
14431 ASC_DBG(1, "advansys_release: free_dma()\n");
14432 free_dma(shost->dma_channel);
14433 }
Matthew Wilcox9a256fa2007-10-02 21:55:28 -040014434 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014435 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014436 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014437 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014438 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014439 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014440 ASC_DBG(1, "advansys_release: end\n");
14441 return 0;
14442}
14443
Matthew Wilcox95c9f162007-09-09 08:56:39 -060014444#define ASC_IOADR_TABLE_MAX_IX 11
14445
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014446static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
14447 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
14448 0x0210, 0x0230, 0x0250, 0x0330
14449};
14450
14451static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
14452{
14453 PortAddr iop_base = _asc_def_iop_base[id];
14454 struct Scsi_Host *shost;
14455
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014456 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014457 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
14458 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014459 return -ENODEV;
14460 }
14461 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014462 if (!AscFindSignature(iop_base))
14463 goto nodev;
14464 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
14465 goto nodev;
14466
14467 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014468 if (!shost)
14469 goto nodev;
14470
14471 dev_set_drvdata(dev, shost);
14472 return 0;
14473
14474 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014475 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014476 return -ENODEV;
14477}
14478
14479static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
14480{
Matthew Wilcox71f36112007-07-30 08:04:53 -060014481 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014482 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014483 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014484 return 0;
14485}
14486
14487static struct isa_driver advansys_isa_driver = {
14488 .probe = advansys_isa_probe,
14489 .remove = __devexit_p(advansys_isa_remove),
14490 .driver = {
14491 .owner = THIS_MODULE,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014492 .name = DRV_NAME,
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014493 },
14494};
14495
14496static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
14497{
14498 PortAddr iop_base = _asc_def_iop_base[id];
14499 struct Scsi_Host *shost;
14500
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014501 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014502 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
14503 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014504 return -ENODEV;
14505 }
14506 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014507 if (!AscFindSignature(iop_base))
14508 goto nodev;
14509 /*
14510 * I don't think this condition can actually happen, but the old
14511 * driver did it, and the chances of finding a VLB setup in 2007
14512 * to do testing with is slight to none.
14513 */
14514 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
14515 goto nodev;
14516
14517 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014518 if (!shost)
14519 goto nodev;
14520
14521 dev_set_drvdata(dev, shost);
14522 return 0;
14523
14524 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014525 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014526 return -ENODEV;
14527}
14528
14529static struct isa_driver advansys_vlb_driver = {
14530 .probe = advansys_vlb_probe,
14531 .remove = __devexit_p(advansys_isa_remove),
14532 .driver = {
14533 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060014534 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014535 },
14536};
14537
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014538static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
14539 { "ABP7401" },
14540 { "ABP7501" },
14541 { "" }
14542};
14543
14544MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
14545
14546/*
14547 * EISA is a little more tricky than PCI; each EISA device may have two
14548 * channels, and this driver is written to make each channel its own Scsi_Host
14549 */
14550struct eisa_scsi_data {
14551 struct Scsi_Host *host[2];
14552};
14553
14554static int __devinit advansys_eisa_probe(struct device *dev)
14555{
14556 int i, ioport;
14557 int err;
14558 struct eisa_device *edev = to_eisa_device(dev);
14559 struct eisa_scsi_data *data;
14560
14561 err = -ENOMEM;
14562 data = kzalloc(sizeof(*data), GFP_KERNEL);
14563 if (!data)
14564 goto fail;
14565 ioport = edev->base_addr + 0xc30;
14566
14567 err = -ENODEV;
14568 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014569 if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014570 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
14571 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014572 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014573 }
14574 if (!AscFindSignature(ioport)) {
14575 release_region(ioport, ASC_IOADR_GAP);
14576 continue;
14577 }
14578
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014579 /*
14580 * I don't know why we need to do this for EISA chips, but
14581 * not for any others. It looks to be equivalent to
14582 * AscGetChipCfgMsw, but I may have overlooked something,
14583 * so I'm not converting it until I get an EISA board to
14584 * test with.
14585 */
14586 inw(ioport + 4);
14587 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014588 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014589 err = 0;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014590 } else {
14591 release_region(ioport, ASC_IOADR_GAP);
14592 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014593 }
14594
14595 if (err) {
14596 kfree(data);
14597 } else {
14598 dev_set_drvdata(dev, data);
14599 }
14600
14601 fail:
14602 return err;
14603}
14604
14605static __devexit int advansys_eisa_remove(struct device *dev)
14606{
14607 int i;
14608 struct eisa_scsi_data *data = dev_get_drvdata(dev);
14609
14610 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014611 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014612 struct Scsi_Host *shost = data->host[i];
14613 if (!shost)
14614 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014615 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014616 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014617 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014618 }
14619
14620 kfree(data);
14621 return 0;
14622}
14623
14624static struct eisa_driver advansys_eisa_driver = {
14625 .id_table = advansys_eisa_table,
14626 .driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014627 .name = DRV_NAME,
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014628 .probe = advansys_eisa_probe,
14629 .remove = __devexit_p(advansys_eisa_remove),
14630 }
14631};
14632
Dave Jones2672ea82006-08-02 17:11:49 -040014633/* PCI Devices supported by this driver */
14634static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014635 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
14636 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14637 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
14638 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14639 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
14640 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14641 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
14642 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14643 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
14644 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14645 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
14646 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14647 {}
Dave Jones2672ea82006-08-02 17:11:49 -040014648};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014649
Dave Jones2672ea82006-08-02 17:11:49 -040014650MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014651
Matthew Wilcox9649af32007-07-26 21:51:47 -060014652static void __devinit advansys_set_latency(struct pci_dev *pdev)
14653{
14654 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
14655 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
14656 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
14657 } else {
14658 u8 latency;
14659 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
14660 if (latency < 0x20)
14661 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
14662 }
14663}
14664
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014665static int __devinit
14666advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14667{
14668 int err, ioport;
14669 struct Scsi_Host *shost;
14670
14671 err = pci_enable_device(pdev);
14672 if (err)
14673 goto fail;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014674 err = pci_request_regions(pdev, DRV_NAME);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014675 if (err)
14676 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060014677 pci_set_master(pdev);
14678 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014679
14680 if (pci_resource_len(pdev, 0) == 0)
14681 goto nodev;
14682
14683 ioport = pci_resource_start(pdev, 0);
14684 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
14685
14686 if (!shost)
14687 goto nodev;
14688
14689 pci_set_drvdata(pdev, shost);
14690 return 0;
14691
14692 nodev:
14693 err = -ENODEV;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014694 pci_release_regions(pdev);
14695 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014696 pci_disable_device(pdev);
14697 fail:
14698 return err;
14699}
14700
14701static void __devexit advansys_pci_remove(struct pci_dev *pdev)
14702{
14703 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014704 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014705 pci_disable_device(pdev);
14706}
14707
14708static struct pci_driver advansys_pci_driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014709 .name = DRV_NAME,
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014710 .id_table = advansys_pci_tbl,
14711 .probe = advansys_pci_probe,
14712 .remove = __devexit_p(advansys_pci_remove),
14713};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014714
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014715static int __init advansys_init(void)
14716{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014717 int error;
14718
14719 error = isa_register_driver(&advansys_isa_driver,
14720 ASC_IOADR_TABLE_MAX_IX);
14721 if (error)
14722 goto fail;
14723
14724 error = isa_register_driver(&advansys_vlb_driver,
14725 ASC_IOADR_TABLE_MAX_IX);
14726 if (error)
14727 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014728
14729 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014730 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014731 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014732
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014733 error = pci_register_driver(&advansys_pci_driver);
14734 if (error)
14735 goto unregister_eisa;
14736
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014737 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014738
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014739 unregister_eisa:
14740 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014741 unregister_vlb:
14742 isa_unregister_driver(&advansys_vlb_driver);
14743 unregister_isa:
14744 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014745 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014746 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014747}
14748
14749static void __exit advansys_exit(void)
14750{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014751 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014752 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014753 isa_unregister_driver(&advansys_vlb_driver);
14754 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014755}
14756
14757module_init(advansys_init);
14758module_exit(advansys_exit);
14759
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014760MODULE_LICENSE("GPL");