blob: 93b1a47ebaf842cbfb7829f8b2228bf5f0902b60 [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
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040069 * 8. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 */
71#warning this driver is still not properly converted to the DMA API
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073/* Enable driver /proc statistics. */
74#define ADVANSYS_STATS
75
76/* Enable driver tracing. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040077#undef ADVANSYS_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Linus Torvalds1da177e2005-04-16 15:20:36 -070079/*
80 * Portable Data Types
81 *
82 * Any instance where a 32-bit long or pointer type is assumed
83 * for precision or HW defined structures, the following define
84 * types must be used. In Linux the char, short, and int types
85 * are all consistent at 8, 16, and 32 bits respectively. Pointers
86 * and long types are 64 bits on Alpha and UltraSPARC.
87 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040088#define ASC_PADDR __u32 /* Physical/Bus address data type. */
89#define ASC_VADDR __u32 /* Virtual address data type. */
90#define ASC_DCNT __u32 /* Unsigned Data count type. */
91#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93/*
94 * These macros are used to convert a virtual address to a
95 * 32-bit value. This currently can be used on Linux Alpha
96 * which uses 64-bit virtual address but a 32-bit bus address.
97 * This is likely to break in the future, but doing this now
98 * will give us time to change the HW and FW to handle 64-bit
99 * addresses.
100 */
101#define ASC_VADDR_TO_U32 virt_to_bus
102#define ASC_U32_TO_VADDR bus_to_virt
103
104typedef unsigned char uchar;
105
106#ifndef TRUE
107#define TRUE (1)
108#endif
109#ifndef FALSE
110#define FALSE (0)
111#endif
112
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#define ERR (-1)
114#define UW_ERR (uint)(0xFFFF)
115#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Dave Jones2672ea82006-08-02 17:11:49 -0400117#define PCI_VENDOR_ID_ASP 0x10cd
118#define PCI_DEVICE_ID_ASP_1200A 0x1100
119#define PCI_DEVICE_ID_ASP_ABP940 0x1200
120#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
121#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
122#define PCI_DEVICE_ID_38C0800_REV1 0x2500
123#define PCI_DEVICE_ID_38C1600_REV1 0x2700
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125/*
126 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
127 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
128 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
129 * SRB structure.
130 */
131#define CC_VERY_LONG_SG_LIST 0
132#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
133
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400134#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135#define inp(port) inb(port)
136#define outp(port, byte) outb((byte), (port))
137
138#define inpw(port) inw(port)
139#define outpw(port, word) outw((word), (port))
140
141#define ASC_MAX_SG_QUEUE 7
142#define ASC_MAX_SG_LIST 255
143
144#define ASC_CS_TYPE unsigned short
145
146#define ASC_IS_ISA (0x0001)
147#define ASC_IS_ISAPNP (0x0081)
148#define ASC_IS_EISA (0x0002)
149#define ASC_IS_PCI (0x0004)
150#define ASC_IS_PCI_ULTRA (0x0104)
151#define ASC_IS_PCMCIA (0x0008)
152#define ASC_IS_MCA (0x0020)
153#define ASC_IS_VL (0x0040)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define ASC_IS_WIDESCSI_16 (0x0100)
155#define ASC_IS_WIDESCSI_32 (0x0200)
156#define ASC_IS_BIG_ENDIAN (0x8000)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158#define ASC_CHIP_MIN_VER_VL (0x01)
159#define ASC_CHIP_MAX_VER_VL (0x07)
160#define ASC_CHIP_MIN_VER_PCI (0x09)
161#define ASC_CHIP_MAX_VER_PCI (0x0F)
162#define ASC_CHIP_VER_PCI_BIT (0x08)
163#define ASC_CHIP_MIN_VER_ISA (0x11)
164#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
165#define ASC_CHIP_MAX_VER_ISA (0x27)
166#define ASC_CHIP_VER_ISA_BIT (0x30)
167#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
168#define ASC_CHIP_VER_ASYN_BUG (0x21)
169#define ASC_CHIP_VER_PCI 0x08
170#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
171#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
172#define ASC_CHIP_MIN_VER_EISA (0x41)
173#define ASC_CHIP_MAX_VER_EISA (0x47)
174#define ASC_CHIP_VER_EISA_BIT (0x40)
175#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
180#define ASC_SCSI_ID_BITS 3
181#define ASC_SCSI_TIX_TYPE uchar
182#define ASC_ALL_DEVICE_BIT_SET 0xFF
183#define ASC_SCSI_BIT_ID_TYPE uchar
184#define ASC_MAX_TID 7
185#define ASC_MAX_LUN 7
186#define ASC_SCSI_WIDTH_BIT_SET 0xFF
187#define ASC_MAX_SENSE_LEN 32
188#define ASC_MIN_SENSE_LEN 14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189#define ASC_SCSI_RESET_HOLD_TIME_US 60
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191/*
Matthew Wilcoxf05ec592007-09-09 08:56:36 -0600192 * Narrow boards only support 12-byte commands, while wide boards
193 * extend to 16-byte commands.
194 */
195#define ASC_MAX_CDB_LEN 12
196#define ADV_MAX_CDB_LEN 16
197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201#define ASC_SG_LIST_PER_Q 7
202#define QS_FREE 0x00
203#define QS_READY 0x01
204#define QS_DISC1 0x02
205#define QS_DISC2 0x04
206#define QS_BUSY 0x08
207#define QS_ABORTED 0x40
208#define QS_DONE 0x80
209#define QC_NO_CALLBACK 0x01
210#define QC_SG_SWAP_QUEUE 0x02
211#define QC_SG_HEAD 0x04
212#define QC_DATA_IN 0x08
213#define QC_DATA_OUT 0x10
214#define QC_URGENT 0x20
215#define QC_MSG_OUT 0x40
216#define QC_REQ_SENSE 0x80
217#define QCSG_SG_XFER_LIST 0x02
218#define QCSG_SG_XFER_MORE 0x04
219#define QCSG_SG_XFER_END 0x08
220#define QD_IN_PROGRESS 0x00
221#define QD_NO_ERROR 0x01
222#define QD_ABORTED_BY_HOST 0x02
223#define QD_WITH_ERROR 0x04
224#define QD_INVALID_REQUEST 0x80
225#define QD_INVALID_HOST_NUM 0x81
226#define QD_INVALID_DEVICE 0x82
227#define QD_ERR_INTERNAL 0xFF
228#define QHSTA_NO_ERROR 0x00
229#define QHSTA_M_SEL_TIMEOUT 0x11
230#define QHSTA_M_DATA_OVER_RUN 0x12
231#define QHSTA_M_DATA_UNDER_RUN 0x12
232#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
233#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
234#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
235#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
236#define QHSTA_D_HOST_ABORT_FAILED 0x23
237#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
238#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
239#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
240#define QHSTA_M_WTM_TIMEOUT 0x41
241#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
242#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
243#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
244#define QHSTA_M_TARGET_STATUS_BUSY 0x45
245#define QHSTA_M_BAD_TAG_CODE 0x46
246#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
247#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
248#define QHSTA_D_LRAM_CMP_ERROR 0x81
249#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
250#define ASC_FLAG_SCSIQ_REQ 0x01
251#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
252#define ASC_FLAG_BIOS_ASYNC_IO 0x04
253#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
254#define ASC_FLAG_WIN16 0x10
255#define ASC_FLAG_WIN32 0x20
256#define ASC_FLAG_ISA_OVER_16MB 0x40
257#define ASC_FLAG_DOS_VM_CALLBACK 0x80
258#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
259#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
260#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
261#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
262#define ASC_SCSIQ_CPY_BEG 4
263#define ASC_SCSIQ_SGHD_CPY_BEG 2
264#define ASC_SCSIQ_B_FWD 0
265#define ASC_SCSIQ_B_BWD 1
266#define ASC_SCSIQ_B_STATUS 2
267#define ASC_SCSIQ_B_QNO 3
268#define ASC_SCSIQ_B_CNTL 4
269#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
270#define ASC_SCSIQ_D_DATA_ADDR 8
271#define ASC_SCSIQ_D_DATA_CNT 12
272#define ASC_SCSIQ_B_SENSE_LEN 20
273#define ASC_SCSIQ_DONE_INFO_BEG 22
274#define ASC_SCSIQ_D_SRBPTR 22
275#define ASC_SCSIQ_B_TARGET_IX 26
276#define ASC_SCSIQ_B_CDB_LEN 28
277#define ASC_SCSIQ_B_TAG_CODE 29
278#define ASC_SCSIQ_W_VM_ID 30
279#define ASC_SCSIQ_DONE_STATUS 32
280#define ASC_SCSIQ_HOST_STATUS 33
281#define ASC_SCSIQ_SCSI_STATUS 34
282#define ASC_SCSIQ_CDB_BEG 36
283#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
284#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
285#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
286#define ASC_SCSIQ_B_SG_WK_QP 49
287#define ASC_SCSIQ_B_SG_WK_IX 50
288#define ASC_SCSIQ_W_ALT_DC1 52
289#define ASC_SCSIQ_B_LIST_CNT 6
290#define ASC_SCSIQ_B_CUR_LIST_CNT 7
291#define ASC_SGQ_B_SG_CNTL 4
292#define ASC_SGQ_B_SG_HEAD_QP 5
293#define ASC_SGQ_B_SG_LIST_CNT 6
294#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
295#define ASC_SGQ_LIST_BEG 8
296#define ASC_DEF_SCSI1_QNG 4
297#define ASC_MAX_SCSI1_QNG 4
298#define ASC_DEF_SCSI2_QNG 16
299#define ASC_MAX_SCSI2_QNG 32
300#define ASC_TAG_CODE_MASK 0x23
301#define ASC_STOP_REQ_RISC_STOP 0x01
302#define ASC_STOP_ACK_RISC_STOP 0x03
303#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
304#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
305#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
306#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
307#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
308#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
309#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
310#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
311#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
312#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
313
314typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400315 uchar status;
316 uchar q_no;
317 uchar cntl;
318 uchar sg_queue_cnt;
319 uchar target_id;
320 uchar target_lun;
321 ASC_PADDR data_addr;
322 ASC_DCNT data_cnt;
323 ASC_PADDR sense_addr;
324 uchar sense_len;
325 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326} ASC_SCSIQ_1;
327
328typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400329 ASC_VADDR srb_ptr;
330 uchar target_ix;
331 uchar flag;
332 uchar cdb_len;
333 uchar tag_code;
334 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335} ASC_SCSIQ_2;
336
337typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400338 uchar done_stat;
339 uchar host_stat;
340 uchar scsi_stat;
341 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342} ASC_SCSIQ_3;
343
344typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400345 uchar cdb[ASC_MAX_CDB_LEN];
346 uchar y_first_sg_list_qp;
347 uchar y_working_sg_qp;
348 uchar y_working_sg_ix;
349 uchar y_res;
350 ushort x_req_count;
351 ushort x_reconnect_rtn;
352 ASC_PADDR x_saved_data_addr;
353 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354} ASC_SCSIQ_4;
355
356typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400357 ASC_SCSIQ_2 d2;
358 ASC_SCSIQ_3 d3;
359 uchar q_status;
360 uchar q_no;
361 uchar cntl;
362 uchar sense_len;
363 uchar extra_bytes;
364 uchar res;
365 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366} ASC_QDONE_INFO;
367
368typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400369 ASC_PADDR addr;
370 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371} ASC_SG_LIST;
372
373typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400374 ushort entry_cnt;
375 ushort queue_cnt;
376 ushort entry_to_copy;
377 ushort res;
Matthew Wilcox05848b62007-10-02 21:55:25 -0400378 ASC_SG_LIST sg_list[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379} ASC_SG_HEAD;
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400382 ASC_SCSIQ_1 q1;
383 ASC_SCSIQ_2 q2;
384 uchar *cdbptr;
385 ASC_SG_HEAD *sg_head;
386 ushort remain_sg_entry_cnt;
387 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388} ASC_SCSI_Q;
389
390typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400391 ASC_SCSIQ_1 r1;
392 ASC_SCSIQ_2 r2;
393 uchar *cdbptr;
394 ASC_SG_HEAD *sg_head;
395 uchar *sense_ptr;
396 ASC_SCSIQ_3 r3;
397 uchar cdb[ASC_MAX_CDB_LEN];
398 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399} ASC_SCSI_REQ_Q;
400
401typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400402 ASC_SCSIQ_1 r1;
403 ASC_SCSIQ_2 r2;
404 uchar *cdbptr;
405 ASC_SG_HEAD *sg_head;
406 uchar *sense_ptr;
407 ASC_SCSIQ_3 r3;
408 uchar cdb[ASC_MAX_CDB_LEN];
409 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410} ASC_SCSI_BIOS_REQ_Q;
411
412typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400413 uchar fwd;
414 uchar bwd;
415 ASC_SCSIQ_1 i1;
416 ASC_SCSIQ_2 i2;
417 ASC_SCSIQ_3 i3;
418 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419} ASC_RISC_Q;
420
421typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400422 uchar seq_no;
423 uchar q_no;
424 uchar cntl;
425 uchar sg_head_qp;
426 uchar sg_list_cnt;
427 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428} ASC_SG_LIST_Q;
429
430typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400431 uchar fwd;
432 uchar bwd;
433 ASC_SG_LIST_Q sg;
434 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435} ASC_RISC_SG_LIST_Q;
436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437#define ASCQ_ERR_Q_STATUS 0x0D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438#define ASCQ_ERR_CUR_QNG 0x17
439#define ASCQ_ERR_SG_Q_LINKS 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
441#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
442#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444/*
445 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
446 */
447#define ASC_WARN_NO_ERROR 0x0000
448#define ASC_WARN_IO_PORT_ROTATE 0x0001
449#define ASC_WARN_EEPROM_CHKSUM 0x0002
450#define ASC_WARN_IRQ_MODIFIED 0x0004
451#define ASC_WARN_AUTO_CONFIG 0x0008
452#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
453#define ASC_WARN_EEPROM_RECOVER 0x0020
454#define ASC_WARN_CFG_MSW_RECOVER 0x0040
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456/*
Matthew Wilcox720349a2007-10-02 21:55:30 -0400457 * Error code values are set in {ASC/ADV}_DVC_VAR 'err_code'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 */
Matthew Wilcox720349a2007-10-02 21:55:30 -0400459#define ASC_IERR_NO_CARRIER 0x0001 /* No more carrier memory */
460#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
461#define ASC_IERR_SET_PC_ADDR 0x0004
462#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
463#define ASC_IERR_ILLEGAL_CONNECTION 0x0010 /* Illegal cable connection */
464#define ASC_IERR_SINGLE_END_DEVICE 0x0020 /* SE device on DIFF bus */
465#define ASC_IERR_REVERSED_CABLE 0x0040 /* Narrow flat cable reversed */
466#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
467#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD device on LVD port */
468#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
469#define ASC_IERR_NO_BUS_TYPE 0x0400
470#define ASC_IERR_BIST_PRE_TEST 0x0800 /* BIST pre-test error */
471#define ASC_IERR_BIST_RAM_TEST 0x1000 /* BIST RAM test error */
472#define ASC_IERR_BAD_CHIPTYPE 0x2000 /* Invalid chip_type setting */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
475#define ASC_MIN_TAG_Q_PER_DVC (0x04)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600476#define ASC_MIN_FREE_Q (0x02)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
478#define ASC_MAX_TOTAL_QNG 240
479#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
480#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
481#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
482#define ASC_MAX_INRAM_TAG_QNG 16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484#define ASC_SYN_MAX_OFFSET 0x0F
485#define ASC_DEF_SDTR_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -0400487#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
488
489/* The narrow chip only supports a limited selection of transfer rates.
490 * These are encoded in the range 0..7 or 0..15 depending whether the chip
491 * is Ultra-capable or not. These tables let us convert from one to the other.
492 */
493static const unsigned char asc_syn_xfer_period[8] = {
494 25, 30, 35, 40, 50, 60, 70, 85
495};
496
497static const unsigned char asc_syn_ultra_xfer_period[16] = {
498 12, 19, 25, 32, 38, 44, 50, 57, 63, 69, 75, 82, 88, 94, 100, 107
499};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
501typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400502 uchar msg_type;
503 uchar msg_len;
504 uchar msg_req;
505 union {
506 struct {
507 uchar sdtr_xfer_period;
508 uchar sdtr_req_ack_offset;
509 } sdtr;
510 struct {
511 uchar wdtr_width;
512 } wdtr;
513 struct {
514 uchar mdp_b3;
515 uchar mdp_b2;
516 uchar mdp_b1;
517 uchar mdp_b0;
518 } mdp;
519 } u_ext_msg;
520 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521} EXT_MSG;
522
523#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
524#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
525#define wdtr_width u_ext_msg.wdtr.wdtr_width
526#define mdp_b3 u_ext_msg.mdp_b3
527#define mdp_b2 u_ext_msg.mdp_b2
528#define mdp_b1 u_ext_msg.mdp_b1
529#define mdp_b0 u_ext_msg.mdp_b0
530
531typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400532 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
533 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
534 ASC_SCSI_BIT_ID_TYPE disc_enable;
535 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
536 uchar chip_scsi_id;
537 uchar isa_dma_speed;
538 uchar isa_dma_channel;
539 uchar chip_version;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400540 ushort mcode_date;
541 ushort mcode_version;
542 uchar max_tag_qng[ASC_MAX_TID + 1];
543 uchar *overrun_buf;
544 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400545 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546} ASC_DVC_CFG;
547
548#define ASC_DEF_DVC_CNTL 0xFFFF
549#define ASC_DEF_CHIP_SCSI_ID 7
550#define ASC_DEF_ISA_DMA_SPEED 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
552#define ASC_INIT_STATE_END_GET_CFG 0x0002
553#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
554#define ASC_INIT_STATE_END_SET_CFG 0x0008
555#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
556#define ASC_INIT_STATE_END_LOAD_MC 0x0020
557#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
558#define ASC_INIT_STATE_END_INQUIRY 0x0080
559#define ASC_INIT_RESET_SCSI_DONE 0x0100
560#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
562#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563#define ASC_MIN_TAGGED_CMD 7
564#define ASC_MAX_SCSI_RESET_WAIT 30
565
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400566struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400569 PortAddr iop_base;
570 ushort err_code;
571 ushort dvc_cntl;
572 ushort bug_fix_cntl;
573 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400574 ASC_SCSI_BIT_ID_TYPE init_sdtr;
575 ASC_SCSI_BIT_ID_TYPE sdtr_done;
576 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
577 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
578 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
579 ASC_SCSI_BIT_ID_TYPE start_motor;
580 uchar scsi_reset_wait;
581 uchar chip_no;
582 char is_in_int;
583 uchar max_total_qng;
584 uchar cur_total_qng;
585 uchar in_critical_cnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400586 uchar last_q_shortage;
587 ushort init_state;
588 uchar cur_dvc_qng[ASC_MAX_TID + 1];
589 uchar max_dvc_qng[ASC_MAX_TID + 1];
590 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
591 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -0400592 const uchar *sdtr_period_tbl;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400593 ASC_DVC_CFG *cfg;
594 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
595 char redo_scam;
596 ushort res2;
597 uchar dos_int13_table[ASC_MAX_TID + 1];
598 ASC_DCNT max_dma_count;
599 ASC_SCSI_BIT_ID_TYPE no_scam;
600 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -0400601 uchar min_sdtr_index;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400602 uchar max_sdtr_index;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400603 struct asc_board *drv_ptr;
604 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605} ASC_DVC_VAR;
606
607typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400608 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609} ASC_DVC_INQ_INFO;
610
611typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400612 ASC_DCNT lba;
613 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614} ASC_CAP_INFO;
615
616typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400617 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618} ASC_CAP_INFO_ARRAY;
619
620#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
621#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
622#define ASC_CNTL_INITIATOR (ushort)0x0001
623#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
624#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
625#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
626#define ASC_CNTL_NO_SCAM (ushort)0x0010
627#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
628#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
629#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
630#define ASC_CNTL_RESET_SCSI (ushort)0x0200
631#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
632#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
633#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
634#define ASC_CNTL_BURST_MODE (ushort)0x2000
635#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
636#define ASC_EEP_DVC_CFG_BEG_VL 2
637#define ASC_EEP_MAX_DVC_ADDR_VL 15
638#define ASC_EEP_DVC_CFG_BEG 32
639#define ASC_EEP_MAX_DVC_ADDR 45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640#define ASC_EEP_MAX_RETRY 20
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642/*
643 * These macros keep the chip SCSI id and ISA DMA speed
644 * bitfields in board order. C bitfields aren't portable
645 * between big and little-endian platforms so they are
646 * not used.
647 */
648
649#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
650#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
651#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
652 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
653#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
654 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
655
656typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400657 ushort cfg_lsw;
658 ushort cfg_msw;
659 uchar init_sdtr;
660 uchar disc_enable;
661 uchar use_cmd_qng;
662 uchar start_motor;
663 uchar max_total_qng;
664 uchar max_tag_qng;
665 uchar bios_scan;
666 uchar power_up_wait;
667 uchar no_scam;
668 uchar id_speed; /* low order 4 bits is chip scsi id */
669 /* high order 4 bits is isa dma speed */
670 uchar dos_int13_table[ASC_MAX_TID + 1];
671 uchar adapter_info[6];
672 ushort cntl;
673 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674} ASCEEP_CONFIG;
675
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676#define ASC_EEP_CMD_READ 0x80
677#define ASC_EEP_CMD_WRITE 0x40
678#define ASC_EEP_CMD_WRITE_ABLE 0x30
679#define ASC_EEP_CMD_WRITE_DISABLE 0x00
680#define ASC_OVERRUN_BSIZE 0x00000048UL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681#define ASCV_MSGOUT_BEG 0x0000
682#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
683#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
684#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
685#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
686#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
687#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
688#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
689#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
690#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
691#define ASCV_BREAK_ADDR (ushort)0x0028
692#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
693#define ASCV_BREAK_CONTROL (ushort)0x002C
694#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
695
696#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
697#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
698#define ASCV_MCODE_SIZE_W (ushort)0x0034
699#define ASCV_STOP_CODE_B (ushort)0x0036
700#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
701#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
702#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
703#define ASCV_HALTCODE_W (ushort)0x0040
704#define ASCV_CHKSUM_W (ushort)0x0042
705#define ASCV_MC_DATE_W (ushort)0x0044
706#define ASCV_MC_VER_W (ushort)0x0046
707#define ASCV_NEXTRDY_B (ushort)0x0048
708#define ASCV_DONENEXT_B (ushort)0x0049
709#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
710#define ASCV_SCSIBUSY_B (ushort)0x004B
711#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
712#define ASCV_CURCDB_B (ushort)0x004D
713#define ASCV_RCLUN_B (ushort)0x004E
714#define ASCV_BUSY_QHEAD_B (ushort)0x004F
715#define ASCV_DISC1_QHEAD_B (ushort)0x0050
716#define ASCV_DISC_ENABLE_B (ushort)0x0052
717#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
718#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
719#define ASCV_MCODE_CNTL_B (ushort)0x0056
720#define ASCV_NULL_TARGET_B (ushort)0x0057
721#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
722#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
723#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
724#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
725#define ASCV_HOST_FLAG_B (ushort)0x005D
726#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
727#define ASCV_VER_SERIAL_B (ushort)0x0065
728#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
729#define ASCV_WTM_FLAG_B (ushort)0x0068
730#define ASCV_RISC_FLAG_B (ushort)0x006A
731#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
732#define ASC_HOST_FLAG_IN_ISR 0x01
733#define ASC_HOST_FLAG_ACK_INT 0x02
734#define ASC_RISC_FLAG_GEN_INT 0x01
735#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
736#define IOP_CTRL (0x0F)
737#define IOP_STATUS (0x0E)
738#define IOP_INT_ACK IOP_STATUS
739#define IOP_REG_IFC (0x0D)
740#define IOP_SYN_OFFSET (0x0B)
741#define IOP_EXTRA_CONTROL (0x0D)
742#define IOP_REG_PC (0x0C)
743#define IOP_RAM_ADDR (0x0A)
744#define IOP_RAM_DATA (0x08)
745#define IOP_EEP_DATA (0x06)
746#define IOP_EEP_CMD (0x07)
747#define IOP_VERSION (0x03)
748#define IOP_CONFIG_HIGH (0x04)
749#define IOP_CONFIG_LOW (0x02)
750#define IOP_SIG_BYTE (0x01)
751#define IOP_SIG_WORD (0x00)
752#define IOP_REG_DC1 (0x0E)
753#define IOP_REG_DC0 (0x0C)
754#define IOP_REG_SB (0x0B)
755#define IOP_REG_DA1 (0x0A)
756#define IOP_REG_DA0 (0x08)
757#define IOP_REG_SC (0x09)
758#define IOP_DMA_SPEED (0x07)
759#define IOP_REG_FLAG (0x07)
760#define IOP_FIFO_H (0x06)
761#define IOP_FIFO_L (0x04)
762#define IOP_REG_ID (0x05)
763#define IOP_REG_QP (0x03)
764#define IOP_REG_IH (0x02)
765#define IOP_REG_IX (0x01)
766#define IOP_REG_AX (0x00)
767#define IFC_REG_LOCK (0x00)
768#define IFC_REG_UNLOCK (0x09)
769#define IFC_WR_EN_FILTER (0x10)
770#define IFC_RD_NO_EEPROM (0x10)
771#define IFC_SLEW_RATE (0x20)
772#define IFC_ACT_NEG (0x40)
773#define IFC_INP_FILTER (0x80)
774#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
775#define SC_SEL (uchar)(0x80)
776#define SC_BSY (uchar)(0x40)
777#define SC_ACK (uchar)(0x20)
778#define SC_REQ (uchar)(0x10)
779#define SC_ATN (uchar)(0x08)
780#define SC_IO (uchar)(0x04)
781#define SC_CD (uchar)(0x02)
782#define SC_MSG (uchar)(0x01)
783#define SEC_SCSI_CTL (uchar)(0x80)
784#define SEC_ACTIVE_NEGATE (uchar)(0x40)
785#define SEC_SLEW_RATE (uchar)(0x20)
786#define SEC_ENABLE_FILTER (uchar)(0x10)
787#define ASC_HALT_EXTMSG_IN (ushort)0x8000
788#define ASC_HALT_CHK_CONDITION (ushort)0x8100
789#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
790#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
791#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
792#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
793#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
794#define ASC_MAX_QNO 0xF8
795#define ASC_DATA_SEC_BEG (ushort)0x0080
796#define ASC_DATA_SEC_END (ushort)0x0080
797#define ASC_CODE_SEC_BEG (ushort)0x0080
798#define ASC_CODE_SEC_END (ushort)0x0080
799#define ASC_QADR_BEG (0x4000)
800#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
801#define ASC_QADR_END (ushort)0x7FFF
802#define ASC_QLAST_ADR (ushort)0x7FC0
803#define ASC_QBLK_SIZE 0x40
804#define ASC_BIOS_DATA_QBEG 0xF8
805#define ASC_MIN_ACTIVE_QNO 0x01
806#define ASC_QLINK_END 0xFF
807#define ASC_EEPROM_WORDS 0x10
808#define ASC_MAX_MGS_LEN 0x10
809#define ASC_BIOS_ADDR_DEF 0xDC00
810#define ASC_BIOS_SIZE 0x3800
811#define ASC_BIOS_RAM_OFF 0x3800
812#define ASC_BIOS_RAM_SIZE 0x800
813#define ASC_BIOS_MIN_ADDR 0xC000
814#define ASC_BIOS_MAX_ADDR 0xEC00
815#define ASC_BIOS_BANK_SIZE 0x0400
816#define ASC_MCODE_START_ADDR 0x0080
817#define ASC_CFG0_HOST_INT_ON 0x0020
818#define ASC_CFG0_BIOS_ON 0x0040
819#define ASC_CFG0_VERA_BURST_ON 0x0080
820#define ASC_CFG0_SCSI_PARITY_ON 0x0800
821#define ASC_CFG1_SCSI_TARGET_ON 0x0080
822#define ASC_CFG1_LRAM_8BITS_ON 0x0800
823#define ASC_CFG_MSW_CLR_MASK 0x3080
824#define CSW_TEST1 (ASC_CS_TYPE)0x8000
825#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
826#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
827#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
828#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
829#define CSW_TEST2 (ASC_CS_TYPE)0x0400
830#define CSW_TEST3 (ASC_CS_TYPE)0x0200
831#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
832#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
833#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
834#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
835#define CSW_HALTED (ASC_CS_TYPE)0x0010
836#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
837#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
838#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
839#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
840#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
841#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
842#define CIW_TEST1 (ASC_CS_TYPE)0x0200
843#define CIW_TEST2 (ASC_CS_TYPE)0x0400
844#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
845#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
846#define CC_CHIP_RESET (uchar)0x80
847#define CC_SCSI_RESET (uchar)0x40
848#define CC_HALT (uchar)0x20
849#define CC_SINGLE_STEP (uchar)0x10
850#define CC_DMA_ABLE (uchar)0x08
851#define CC_TEST (uchar)0x04
852#define CC_BANK_ONE (uchar)0x02
853#define CC_DIAG (uchar)0x01
854#define ASC_1000_ID0W 0x04C1
855#define ASC_1000_ID0W_FIX 0x00C1
856#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857#define ASC_EISA_REV_IOP_MASK (0x0C83)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858#define ASC_EISA_CFG_IOP_MASK (0x0C86)
859#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860#define INS_HALTINT (ushort)0x6281
861#define INS_HALT (ushort)0x6280
862#define INS_SINT (ushort)0x6200
863#define INS_RFLAG_WTM (ushort)0x7380
864#define ASC_MC_SAVE_CODE_WSIZE 0x500
865#define ASC_MC_SAVE_DATA_WSIZE 0x40
866
867typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400868 ushort data[ASC_MC_SAVE_DATA_WSIZE];
869 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870} ASC_MC_SAVED;
871
872#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
873#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
874#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
875#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
876#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
877#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
878#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
879#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
880#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
881#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
Matthew Wilcox51219352007-10-02 21:55:22 -0400882#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data))
883#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id))
884#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data)
885#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
887#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
888#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
889#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
890#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
891#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
892#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
893#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
894#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
895#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
896#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
897#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
898#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
899#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
900#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
901#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
902#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
903#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
904#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
905#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
906#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
907#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
908#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
909#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
910#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
911#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
912#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
913#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
914#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
915#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
916#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
917#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
918#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
919#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
920#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
921#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
922#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
923#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
924#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
925#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
926#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
927#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
928#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
929#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
930#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
931#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
932#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
933#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
934#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
935#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
936#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
937#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
938#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
939
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940/*
941 * Portable Data Types
942 *
943 * Any instance where a 32-bit long or pointer type is assumed
944 * for precision or HW defined structures, the following define
945 * types must be used. In Linux the char, short, and int types
946 * are all consistent at 8, 16, and 32 bits respectively. Pointers
947 * and long types are 64 bits on Alpha and UltraSPARC.
948 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400949#define ADV_PADDR __u32 /* Physical address data type. */
950#define ADV_VADDR __u32 /* Virtual address data type. */
951#define ADV_DCNT __u32 /* Unsigned Data count type. */
952#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
954/*
955 * These macros are used to convert a virtual address to a
956 * 32-bit value. This currently can be used on Linux Alpha
957 * which uses 64-bit virtual address but a 32-bit bus address.
958 * This is likely to break in the future, but doing this now
959 * will give us time to change the HW and FW to handle 64-bit
960 * addresses.
961 */
962#define ADV_VADDR_TO_U32 virt_to_bus
963#define ADV_U32_TO_VADDR bus_to_virt
964
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400965#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966
967/*
968 * Define Adv Library required memory access macros.
969 */
970#define ADV_MEM_READB(addr) readb(addr)
971#define ADV_MEM_READW(addr) readw(addr)
972#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
973#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
974#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
975
976#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
977
978/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 * Define total number of simultaneous maximum element scatter-gather
980 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
981 * maximum number of outstanding commands per wide host adapter. Each
982 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
983 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
984 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
985 * structures or 255 scatter-gather elements.
986 *
987 */
988#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
989
990/*
991 * Define Adv Library required maximum number of scatter-gather
992 * elements per request.
993 */
994#define ADV_MAX_SG_LIST 255
995
996/* Number of SG blocks needed. */
997#define ADV_NUM_SG_BLOCK \
998 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
999
1000/* Total contiguous memory needed for SG blocks. */
1001#define ADV_SG_TOTAL_MEM_SIZE \
1002 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1003
1004#define ADV_PAGE_SIZE PAGE_SIZE
1005
1006#define ADV_NUM_PAGE_CROSSING \
1007 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1010#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001011#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1013
1014#define ADV_EEP_DELAY_MS 100
1015
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001016#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1017#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018/*
1019 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1020 * For later ICs Bit 13 controls whether the CIS (Card Information
1021 * Service Section) is loaded from EEPROM.
1022 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001023#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1024#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025/*
1026 * ASC38C1600 Bit 11
1027 *
1028 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1029 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1030 * Function 0 will specify INT B.
1031 *
1032 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1033 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1034 * Function 1 will specify INT A.
1035 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001036#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001038typedef struct adveep_3550_config {
1039 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001041 ushort cfg_lsw; /* 00 power up initialization */
1042 /* bit 13 set - Term Polarity Control */
1043 /* bit 14 set - BIOS Enable */
1044 /* bit 15 set - Big Endian Mode */
1045 ushort cfg_msw; /* 01 unused */
1046 ushort disc_enable; /* 02 disconnect enable */
1047 ushort wdtr_able; /* 03 Wide DTR able */
1048 ushort sdtr_able; /* 04 Synchronous DTR able */
1049 ushort start_motor; /* 05 send start up motor */
1050 ushort tagqng_able; /* 06 tag queuing able */
1051 ushort bios_scan; /* 07 BIOS device control */
1052 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001054 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1055 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001057 uchar scsi_reset_delay; /* 10 reset delay */
1058 uchar bios_id_lun; /* first boot device scsi id & lun */
1059 /* high nibble is lun */
1060 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001062 uchar termination; /* 11 0 - automatic */
1063 /* 1 - low off / high off */
1064 /* 2 - low off / high on */
1065 /* 3 - low on / high on */
1066 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001068 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001070 ushort bios_ctrl; /* 12 BIOS control bits */
1071 /* bit 0 BIOS don't act as initiator. */
1072 /* bit 1 BIOS > 1 GB support */
1073 /* bit 2 BIOS > 2 Disk Support */
1074 /* bit 3 BIOS don't support removables */
1075 /* bit 4 BIOS support bootable CD */
1076 /* bit 5 BIOS scan enabled */
1077 /* bit 6 BIOS support multiple LUNs */
1078 /* bit 7 BIOS display of message */
1079 /* bit 8 SCAM disabled */
1080 /* bit 9 Reset SCSI bus during init. */
1081 /* bit 10 */
1082 /* bit 11 No verbose initialization. */
1083 /* bit 12 SCSI parity enabled */
1084 /* bit 13 */
1085 /* bit 14 */
1086 /* bit 15 */
1087 ushort ultra_able; /* 13 ULTRA speed able */
1088 ushort reserved2; /* 14 reserved */
1089 uchar max_host_qng; /* 15 maximum host queuing */
1090 uchar max_dvc_qng; /* maximum per device queuing */
1091 ushort dvc_cntl; /* 16 control bit for driver */
1092 ushort bug_fix; /* 17 control bit for bug fix */
1093 ushort serial_number_word1; /* 18 Board serial number word 1 */
1094 ushort serial_number_word2; /* 19 Board serial number word 2 */
1095 ushort serial_number_word3; /* 20 Board serial number word 3 */
1096 ushort check_sum; /* 21 EEP check sum */
1097 uchar oem_name[16]; /* 22 OEM name */
1098 ushort dvc_err_code; /* 30 last device driver error code */
1099 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1100 ushort adv_err_addr; /* 32 last uc error address */
1101 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1102 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1103 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1104 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105} ADVEEP_3550_CONFIG;
1106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001107typedef struct adveep_38C0800_config {
1108 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001110 ushort cfg_lsw; /* 00 power up initialization */
1111 /* bit 13 set - Load CIS */
1112 /* bit 14 set - BIOS Enable */
1113 /* bit 15 set - Big Endian Mode */
1114 ushort cfg_msw; /* 01 unused */
1115 ushort disc_enable; /* 02 disconnect enable */
1116 ushort wdtr_able; /* 03 Wide DTR able */
1117 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1118 ushort start_motor; /* 05 send start up motor */
1119 ushort tagqng_able; /* 06 tag queuing able */
1120 ushort bios_scan; /* 07 BIOS device control */
1121 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001123 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1124 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001126 uchar scsi_reset_delay; /* 10 reset delay */
1127 uchar bios_id_lun; /* first boot device scsi id & lun */
1128 /* high nibble is lun */
1129 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001131 uchar termination_se; /* 11 0 - automatic */
1132 /* 1 - low off / high off */
1133 /* 2 - low off / high on */
1134 /* 3 - low on / high on */
1135 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001137 uchar termination_lvd; /* 11 0 - automatic */
1138 /* 1 - low off / high off */
1139 /* 2 - low off / high on */
1140 /* 3 - low on / high on */
1141 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001143 ushort bios_ctrl; /* 12 BIOS control bits */
1144 /* bit 0 BIOS don't act as initiator. */
1145 /* bit 1 BIOS > 1 GB support */
1146 /* bit 2 BIOS > 2 Disk Support */
1147 /* bit 3 BIOS don't support removables */
1148 /* bit 4 BIOS support bootable CD */
1149 /* bit 5 BIOS scan enabled */
1150 /* bit 6 BIOS support multiple LUNs */
1151 /* bit 7 BIOS display of message */
1152 /* bit 8 SCAM disabled */
1153 /* bit 9 Reset SCSI bus during init. */
1154 /* bit 10 */
1155 /* bit 11 No verbose initialization. */
1156 /* bit 12 SCSI parity enabled */
1157 /* bit 13 */
1158 /* bit 14 */
1159 /* bit 15 */
1160 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1161 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1162 uchar max_host_qng; /* 15 maximum host queueing */
1163 uchar max_dvc_qng; /* maximum per device queuing */
1164 ushort dvc_cntl; /* 16 control bit for driver */
1165 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1166 ushort serial_number_word1; /* 18 Board serial number word 1 */
1167 ushort serial_number_word2; /* 19 Board serial number word 2 */
1168 ushort serial_number_word3; /* 20 Board serial number word 3 */
1169 ushort check_sum; /* 21 EEP check sum */
1170 uchar oem_name[16]; /* 22 OEM name */
1171 ushort dvc_err_code; /* 30 last device driver error code */
1172 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1173 ushort adv_err_addr; /* 32 last uc error address */
1174 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1175 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1176 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1177 ushort reserved36; /* 36 reserved */
1178 ushort reserved37; /* 37 reserved */
1179 ushort reserved38; /* 38 reserved */
1180 ushort reserved39; /* 39 reserved */
1181 ushort reserved40; /* 40 reserved */
1182 ushort reserved41; /* 41 reserved */
1183 ushort reserved42; /* 42 reserved */
1184 ushort reserved43; /* 43 reserved */
1185 ushort reserved44; /* 44 reserved */
1186 ushort reserved45; /* 45 reserved */
1187 ushort reserved46; /* 46 reserved */
1188 ushort reserved47; /* 47 reserved */
1189 ushort reserved48; /* 48 reserved */
1190 ushort reserved49; /* 49 reserved */
1191 ushort reserved50; /* 50 reserved */
1192 ushort reserved51; /* 51 reserved */
1193 ushort reserved52; /* 52 reserved */
1194 ushort reserved53; /* 53 reserved */
1195 ushort reserved54; /* 54 reserved */
1196 ushort reserved55; /* 55 reserved */
1197 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1198 ushort cisprt_msw; /* 57 CIS PTR MSW */
1199 ushort subsysvid; /* 58 SubSystem Vendor ID */
1200 ushort subsysid; /* 59 SubSystem ID */
1201 ushort reserved60; /* 60 reserved */
1202 ushort reserved61; /* 61 reserved */
1203 ushort reserved62; /* 62 reserved */
1204 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205} ADVEEP_38C0800_CONFIG;
1206
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001207typedef struct adveep_38C1600_config {
1208 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001210 ushort cfg_lsw; /* 00 power up initialization */
1211 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1212 /* clear - Func. 0 INTA, Func. 1 INTB */
1213 /* bit 13 set - Load CIS */
1214 /* bit 14 set - BIOS Enable */
1215 /* bit 15 set - Big Endian Mode */
1216 ushort cfg_msw; /* 01 unused */
1217 ushort disc_enable; /* 02 disconnect enable */
1218 ushort wdtr_able; /* 03 Wide DTR able */
1219 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1220 ushort start_motor; /* 05 send start up motor */
1221 ushort tagqng_able; /* 06 tag queuing able */
1222 ushort bios_scan; /* 07 BIOS device control */
1223 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001225 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1226 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001228 uchar scsi_reset_delay; /* 10 reset delay */
1229 uchar bios_id_lun; /* first boot device scsi id & lun */
1230 /* high nibble is lun */
1231 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001233 uchar termination_se; /* 11 0 - automatic */
1234 /* 1 - low off / high off */
1235 /* 2 - low off / high on */
1236 /* 3 - low on / high on */
1237 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001239 uchar termination_lvd; /* 11 0 - automatic */
1240 /* 1 - low off / high off */
1241 /* 2 - low off / high on */
1242 /* 3 - low on / high on */
1243 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001245 ushort bios_ctrl; /* 12 BIOS control bits */
1246 /* bit 0 BIOS don't act as initiator. */
1247 /* bit 1 BIOS > 1 GB support */
1248 /* bit 2 BIOS > 2 Disk Support */
1249 /* bit 3 BIOS don't support removables */
1250 /* bit 4 BIOS support bootable CD */
1251 /* bit 5 BIOS scan enabled */
1252 /* bit 6 BIOS support multiple LUNs */
1253 /* bit 7 BIOS display of message */
1254 /* bit 8 SCAM disabled */
1255 /* bit 9 Reset SCSI bus during init. */
1256 /* bit 10 Basic Integrity Checking disabled */
1257 /* bit 11 No verbose initialization. */
1258 /* bit 12 SCSI parity enabled */
1259 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1260 /* bit 14 */
1261 /* bit 15 */
1262 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1263 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1264 uchar max_host_qng; /* 15 maximum host queueing */
1265 uchar max_dvc_qng; /* maximum per device queuing */
1266 ushort dvc_cntl; /* 16 control bit for driver */
1267 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1268 ushort serial_number_word1; /* 18 Board serial number word 1 */
1269 ushort serial_number_word2; /* 19 Board serial number word 2 */
1270 ushort serial_number_word3; /* 20 Board serial number word 3 */
1271 ushort check_sum; /* 21 EEP check sum */
1272 uchar oem_name[16]; /* 22 OEM name */
1273 ushort dvc_err_code; /* 30 last device driver error code */
1274 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1275 ushort adv_err_addr; /* 32 last uc error address */
1276 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1277 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1278 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1279 ushort reserved36; /* 36 reserved */
1280 ushort reserved37; /* 37 reserved */
1281 ushort reserved38; /* 38 reserved */
1282 ushort reserved39; /* 39 reserved */
1283 ushort reserved40; /* 40 reserved */
1284 ushort reserved41; /* 41 reserved */
1285 ushort reserved42; /* 42 reserved */
1286 ushort reserved43; /* 43 reserved */
1287 ushort reserved44; /* 44 reserved */
1288 ushort reserved45; /* 45 reserved */
1289 ushort reserved46; /* 46 reserved */
1290 ushort reserved47; /* 47 reserved */
1291 ushort reserved48; /* 48 reserved */
1292 ushort reserved49; /* 49 reserved */
1293 ushort reserved50; /* 50 reserved */
1294 ushort reserved51; /* 51 reserved */
1295 ushort reserved52; /* 52 reserved */
1296 ushort reserved53; /* 53 reserved */
1297 ushort reserved54; /* 54 reserved */
1298 ushort reserved55; /* 55 reserved */
1299 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1300 ushort cisprt_msw; /* 57 CIS PTR MSW */
1301 ushort subsysvid; /* 58 SubSystem Vendor ID */
1302 ushort subsysid; /* 59 SubSystem ID */
1303 ushort reserved60; /* 60 reserved */
1304 ushort reserved61; /* 61 reserved */
1305 ushort reserved62; /* 62 reserved */
1306 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307} ADVEEP_38C1600_CONFIG;
1308
1309/*
1310 * EEPROM Commands
1311 */
1312#define ASC_EEP_CMD_DONE 0x0200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
1314/* bios_ctrl */
1315#define BIOS_CTRL_BIOS 0x0001
1316#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1317#define BIOS_CTRL_GT_2_DISK 0x0004
1318#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1319#define BIOS_CTRL_BOOTABLE_CD 0x0010
1320#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1321#define BIOS_CTRL_DISPLAY_MSG 0x0080
1322#define BIOS_CTRL_NO_SCAM 0x0100
1323#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1324#define BIOS_CTRL_INIT_VERBOSE 0x0800
1325#define BIOS_CTRL_SCSI_PARITY 0x1000
1326#define BIOS_CTRL_AIPP_DIS 0x2000
1327
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001328#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001330#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
1332/*
1333 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1334 * a special 16K Adv Library and Microcode version. After the issue is
1335 * resolved, should restore 32K support.
1336 *
1337 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1338 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001339#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
1341/*
1342 * Byte I/O register address from base of 'iop_base'.
1343 */
1344#define IOPB_INTR_STATUS_REG 0x00
1345#define IOPB_CHIP_ID_1 0x01
1346#define IOPB_INTR_ENABLES 0x02
1347#define IOPB_CHIP_TYPE_REV 0x03
1348#define IOPB_RES_ADDR_4 0x04
1349#define IOPB_RES_ADDR_5 0x05
1350#define IOPB_RAM_DATA 0x06
1351#define IOPB_RES_ADDR_7 0x07
1352#define IOPB_FLAG_REG 0x08
1353#define IOPB_RES_ADDR_9 0x09
1354#define IOPB_RISC_CSR 0x0A
1355#define IOPB_RES_ADDR_B 0x0B
1356#define IOPB_RES_ADDR_C 0x0C
1357#define IOPB_RES_ADDR_D 0x0D
1358#define IOPB_SOFT_OVER_WR 0x0E
1359#define IOPB_RES_ADDR_F 0x0F
1360#define IOPB_MEM_CFG 0x10
1361#define IOPB_RES_ADDR_11 0x11
1362#define IOPB_GPIO_DATA 0x12
1363#define IOPB_RES_ADDR_13 0x13
1364#define IOPB_FLASH_PAGE 0x14
1365#define IOPB_RES_ADDR_15 0x15
1366#define IOPB_GPIO_CNTL 0x16
1367#define IOPB_RES_ADDR_17 0x17
1368#define IOPB_FLASH_DATA 0x18
1369#define IOPB_RES_ADDR_19 0x19
1370#define IOPB_RES_ADDR_1A 0x1A
1371#define IOPB_RES_ADDR_1B 0x1B
1372#define IOPB_RES_ADDR_1C 0x1C
1373#define IOPB_RES_ADDR_1D 0x1D
1374#define IOPB_RES_ADDR_1E 0x1E
1375#define IOPB_RES_ADDR_1F 0x1F
1376#define IOPB_DMA_CFG0 0x20
1377#define IOPB_DMA_CFG1 0x21
1378#define IOPB_TICKLE 0x22
1379#define IOPB_DMA_REG_WR 0x23
1380#define IOPB_SDMA_STATUS 0x24
1381#define IOPB_SCSI_BYTE_CNT 0x25
1382#define IOPB_HOST_BYTE_CNT 0x26
1383#define IOPB_BYTE_LEFT_TO_XFER 0x27
1384#define IOPB_BYTE_TO_XFER_0 0x28
1385#define IOPB_BYTE_TO_XFER_1 0x29
1386#define IOPB_BYTE_TO_XFER_2 0x2A
1387#define IOPB_BYTE_TO_XFER_3 0x2B
1388#define IOPB_ACC_GRP 0x2C
1389#define IOPB_RES_ADDR_2D 0x2D
1390#define IOPB_DEV_ID 0x2E
1391#define IOPB_RES_ADDR_2F 0x2F
1392#define IOPB_SCSI_DATA 0x30
1393#define IOPB_RES_ADDR_31 0x31
1394#define IOPB_RES_ADDR_32 0x32
1395#define IOPB_SCSI_DATA_HSHK 0x33
1396#define IOPB_SCSI_CTRL 0x34
1397#define IOPB_RES_ADDR_35 0x35
1398#define IOPB_RES_ADDR_36 0x36
1399#define IOPB_RES_ADDR_37 0x37
1400#define IOPB_RAM_BIST 0x38
1401#define IOPB_PLL_TEST 0x39
1402#define IOPB_PCI_INT_CFG 0x3A
1403#define IOPB_RES_ADDR_3B 0x3B
1404#define IOPB_RFIFO_CNT 0x3C
1405#define IOPB_RES_ADDR_3D 0x3D
1406#define IOPB_RES_ADDR_3E 0x3E
1407#define IOPB_RES_ADDR_3F 0x3F
1408
1409/*
1410 * Word I/O register address from base of 'iop_base'.
1411 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001412#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1413#define IOPW_CTRL_REG 0x02 /* CC */
1414#define IOPW_RAM_ADDR 0x04 /* LA */
1415#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001417#define IOPW_RISC_CSR 0x0A /* CSR */
1418#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1419#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001421#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001423#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001425#define IOPW_EE_CMD 0x1A /* EC */
1426#define IOPW_EE_DATA 0x1C /* ED */
1427#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001429#define IOPW_Q_BASE 0x22 /* QB */
1430#define IOPW_QP 0x24 /* QP */
1431#define IOPW_IX 0x26 /* IX */
1432#define IOPW_SP 0x28 /* SP */
1433#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434#define IOPW_RES_ADDR_2C 0x2C
1435#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001436#define IOPW_SCSI_DATA 0x30 /* SD */
1437#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1438#define IOPW_SCSI_CTRL 0x34 /* SC */
1439#define IOPW_HSHK_CFG 0x36 /* HCFG */
1440#define IOPW_SXFR_STATUS 0x36 /* SXS */
1441#define IOPW_SXFR_CNTL 0x38 /* SXL */
1442#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001444#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
1446/*
1447 * Doubleword I/O register address from base of 'iop_base'.
1448 */
1449#define IOPDW_RES_ADDR_0 0x00
1450#define IOPDW_RAM_DATA 0x04
1451#define IOPDW_RES_ADDR_8 0x08
1452#define IOPDW_RES_ADDR_C 0x0C
1453#define IOPDW_RES_ADDR_10 0x10
1454#define IOPDW_COMMA 0x14
1455#define IOPDW_COMMB 0x18
1456#define IOPDW_RES_ADDR_1C 0x1C
1457#define IOPDW_SDMA_ADDR0 0x20
1458#define IOPDW_SDMA_ADDR1 0x24
1459#define IOPDW_SDMA_COUNT 0x28
1460#define IOPDW_SDMA_ERROR 0x2C
1461#define IOPDW_RDMA_ADDR0 0x30
1462#define IOPDW_RDMA_ADDR1 0x34
1463#define IOPDW_RDMA_COUNT 0x38
1464#define IOPDW_RDMA_ERROR 0x3C
1465
1466#define ADV_CHIP_ID_BYTE 0x25
1467#define ADV_CHIP_ID_WORD 0x04C1
1468
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469#define ADV_INTR_ENABLE_HOST_INTR 0x01
1470#define ADV_INTR_ENABLE_SEL_INTR 0x02
1471#define ADV_INTR_ENABLE_DPR_INTR 0x04
1472#define ADV_INTR_ENABLE_RTA_INTR 0x08
1473#define ADV_INTR_ENABLE_RMA_INTR 0x10
1474#define ADV_INTR_ENABLE_RST_INTR 0x20
1475#define ADV_INTR_ENABLE_DPE_INTR 0x40
1476#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1477
1478#define ADV_INTR_STATUS_INTRA 0x01
1479#define ADV_INTR_STATUS_INTRB 0x02
1480#define ADV_INTR_STATUS_INTRC 0x04
1481
1482#define ADV_RISC_CSR_STOP (0x0000)
1483#define ADV_RISC_TEST_COND (0x2000)
1484#define ADV_RISC_CSR_RUN (0x4000)
1485#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1486
1487#define ADV_CTRL_REG_HOST_INTR 0x0100
1488#define ADV_CTRL_REG_SEL_INTR 0x0200
1489#define ADV_CTRL_REG_DPR_INTR 0x0400
1490#define ADV_CTRL_REG_RTA_INTR 0x0800
1491#define ADV_CTRL_REG_RMA_INTR 0x1000
1492#define ADV_CTRL_REG_RES_BIT14 0x2000
1493#define ADV_CTRL_REG_DPE_INTR 0x4000
1494#define ADV_CTRL_REG_POWER_DONE 0x8000
1495#define ADV_CTRL_REG_ANY_INTR 0xFF00
1496
1497#define ADV_CTRL_REG_CMD_RESET 0x00C6
1498#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1499#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1500#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1501#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1502
1503#define ADV_TICKLE_NOP 0x00
1504#define ADV_TICKLE_A 0x01
1505#define ADV_TICKLE_B 0x02
1506#define ADV_TICKLE_C 0x03
1507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508#define AdvIsIntPending(port) \
1509 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1510
1511/*
1512 * SCSI_CFG0 Register bit definitions
1513 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001514#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1515#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1516#define EVEN_PARITY 0x1000 /* Select Even Parity */
1517#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1518#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1519#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1520#define SCAM_EN 0x0080 /* Enable SCAM selection */
1521#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1522#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1523#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1524#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
1526/*
1527 * SCSI_CFG1 Register bit definitions
1528 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001529#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1530#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1531#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1532#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1533#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1534#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1535#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1536#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1537#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1538#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1539#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1540#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1541#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1542#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1543#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
1545/*
1546 * Addendum for ASC-38C0800 Chip
1547 *
1548 * The ASC-38C1600 Chip uses the same definitions except that the
1549 * bus mode override bits [12:10] have been moved to byte register
1550 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1551 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1552 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1553 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1554 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1555 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001556#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1557#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1558#define HVD 0x1000 /* HVD Device Detect */
1559#define LVD 0x0800 /* LVD Device Detect */
1560#define SE 0x0400 /* SE Device Detect */
1561#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1562#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1563#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1564#define TERM_SE 0x0030 /* SE Termination Bits */
1565#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1566#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1567#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1568#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1569#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1570#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1571#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1572#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
1574#define CABLE_ILLEGAL_A 0x7
1575 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1576
1577#define CABLE_ILLEGAL_B 0xB
1578 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1579
1580/*
1581 * MEM_CFG Register bit definitions
1582 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001583#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1584#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1585#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1586#define RAM_SZ_2KB 0x00 /* 2 KB */
1587#define RAM_SZ_4KB 0x04 /* 4 KB */
1588#define RAM_SZ_8KB 0x08 /* 8 KB */
1589#define RAM_SZ_16KB 0x0C /* 16 KB */
1590#define RAM_SZ_32KB 0x10 /* 32 KB */
1591#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
1593/*
1594 * DMA_CFG0 Register bit definitions
1595 *
1596 * This register is only accessible to the host.
1597 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001598#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1599#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1600#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1601#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1602#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1603#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1604#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1605#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1606#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1607#define START_CTL 0x0C /* DMA start conditions */
1608#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1609#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1610#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1611#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1612#define READ_CMD 0x03 /* Memory Read Method */
1613#define READ_CMD_MR 0x00 /* Memory Read */
1614#define READ_CMD_MRL 0x02 /* Memory Read Long */
1615#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
1617/*
1618 * ASC-38C0800 RAM BIST Register bit definitions
1619 */
1620#define RAM_TEST_MODE 0x80
1621#define PRE_TEST_MODE 0x40
1622#define NORMAL_MODE 0x00
1623#define RAM_TEST_DONE 0x10
1624#define RAM_TEST_STATUS 0x0F
1625#define RAM_TEST_HOST_ERROR 0x08
1626#define RAM_TEST_INTRAM_ERROR 0x04
1627#define RAM_TEST_RISC_ERROR 0x02
1628#define RAM_TEST_SCSI_ERROR 0x01
1629#define RAM_TEST_SUCCESS 0x00
1630#define PRE_TEST_VALUE 0x05
1631#define NORMAL_VALUE 0x00
1632
1633/*
1634 * ASC38C1600 Definitions
1635 *
1636 * IOPB_PCI_INT_CFG Bit Field Definitions
1637 */
1638
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001639#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641/*
1642 * Bit 1 can be set to change the interrupt for the Function to operate in
1643 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1644 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1645 * mode, otherwise the operating mode is undefined.
1646 */
1647#define TOTEMPOLE 0x02
1648
1649/*
1650 * Bit 0 can be used to change the Int Pin for the Function. The value is
1651 * 0 by default for both Functions with Function 0 using INT A and Function
1652 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1653 * INT A is used.
1654 *
1655 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1656 * value specified in the PCI Configuration Space.
1657 */
1658#define INTAB 0x01
1659
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660/*
1661 * Adv Library Status Definitions
1662 */
1663#define ADV_TRUE 1
1664#define ADV_FALSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665#define ADV_SUCCESS 1
1666#define ADV_BUSY 0
1667#define ADV_ERROR (-1)
1668
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669/*
1670 * ADV_DVC_VAR 'warn_code' values
1671 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001672#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1673#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1674#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001675#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001677#define ADV_MAX_TID 15 /* max. target identifier */
1678#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
1680/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 * Fixed locations of microcode operating variables.
1682 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001683#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1684#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1685#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1686#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1687#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1688#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1689#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1690#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1691#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1692#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1693#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1694#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1695#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696#define ASC_MC_CHIP_TYPE 0x009A
1697#define ASC_MC_INTRB_CODE 0x009B
1698#define ASC_MC_WDTR_ABLE 0x009C
1699#define ASC_MC_SDTR_ABLE 0x009E
1700#define ASC_MC_TAGQNG_ABLE 0x00A0
1701#define ASC_MC_DISC_ENABLE 0x00A2
1702#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1703#define ASC_MC_IDLE_CMD 0x00A6
1704#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1705#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1706#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1707#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1708#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1709#define ASC_MC_SDTR_DONE 0x00B6
1710#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1711#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1712#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001713#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001715#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716#define ASC_MC_ICQ 0x0160
1717#define ASC_MC_IRQ 0x0164
1718#define ASC_MC_PPR_ABLE 0x017A
1719
1720/*
1721 * BIOS LRAM variable absolute offsets.
1722 */
1723#define BIOS_CODESEG 0x54
1724#define BIOS_CODELEN 0x56
1725#define BIOS_SIGNATURE 0x58
1726#define BIOS_VERSION 0x5A
1727
1728/*
1729 * Microcode Control Flags
1730 *
1731 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1732 * and handled by the microcode.
1733 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001734#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1735#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
1737/*
1738 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1739 */
1740#define HSHK_CFG_WIDE_XFR 0x8000
1741#define HSHK_CFG_RATE 0x0F00
1742#define HSHK_CFG_OFFSET 0x001F
1743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001744#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1745#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1746#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1747#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001749#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
1750#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
1751#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
1752#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
1753#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001755#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
1756#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
1757#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
1758#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
1759#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760/*
1761 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
1762 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
1763 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001764#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
1765#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
1767/*
1768 * All fields here are accessed by the board microcode and need to be
1769 * little-endian.
1770 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001771typedef struct adv_carr_t {
1772 ADV_VADDR carr_va; /* Carrier Virtual Address */
1773 ADV_PADDR carr_pa; /* Carrier Physical Address */
1774 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
1775 /*
1776 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
1777 *
1778 * next_vpa [3:1] Reserved Bits
1779 * next_vpa [0] Done Flag set in Response Queue.
1780 */
1781 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782} ADV_CARR_T;
1783
1784/*
1785 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
1786 */
1787#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
1788
1789#define ASC_RQ_DONE 0x00000001
1790#define ASC_RQ_GOOD 0x00000002
1791#define ASC_CQ_STOPPER 0x00000000
1792
1793#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
1794
1795#define ADV_CARRIER_NUM_PAGE_CROSSING \
1796 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
1797 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1798
1799#define ADV_CARRIER_BUFSIZE \
1800 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
1801
1802/*
1803 * ASC_SCSI_REQ_Q 'a_flag' definitions
1804 *
1805 * The Adv Library should limit use to the lower nibble (4 bits) of
1806 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
1807 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001808#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
1809#define ADV_SCSIQ_DONE 0x02 /* request done */
1810#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001812#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
1813#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
1814#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816/*
1817 * Adapter temporary configuration structure
1818 *
1819 * This structure can be discarded after initialization. Don't add
1820 * fields here needed after initialization.
1821 *
1822 * Field naming convention:
1823 *
1824 * *_enable indicates the field enables or disables a feature. The
1825 * value of the field is never reset.
1826 */
1827typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001828 ushort disc_enable; /* enable disconnection */
1829 uchar chip_version; /* chip version */
1830 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001831 ushort control_flag; /* Microcode Control Flag */
1832 ushort mcode_date; /* Microcode date */
1833 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001834 ushort serial1; /* EEPROM serial number word 1 */
1835 ushort serial2; /* EEPROM serial number word 2 */
1836 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837} ADV_DVC_CFG;
1838
1839struct adv_dvc_var;
1840struct adv_scsi_req_q;
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842/*
1843 * Adapter operation variable structure.
1844 *
1845 * One structure is required per host adapter.
1846 *
1847 * Field naming convention:
1848 *
1849 * *_able indicates both whether a feature should be enabled or disabled
1850 * and whether a device isi capable of the feature. At initialization
1851 * this field may be set, but later if a device is found to be incapable
1852 * of the feature, the field is cleared.
1853 */
1854typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001855 AdvPortAddr iop_base; /* I/O port address */
1856 ushort err_code; /* fatal error code */
1857 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001858 ushort wdtr_able; /* try WDTR for a device */
1859 ushort sdtr_able; /* try SDTR for a device */
1860 ushort ultra_able; /* try SDTR Ultra speed for a device */
1861 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
1862 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
1863 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
1864 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
1865 ushort tagqng_able; /* try tagged queuing with a device */
1866 ushort ppr_able; /* PPR message capable per TID bitmask. */
1867 uchar max_dvc_qng; /* maximum number of tagged commands per device */
1868 ushort start_motor; /* start motor command allowed */
1869 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
1870 uchar chip_no; /* should be assigned by caller */
1871 uchar max_host_qng; /* maximum number of Q'ed command allowed */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001872 ushort no_scam; /* scam_tolerant of EEPROM */
1873 struct asc_board *drv_ptr; /* driver pointer to private structure */
1874 uchar chip_scsi_id; /* chip SCSI target ID */
1875 uchar chip_type;
1876 uchar bist_err_code;
1877 ADV_CARR_T *carrier_buf;
1878 ADV_CARR_T *carr_freelist; /* Carrier free list. */
1879 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
1880 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
1881 ushort carr_pending_cnt; /* Count of pending carriers. */
1882 /*
1883 * Note: The following fields will not be used after initialization. The
1884 * driver may discard the buffer after initialization is done.
1885 */
1886 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887} ADV_DVC_VAR;
1888
1889#define NO_OF_SG_PER_BLOCK 15
1890
1891typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001892 uchar reserved1;
1893 uchar reserved2;
1894 uchar reserved3;
1895 uchar sg_cnt; /* Valid entries in block. */
1896 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
1897 struct {
1898 ADV_PADDR sg_addr; /* SG element address. */
1899 ADV_DCNT sg_count; /* SG element count. */
1900 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901} ADV_SG_BLOCK;
1902
1903/*
1904 * ADV_SCSI_REQ_Q - microcode request structure
1905 *
1906 * All fields in this structure up to byte 60 are used by the microcode.
1907 * The microcode makes assumptions about the size and ordering of fields
1908 * in this structure. Do not change the structure definition here without
1909 * coordinating the change with the microcode.
1910 *
1911 * All fields accessed by microcode must be maintained in little_endian
1912 * order.
1913 */
1914typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001915 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
1916 uchar target_cmd;
1917 uchar target_id; /* Device target identifier. */
1918 uchar target_lun; /* Device target logical unit number. */
1919 ADV_PADDR data_addr; /* Data buffer physical address. */
1920 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
1921 ADV_PADDR sense_addr;
1922 ADV_PADDR carr_pa;
1923 uchar mflag;
1924 uchar sense_len;
1925 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
1926 uchar scsi_cntl;
1927 uchar done_status; /* Completion status. */
1928 uchar scsi_status; /* SCSI status byte. */
1929 uchar host_status; /* Ucode host status. */
1930 uchar sg_working_ix;
1931 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
1932 ADV_PADDR sg_real_addr; /* SG list physical address. */
1933 ADV_PADDR scsiq_rptr;
1934 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
1935 ADV_VADDR scsiq_ptr;
1936 ADV_VADDR carr_va;
1937 /*
1938 * End of microcode structure - 60 bytes. The rest of the structure
1939 * is used by the Adv Library and ignored by the microcode.
1940 */
1941 ADV_VADDR srb_ptr;
1942 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
1943 char *vdata_addr; /* Data buffer virtual address. */
1944 uchar a_flag;
1945 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946} ADV_SCSI_REQ_Q;
1947
1948/*
1949 * Microcode idle loop commands
1950 */
1951#define IDLE_CMD_COMPLETED 0
1952#define IDLE_CMD_STOP_CHIP 0x0001
1953#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
1954#define IDLE_CMD_SEND_INT 0x0004
1955#define IDLE_CMD_ABORT 0x0008
1956#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001957#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
1958#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959#define IDLE_CMD_SCSIREQ 0x0080
1960
1961#define IDLE_CMD_STATUS_SUCCESS 0x0001
1962#define IDLE_CMD_STATUS_FAILURE 0x0002
1963
1964/*
1965 * AdvSendIdleCmd() flag definitions.
1966 */
1967#define ADV_NOWAIT 0x01
1968
1969/*
1970 * Wait loop time out values.
1971 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001972#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
1973#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001974#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001976#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
1977#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
1978#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
1979#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001981#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983/* Read byte from a register. */
1984#define AdvReadByteRegister(iop_base, reg_off) \
1985 (ADV_MEM_READB((iop_base) + (reg_off)))
1986
1987/* Write byte to a register. */
1988#define AdvWriteByteRegister(iop_base, reg_off, byte) \
1989 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
1990
1991/* Read word (2 bytes) from a register. */
1992#define AdvReadWordRegister(iop_base, reg_off) \
1993 (ADV_MEM_READW((iop_base) + (reg_off)))
1994
1995/* Write word (2 bytes) to a register. */
1996#define AdvWriteWordRegister(iop_base, reg_off, word) \
1997 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
1998
1999/* Write dword (4 bytes) to a register. */
2000#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2001 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2002
2003/* Read byte from LRAM. */
2004#define AdvReadByteLram(iop_base, addr, byte) \
2005do { \
2006 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2007 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2008} while (0)
2009
2010/* Write byte to LRAM. */
2011#define AdvWriteByteLram(iop_base, addr, byte) \
2012 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2013 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2014
2015/* Read word (2 bytes) from LRAM. */
2016#define AdvReadWordLram(iop_base, addr, word) \
2017do { \
2018 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2019 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2020} while (0)
2021
2022/* Write word (2 bytes) to LRAM. */
2023#define AdvWriteWordLram(iop_base, addr, word) \
2024 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2025 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2026
2027/* Write little-endian double word (4 bytes) to LRAM */
2028/* Because of unspecified C language ordering don't use auto-increment. */
2029#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2030 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2031 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2032 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2033 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2034 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2035 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2036
2037/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2038#define AdvReadWordAutoIncLram(iop_base) \
2039 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2040
2041/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2042#define AdvWriteWordAutoIncLram(iop_base, word) \
2043 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2044
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045/*
2046 * Define macro to check for Condor signature.
2047 *
2048 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2049 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2050 */
2051#define AdvFindSignature(iop_base) \
2052 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2053 ADV_CHIP_ID_BYTE) && \
2054 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2055 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2056
2057/*
2058 * Define macro to Return the version number of the chip at 'iop_base'.
2059 *
2060 * The second parameter 'bus_type' is currently unused.
2061 */
2062#define AdvGetChipVersion(iop_base, bus_type) \
2063 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2064
2065/*
2066 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2067 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2068 *
2069 * If the request has not yet been sent to the device it will simply be
2070 * aborted from RISC memory. If the request is disconnected it will be
2071 * aborted on reselection by sending an Abort Message to the target ID.
2072 *
2073 * Return value:
2074 * ADV_TRUE(1) - Queue was successfully aborted.
2075 * ADV_FALSE(0) - Queue was not found on the active queue list.
2076 */
2077#define AdvAbortQueue(asc_dvc, scsiq) \
2078 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2079 (ADV_DCNT) (scsiq))
2080
2081/*
2082 * Send a Bus Device Reset Message to the specified target ID.
2083 *
2084 * All outstanding commands will be purged if sending the
2085 * Bus Device Reset Message is successful.
2086 *
2087 * Return Value:
2088 * ADV_TRUE(1) - All requests on the target are purged.
2089 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2090 * are not purged.
2091 */
2092#define AdvResetDevice(asc_dvc, target_id) \
2093 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2094 (ADV_DCNT) (target_id))
2095
2096/*
2097 * SCSI Wide Type definition.
2098 */
2099#define ADV_SCSI_BIT_ID_TYPE ushort
2100
2101/*
2102 * AdvInitScsiTarget() 'cntl_flag' options.
2103 */
2104#define ADV_SCAN_LUN 0x01
2105#define ADV_CAPINFO_NOLUN 0x02
2106
2107/*
2108 * Convert target id to target id bit mask.
2109 */
2110#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2111
2112/*
2113 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2114 */
2115
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002116#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117#define QD_NO_ERROR 0x01
2118#define QD_ABORTED_BY_HOST 0x02
2119#define QD_WITH_ERROR 0x04
2120
2121#define QHSTA_NO_ERROR 0x00
2122#define QHSTA_M_SEL_TIMEOUT 0x11
2123#define QHSTA_M_DATA_OVER_RUN 0x12
2124#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2125#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002126#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2127#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2128#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2129#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2130#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2131#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2132#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002134#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2135#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2136#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2137#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2138#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2139#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2140#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2141#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142#define QHSTA_M_WTM_TIMEOUT 0x41
2143#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2144#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2145#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002146#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2147#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2148#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
2150/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 * DvcGetPhyAddr() flag arguments
2152 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002153#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2154#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2155#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2156#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2157#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2158#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2161#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2162#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2163#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2164
2165/*
2166 * Total contiguous memory needed for driver SG blocks.
2167 *
2168 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2169 * number of scatter-gather elements the driver supports in a
2170 * single request.
2171 */
2172
2173#define ADV_SG_LIST_MAX_BYTE_SIZE \
2174 (sizeof(ADV_SG_BLOCK) * \
2175 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2176
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002177/* struct asc_board flags */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002178#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
2180#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002182#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002184#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185
2186#ifdef CONFIG_PROC_FS
2187/* /proc/scsi/advansys/[0...] related definitions */
2188#define ASC_PRTBUF_SIZE 2048
2189#define ASC_PRTLINE_SIZE 160
2190
2191#define ASC_PRT_NEXT() \
2192 if (cp) { \
2193 totlen += len; \
2194 leftlen -= len; \
2195 if (leftlen == 0) { \
2196 return totlen; \
2197 } \
2198 cp += len; \
2199 }
2200#endif /* CONFIG_PROC_FS */
2201
2202/* Asc Library return codes */
2203#define ASC_TRUE 1
2204#define ASC_FALSE 0
2205#define ASC_NOERROR 1
2206#define ASC_BUSY 0
2207#define ASC_ERROR (-1)
2208
2209/* struct scsi_cmnd function return codes */
2210#define STATUS_BYTE(byte) (byte)
2211#define MSG_BYTE(byte) ((byte) << 8)
2212#define HOST_BYTE(byte) ((byte) << 16)
2213#define DRIVER_BYTE(byte) ((byte) << 24)
2214
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002215#define ASC_STATS(shost, counter) ASC_STATS_ADD(shost, counter, 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002217#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002219#define ASC_STATS_ADD(shost, counter, count) \
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002220 (((struct asc_board *) shost_priv(shost))->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221#endif /* ADVANSYS_STATS */
2222
2223#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2224
2225/* If the result wraps when calculating tenths, return 0. */
2226#define ASC_TENTHS(num, den) \
2227 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2228 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2229
2230/*
2231 * Display a message to the console.
2232 */
2233#define ASC_PRINT(s) \
2234 { \
2235 printk("advansys: "); \
2236 printk(s); \
2237 }
2238
2239#define ASC_PRINT1(s, a1) \
2240 { \
2241 printk("advansys: "); \
2242 printk((s), (a1)); \
2243 }
2244
2245#define ASC_PRINT2(s, a1, a2) \
2246 { \
2247 printk("advansys: "); \
2248 printk((s), (a1), (a2)); \
2249 }
2250
2251#define ASC_PRINT3(s, a1, a2, a3) \
2252 { \
2253 printk("advansys: "); \
2254 printk((s), (a1), (a2), (a3)); \
2255 }
2256
2257#define ASC_PRINT4(s, a1, a2, a3, a4) \
2258 { \
2259 printk("advansys: "); \
2260 printk((s), (a1), (a2), (a3), (a4)); \
2261 }
2262
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263#ifndef ADVANSYS_DEBUG
2264
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002265#define ASC_DBG(lvl, s...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2268#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2269#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2270#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2271#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2272#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2273#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2274#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2275
2276#else /* ADVANSYS_DEBUG */
2277
2278/*
2279 * Debugging Message Levels:
2280 * 0: Errors Only
2281 * 1: High-Level Tracing
2282 * 2-N: Verbose Tracing
2283 */
2284
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002285#define ASC_DBG(lvl, format, arg...) { \
2286 if (asc_dbglvl >= (lvl)) \
2287 printk(KERN_DEBUG "%s: %s: " format, DRV_NAME, \
2288 __FUNCTION__ , ## arg); \
2289}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
2291#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2292 { \
2293 if (asc_dbglvl >= (lvl)) { \
2294 asc_prt_scsi_host(s); \
2295 } \
2296 }
2297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2299 { \
2300 if (asc_dbglvl >= (lvl)) { \
2301 asc_prt_asc_scsi_q(scsiqp); \
2302 } \
2303 }
2304
2305#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2306 { \
2307 if (asc_dbglvl >= (lvl)) { \
2308 asc_prt_asc_qdone_info(qdone); \
2309 } \
2310 }
2311
2312#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2313 { \
2314 if (asc_dbglvl >= (lvl)) { \
2315 asc_prt_adv_scsi_req_q(scsiqp); \
2316 } \
2317 }
2318
2319#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2320 { \
2321 if (asc_dbglvl >= (lvl)) { \
2322 asc_prt_hex((name), (start), (length)); \
2323 } \
2324 }
2325
2326#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2327 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2328
2329#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2330 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2331
2332#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2333 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2334#endif /* ADVANSYS_DEBUG */
2335
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336#ifdef ADVANSYS_STATS
2337
2338/* Per board statistics structure */
2339struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002340 /* Driver Entrypoint Statistics */
2341 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2342 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2343 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2344 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2345 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2346 ADV_DCNT done; /* # calls to request's scsi_done function */
2347 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2348 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2349 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2350 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2351 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2352 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2353 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2354 ADV_DCNT exe_unknown; /* # unknown returns. */
2355 /* Data Transfer Statistics */
2356 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2357 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2358 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2359 ADV_DCNT sg_elem; /* # scatter-gather elements */
2360 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361};
2362#endif /* ADVANSYS_STATS */
2363
2364/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 * Adv Library Request Structures
2366 *
2367 * The following two structures are used to process Wide Board requests.
2368 *
2369 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2370 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2371 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2372 * Mid-Level SCSI request structure.
2373 *
2374 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2375 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2376 * up to 255 scatter-gather elements may be used per request or
2377 * ADV_SCSI_REQ_Q.
2378 *
2379 * Both structures must be 32 byte aligned.
2380 */
2381typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002382 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2383 uchar align[32]; /* Sgblock structure padding. */
2384 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385} adv_sgblk_t;
2386
2387typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002388 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2389 uchar align[32]; /* Request structure padding. */
2390 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2391 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2392 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393} adv_req_t;
2394
2395/*
2396 * Structure allocated for each board.
2397 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002398 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 * of the 'Scsi_Host' structure starting at the 'hostdata'
2400 * field. It is guaranteed to be allocated from DMA-able memory.
2401 */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002402struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002403 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002404 uint flags; /* Board flags */
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002405 unsigned int irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002406 union {
2407 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2408 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2409 } dvc_var;
2410 union {
2411 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2412 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2413 } dvc_cfg;
2414 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002415 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002416 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2417 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2418 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2419 union {
2420 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2421 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2422 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2423 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2424 } eep_config;
2425 ulong last_reset; /* Saved last reset time */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002426 /* /proc/scsi/advansys/[0...] */
2427 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002429 struct asc_stats asc_stats; /* Board statistics */
2430#endif /* ADVANSYS_STATS */
2431 /*
2432 * The following fields are used only for Narrow Boards.
2433 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002434 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2435 /*
2436 * The following fields are used only for Wide Boards.
2437 */
2438 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2439 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002440 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002441 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2442 adv_req_t *adv_reqp; /* Request structures. */
2443 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2444 ushort bios_signature; /* BIOS Signature. */
2445 ushort bios_version; /* BIOS Version. */
2446 ushort bios_codeseg; /* BIOS Code Segment. */
2447 ushort bios_codelen; /* BIOS Code Segment Length. */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002448};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002450#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2451 dvc_var.adv_dvc_var)
2452#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2453
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002455static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002458static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002461 * asc_prt_asc_dvc_var()
2462 */
2463static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
2464{
2465 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
2466
2467 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
2468 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
2469
2470 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
2471 (unsigned)h->init_sdtr);
2472
2473 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
2474 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
2475 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
2476 (unsigned)h->chip_no);
2477
2478 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
2479 "%u,\n", (unsigned)h->queue_full_or_busy,
2480 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
2481
2482 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
2483 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
2484 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
2485 (unsigned)h->in_critical_cnt);
2486
2487 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
2488 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
2489 (unsigned)h->init_state, (unsigned)h->no_scam,
2490 (unsigned)h->pci_fix_asyn_xfer);
2491
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002492 printk(" cfg 0x%lx\n", (ulong)h->cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002493}
2494
2495/*
2496 * asc_prt_asc_dvc_cfg()
2497 */
2498static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
2499{
2500 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
2501
2502 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
2503 h->can_tagged_qng, h->cmd_qng_enabled);
2504 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
2505 h->disc_enable, h->sdtr_enable);
2506
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04002507 printk(" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, "
2508 "chip_version %d,\n", h->chip_scsi_id, h->isa_dma_speed,
2509 h->isa_dma_channel, h->chip_version);
Matthew Wilcox51219352007-10-02 21:55:22 -04002510
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002511 printk(" mcode_date 0x%x, mcode_version %d, overrun_buf 0x%p\n",
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04002512 h->mcode_date, h->mcode_version, h->overrun_buf);
Matthew Wilcox51219352007-10-02 21:55:22 -04002513}
2514
2515/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002516 * asc_prt_adv_dvc_var()
2517 *
2518 * Display an ADV_DVC_VAR structure.
2519 */
2520static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
2521{
2522 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
2523
2524 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
2525 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
2526
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002527 printk(" sdtr_able 0x%x, wdtr_able 0x%x\n",
2528 (unsigned)h->sdtr_able, (unsigned)h->wdtr_able);
Matthew Wilcox51219352007-10-02 21:55:22 -04002529
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002530 printk(" start_motor 0x%x, scsi_reset_wait 0x%x\n",
2531 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Matthew Wilcox51219352007-10-02 21:55:22 -04002532
2533 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
2534 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
2535 (ulong)h->carr_freelist);
2536
2537 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
2538 (ulong)h->icq_sp, (ulong)h->irq_sp);
2539
2540 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
2541 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
2542
2543 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
2544 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
2545}
2546
2547/*
2548 * asc_prt_adv_dvc_cfg()
2549 *
2550 * Display an ADV_DVC_CFG structure.
2551 */
2552static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
2553{
2554 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
2555
2556 printk(" disc_enable 0x%x, termination 0x%x\n",
2557 h->disc_enable, h->termination);
2558
2559 printk(" chip_version 0x%x, mcode_date 0x%x\n",
2560 h->chip_version, h->mcode_date);
2561
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002562 printk(" mcode_version 0x%x, control_flag 0x%x\n",
2563 h->mcode_version, h->control_flag);
Matthew Wilcox51219352007-10-02 21:55:22 -04002564}
2565
2566/*
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002567 * asc_prt_scsi_host()
Matthew Wilcox51219352007-10-02 21:55:22 -04002568 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002569static void asc_prt_scsi_host(struct Scsi_Host *s)
Matthew Wilcox51219352007-10-02 21:55:22 -04002570{
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002571 struct asc_board *boardp = shost_priv(s);
Matthew Wilcox51219352007-10-02 21:55:22 -04002572
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002573 printk("Scsi_Host at addr 0x%p, device %s\n", s, boardp->dev->bus_id);
2574 printk(" host_busy %u, host_no %d, last_reset %d,\n",
2575 s->host_busy, s->host_no, (unsigned)s->last_reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04002576
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002577 printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
2578 (ulong)s->base, (ulong)s->io_port, boardp->irq);
Matthew Wilcox51219352007-10-02 21:55:22 -04002579
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002580 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
2581 s->dma_channel, s->this_id, s->can_queue);
Matthew Wilcox51219352007-10-02 21:55:22 -04002582
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002583 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
2584 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Matthew Wilcox51219352007-10-02 21:55:22 -04002585
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002586 if (ASC_NARROW_BOARD(boardp)) {
2587 asc_prt_asc_dvc_var(&boardp->dvc_var.asc_dvc_var);
2588 asc_prt_asc_dvc_cfg(&boardp->dvc_cfg.asc_dvc_cfg);
2589 } else {
2590 asc_prt_adv_dvc_var(&boardp->dvc_var.adv_dvc_var);
2591 asc_prt_adv_dvc_cfg(&boardp->dvc_cfg.adv_dvc_cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002592 }
2593}
2594
2595/*
2596 * asc_prt_hex()
2597 *
2598 * Print hexadecimal output in 4 byte groupings 32 bytes
2599 * or 8 double-words per line.
2600 */
2601static void asc_prt_hex(char *f, uchar *s, int l)
2602{
2603 int i;
2604 int j;
2605 int k;
2606 int m;
2607
2608 printk("%s: (%d bytes)\n", f, l);
2609
2610 for (i = 0; i < l; i += 32) {
2611
2612 /* Display a maximum of 8 double-words per line. */
2613 if ((k = (l - i) / 4) >= 8) {
2614 k = 8;
2615 m = 0;
2616 } else {
2617 m = (l - i) % 4;
2618 }
2619
2620 for (j = 0; j < k; j++) {
2621 printk(" %2.2X%2.2X%2.2X%2.2X",
2622 (unsigned)s[i + (j * 4)],
2623 (unsigned)s[i + (j * 4) + 1],
2624 (unsigned)s[i + (j * 4) + 2],
2625 (unsigned)s[i + (j * 4) + 3]);
2626 }
2627
2628 switch (m) {
2629 case 0:
2630 default:
2631 break;
2632 case 1:
2633 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
2634 break;
2635 case 2:
2636 printk(" %2.2X%2.2X",
2637 (unsigned)s[i + (j * 4)],
2638 (unsigned)s[i + (j * 4) + 1]);
2639 break;
2640 case 3:
2641 printk(" %2.2X%2.2X%2.2X",
2642 (unsigned)s[i + (j * 4) + 1],
2643 (unsigned)s[i + (j * 4) + 2],
2644 (unsigned)s[i + (j * 4) + 3]);
2645 break;
2646 }
2647
2648 printk("\n");
2649 }
2650}
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002651
2652/*
2653 * asc_prt_asc_scsi_q()
2654 */
2655static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
2656{
2657 ASC_SG_HEAD *sgp;
2658 int i;
2659
2660 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
2661
2662 printk
2663 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
2664 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
2665 q->q2.tag_code);
2666
2667 printk
2668 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2669 (ulong)le32_to_cpu(q->q1.data_addr),
2670 (ulong)le32_to_cpu(q->q1.data_cnt),
2671 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
2672
2673 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
2674 (ulong)q->cdbptr, q->q2.cdb_len,
2675 (ulong)q->sg_head, q->q1.sg_queue_cnt);
2676
2677 if (q->sg_head) {
2678 sgp = q->sg_head;
2679 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
2680 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
2681 sgp->queue_cnt);
2682 for (i = 0; i < sgp->entry_cnt; i++) {
2683 printk(" [%u]: addr 0x%lx, bytes %lu\n",
2684 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
2685 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
2686 }
2687
2688 }
2689}
2690
2691/*
2692 * asc_prt_asc_qdone_info()
2693 */
2694static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
2695{
2696 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
2697 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
2698 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
2699 q->d2.tag_code);
2700 printk
2701 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
2702 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
2703}
2704
2705/*
2706 * asc_prt_adv_sgblock()
2707 *
2708 * Display an ADV_SG_BLOCK structure.
2709 */
2710static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
2711{
2712 int i;
2713
2714 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
2715 (ulong)b, sgblockno);
2716 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
2717 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
2718 BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
2719 if (b->sg_ptr != 0)
2720 BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
2721 for (i = 0; i < b->sg_cnt; i++) {
2722 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
2723 i, (ulong)b->sg_list[i].sg_addr,
2724 (ulong)b->sg_list[i].sg_count);
2725 }
2726}
2727
2728/*
2729 * asc_prt_adv_scsi_req_q()
2730 *
2731 * Display an ADV_SCSI_REQ_Q structure.
2732 */
2733static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
2734{
2735 int sg_blk_cnt;
2736 struct asc_sg_block *sg_ptr;
2737
2738 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
2739
2740 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
2741 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
2742
2743 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
2744 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
2745
2746 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2747 (ulong)le32_to_cpu(q->data_cnt),
2748 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
2749
2750 printk
2751 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
2752 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
2753
2754 printk(" sg_working_ix 0x%x, target_cmd %u\n",
2755 q->sg_working_ix, q->target_cmd);
2756
2757 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
2758 (ulong)le32_to_cpu(q->scsiq_rptr),
2759 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
2760
2761 /* Display the request's ADV_SG_BLOCK structures. */
2762 if (q->sg_list_ptr != NULL) {
2763 sg_blk_cnt = 0;
2764 while (1) {
2765 /*
2766 * 'sg_ptr' is a physical address. Convert it to a virtual
2767 * address by indexing 'sg_blk_cnt' into the virtual address
2768 * array 'sg_list_ptr'.
2769 *
2770 * XXX - Assumes all SG physical blocks are virtually contiguous.
2771 */
2772 sg_ptr =
2773 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
2774 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
2775 if (sg_ptr->sg_ptr == 0) {
2776 break;
2777 }
2778 sg_blk_cnt++;
2779 }
2780 }
2781}
Matthew Wilcox51219352007-10-02 21:55:22 -04002782#endif /* ADVANSYS_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783
2784/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 * advansys_info()
2786 *
2787 * Return suitable for printing on the console with the argument
2788 * adapter's configuration information.
2789 *
2790 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
2791 * otherwise the static 'info' array will be overrun.
2792 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002793static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002795 static char info[ASC_INFO_SIZE];
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002796 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002797 ASC_DVC_VAR *asc_dvc_varp;
2798 ADV_DVC_VAR *adv_dvc_varp;
2799 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002800 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002802 if (ASC_NARROW_BOARD(boardp)) {
2803 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002804 ASC_DBG(1, "begin\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002805 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
2806 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
2807 ASC_IS_ISAPNP) {
2808 busname = "ISA PnP";
2809 } else {
2810 busname = "ISA";
2811 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002812 sprintf(info,
2813 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
2814 ASC_VERSION, busname,
2815 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002816 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002817 boardp->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002818 } else {
2819 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
2820 busname = "VL";
2821 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
2822 busname = "EISA";
2823 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
2824 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
2825 == ASC_IS_PCI_ULTRA) {
2826 busname = "PCI Ultra";
2827 } else {
2828 busname = "PCI";
2829 }
2830 } else {
2831 busname = "?";
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -04002832 shost_printk(KERN_ERR, shost, "unknown bus "
2833 "type %d\n", asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002834 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002835 sprintf(info,
2836 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002837 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002838 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002839 boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002840 }
2841 } else {
2842 /*
2843 * Wide Adapter Information
2844 *
2845 * Memory-mapped I/O is used instead of I/O space to access
2846 * the adapter, but display the I/O Port range. The Memory
2847 * I/O address is displayed through the driver /proc file.
2848 */
2849 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
2850 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002851 widename = "Ultra-Wide";
2852 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002853 widename = "Ultra2-Wide";
2854 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002855 widename = "Ultra3-Wide";
2856 }
2857 sprintf(info,
2858 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
2859 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002860 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002861 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002862 BUG_ON(strlen(info) >= ASC_INFO_SIZE);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002863 ASC_DBG(1, "end\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002864 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865}
2866
Matthew Wilcox51219352007-10-02 21:55:22 -04002867#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002869 * asc_prt_line()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 *
Matthew Wilcox51219352007-10-02 21:55:22 -04002871 * If 'cp' is NULL print to the console, otherwise print to a buffer.
2872 *
2873 * Return 0 if printing to the console, otherwise return the number of
2874 * bytes written to the buffer.
2875 *
2876 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
2877 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 */
Matthew Wilcox51219352007-10-02 21:55:22 -04002879static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880{
Matthew Wilcox51219352007-10-02 21:55:22 -04002881 va_list args;
2882 int ret;
2883 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884
Matthew Wilcox51219352007-10-02 21:55:22 -04002885 va_start(args, fmt);
2886 ret = vsprintf(s, fmt, args);
2887 BUG_ON(ret >= ASC_PRTLINE_SIZE);
2888 if (buf == NULL) {
2889 (void)printk(s);
2890 ret = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002891 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04002892 ret = min(buflen, ret);
2893 memcpy(buf, s, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002894 }
Matthew Wilcox51219352007-10-02 21:55:22 -04002895 va_end(args);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002896 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897}
2898
2899/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 * asc_prt_board_devices()
2901 *
2902 * Print driver information for devices attached to the board.
2903 *
2904 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
2905 * cf. asc_prt_line().
2906 *
2907 * Return the number of characters copied into 'cp'. No more than
2908 * 'cplen' characters will be copied to 'cp'.
2909 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002910static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002912 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002913 int leftlen;
2914 int totlen;
2915 int len;
2916 int chip_scsi_id;
2917 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002919 leftlen = cplen;
2920 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002922 len = asc_prt_line(cp, leftlen,
2923 "\nDevice Information for AdvanSys SCSI Host %d:\n",
2924 shost->host_no);
2925 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002927 if (ASC_NARROW_BOARD(boardp)) {
2928 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
2929 } else {
2930 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
2931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002933 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
2934 ASC_PRT_NEXT();
2935 for (i = 0; i <= ADV_MAX_TID; i++) {
2936 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
2937 len = asc_prt_line(cp, leftlen, " %X,", i);
2938 ASC_PRT_NEXT();
2939 }
2940 }
2941 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
2942 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002944 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945}
2946
2947/*
2948 * Display Wide Board BIOS Information.
2949 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002950static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002952 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002953 int leftlen;
2954 int totlen;
2955 int len;
2956 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002958 leftlen = cplen;
2959 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002961 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
2962 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002964 /*
2965 * If the BIOS saved a valid signature, then fill in
2966 * the BIOS code segment base address.
2967 */
2968 if (boardp->bios_signature != 0x55AA) {
2969 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
2970 ASC_PRT_NEXT();
2971 len = asc_prt_line(cp, leftlen,
2972 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
2973 ASC_PRT_NEXT();
2974 len = asc_prt_line(cp, leftlen,
2975 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
2976 ASC_PRT_NEXT();
2977 } else {
2978 major = (boardp->bios_version >> 12) & 0xF;
2979 minor = (boardp->bios_version >> 8) & 0xF;
2980 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002982 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
2983 major, minor,
2984 letter >= 26 ? '?' : letter + 'A');
2985 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002987 /*
2988 * Current available ROM BIOS release is 3.1I for UW
2989 * and 3.2I for U2W. This code doesn't differentiate
2990 * UW and U2W boards.
2991 */
2992 if (major < 3 || (major <= 3 && minor < 1) ||
2993 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
2994 len = asc_prt_line(cp, leftlen,
2995 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
2996 ASC_PRT_NEXT();
2997 len = asc_prt_line(cp, leftlen,
2998 "ftp://ftp.connectcom.net/pub\n");
2999 ASC_PRT_NEXT();
3000 }
3001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003003 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004}
3005
3006/*
3007 * Add serial number to information bar if signature AAh
3008 * is found in at bit 15-9 (7 bits) of word 1.
3009 *
3010 * Serial Number consists fo 12 alpha-numeric digits.
3011 *
3012 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
3013 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
3014 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
3015 * 5 - Product revision (A-J) Word0: " "
3016 *
3017 * Signature Word1: 15-9 (7 bits)
3018 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
3019 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
3020 *
3021 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
3022 *
3023 * Note 1: Only production cards will have a serial number.
3024 *
3025 * Note 2: Signature is most significant 7 bits (0xFE).
3026 *
3027 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
3028 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003029static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003031 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003033 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
3034 return ASC_FALSE;
3035 } else {
3036 /*
3037 * First word - 6 digits.
3038 */
3039 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003041 /* Product type - 1st digit. */
3042 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
3043 /* Product type is P=Prototype */
3044 *cp += 0x8;
3045 }
3046 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003048 /* Manufacturing location - 2nd digit. */
3049 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003051 /* Product ID - 3rd, 4th digits. */
3052 num = w & 0x3FF;
3053 *cp++ = '0' + (num / 100);
3054 num %= 100;
3055 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003057 /* Product revision - 5th digit. */
3058 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003060 /*
3061 * Second word
3062 */
3063 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003065 /*
3066 * Year - 6th digit.
3067 *
3068 * If bit 15 of third word is set, then the
3069 * last digit of the year is greater than 7.
3070 */
3071 if (serialnum[2] & 0x8000) {
3072 *cp++ = '8' + ((w & 0x1C0) >> 6);
3073 } else {
3074 *cp++ = '0' + ((w & 0x1C0) >> 6);
3075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003077 /* Week of year - 7th, 8th digits. */
3078 num = w & 0x003F;
3079 *cp++ = '0' + num / 10;
3080 num %= 10;
3081 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003083 /*
3084 * Third word
3085 */
3086 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003088 /* Serial number - 9th digit. */
3089 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003091 /* 10th, 11th, 12th digits. */
3092 num = w % 1000;
3093 *cp++ = '0' + num / 100;
3094 num %= 100;
3095 *cp++ = '0' + num / 10;
3096 num %= 10;
3097 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003099 *cp = '\0'; /* Null Terminate the string. */
3100 return ASC_TRUE;
3101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102}
3103
3104/*
3105 * asc_prt_asc_board_eeprom()
3106 *
3107 * Print board EEPROM configuration.
3108 *
3109 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3110 * cf. asc_prt_line().
3111 *
3112 * Return the number of characters copied into 'cp'. No more than
3113 * 'cplen' characters will be copied to 'cp'.
3114 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003115static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003117 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003118 ASC_DVC_VAR *asc_dvc_varp;
3119 int leftlen;
3120 int totlen;
3121 int len;
3122 ASCEEP_CONFIG *ep;
3123 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003125 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003127 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003129 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3130 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003132 leftlen = cplen;
3133 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003135 len = asc_prt_line(cp, leftlen,
3136 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3137 shost->host_no);
3138 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003140 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
3141 == ASC_TRUE) {
3142 len =
3143 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3144 serialstr);
3145 ASC_PRT_NEXT();
3146 } else {
3147 if (ep->adapter_info[5] == 0xBB) {
3148 len = asc_prt_line(cp, leftlen,
3149 " Default Settings Used for EEPROM-less Adapter.\n");
3150 ASC_PRT_NEXT();
3151 } else {
3152 len = asc_prt_line(cp, leftlen,
3153 " Serial Number Signature Not Present.\n");
3154 ASC_PRT_NEXT();
3155 }
3156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003158 len = asc_prt_line(cp, leftlen,
3159 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3160 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
3161 ep->max_tag_qng);
3162 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003164 len = asc_prt_line(cp, leftlen,
3165 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
3166 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003168 len = asc_prt_line(cp, leftlen, " Target ID: ");
3169 ASC_PRT_NEXT();
3170 for (i = 0; i <= ASC_MAX_TID; i++) {
3171 len = asc_prt_line(cp, leftlen, " %d", i);
3172 ASC_PRT_NEXT();
3173 }
3174 len = asc_prt_line(cp, leftlen, "\n");
3175 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003177 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3178 ASC_PRT_NEXT();
3179 for (i = 0; i <= ASC_MAX_TID; i++) {
3180 len = asc_prt_line(cp, leftlen, " %c",
3181 (ep->
3182 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3183 'N');
3184 ASC_PRT_NEXT();
3185 }
3186 len = asc_prt_line(cp, leftlen, "\n");
3187 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003189 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3190 ASC_PRT_NEXT();
3191 for (i = 0; i <= ASC_MAX_TID; i++) {
3192 len = asc_prt_line(cp, leftlen, " %c",
3193 (ep->
3194 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3195 'N');
3196 ASC_PRT_NEXT();
3197 }
3198 len = asc_prt_line(cp, leftlen, "\n");
3199 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003201 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3202 ASC_PRT_NEXT();
3203 for (i = 0; i <= ASC_MAX_TID; i++) {
3204 len = asc_prt_line(cp, leftlen, " %c",
3205 (ep->
3206 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3207 'N');
3208 ASC_PRT_NEXT();
3209 }
3210 len = asc_prt_line(cp, leftlen, "\n");
3211 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003213 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3214 ASC_PRT_NEXT();
3215 for (i = 0; i <= ASC_MAX_TID; i++) {
3216 len = asc_prt_line(cp, leftlen, " %c",
3217 (ep->
3218 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3219 'N');
3220 ASC_PRT_NEXT();
3221 }
3222 len = asc_prt_line(cp, leftlen, "\n");
3223 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
3225#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003226 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3227 len = asc_prt_line(cp, leftlen,
3228 " Host ISA DMA speed: %d MB/S\n",
3229 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
3230 ASC_PRT_NEXT();
3231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232#endif /* CONFIG_ISA */
3233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003234 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235}
3236
3237/*
3238 * asc_prt_adv_board_eeprom()
3239 *
3240 * Print board EEPROM configuration.
3241 *
3242 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3243 * cf. asc_prt_line().
3244 *
3245 * Return the number of characters copied into 'cp'. No more than
3246 * 'cplen' characters will be copied to 'cp'.
3247 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003248static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003250 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003251 ADV_DVC_VAR *adv_dvc_varp;
3252 int leftlen;
3253 int totlen;
3254 int len;
3255 int i;
3256 char *termstr;
3257 uchar serialstr[13];
3258 ADVEEP_3550_CONFIG *ep_3550 = NULL;
3259 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
3260 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
3261 ushort word;
3262 ushort *wordp;
3263 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003265 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3266 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3267 ep_3550 = &boardp->eep_config.adv_3550_eep;
3268 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3269 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
3270 } else {
3271 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
3272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003274 leftlen = cplen;
3275 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003277 len = asc_prt_line(cp, leftlen,
3278 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3279 shost->host_no);
3280 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003282 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3283 wordp = &ep_3550->serial_number_word1;
3284 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3285 wordp = &ep_38C0800->serial_number_word1;
3286 } else {
3287 wordp = &ep_38C1600->serial_number_word1;
3288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003290 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
3291 len =
3292 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3293 serialstr);
3294 ASC_PRT_NEXT();
3295 } else {
3296 len = asc_prt_line(cp, leftlen,
3297 " Serial Number Signature Not Present.\n");
3298 ASC_PRT_NEXT();
3299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003301 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3302 len = asc_prt_line(cp, leftlen,
3303 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3304 ep_3550->adapter_scsi_id,
3305 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
3306 ASC_PRT_NEXT();
3307 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3308 len = asc_prt_line(cp, leftlen,
3309 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3310 ep_38C0800->adapter_scsi_id,
3311 ep_38C0800->max_host_qng,
3312 ep_38C0800->max_dvc_qng);
3313 ASC_PRT_NEXT();
3314 } else {
3315 len = asc_prt_line(cp, leftlen,
3316 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3317 ep_38C1600->adapter_scsi_id,
3318 ep_38C1600->max_host_qng,
3319 ep_38C1600->max_dvc_qng);
3320 ASC_PRT_NEXT();
3321 }
3322 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3323 word = ep_3550->termination;
3324 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3325 word = ep_38C0800->termination_lvd;
3326 } else {
3327 word = ep_38C1600->termination_lvd;
3328 }
3329 switch (word) {
3330 case 1:
3331 termstr = "Low Off/High Off";
3332 break;
3333 case 2:
3334 termstr = "Low Off/High On";
3335 break;
3336 case 3:
3337 termstr = "Low On/High On";
3338 break;
3339 default:
3340 case 0:
3341 termstr = "Automatic";
3342 break;
3343 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003345 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3346 len = asc_prt_line(cp, leftlen,
3347 " termination: %u (%s), bios_ctrl: 0x%x\n",
3348 ep_3550->termination, termstr,
3349 ep_3550->bios_ctrl);
3350 ASC_PRT_NEXT();
3351 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3352 len = asc_prt_line(cp, leftlen,
3353 " termination: %u (%s), bios_ctrl: 0x%x\n",
3354 ep_38C0800->termination_lvd, termstr,
3355 ep_38C0800->bios_ctrl);
3356 ASC_PRT_NEXT();
3357 } else {
3358 len = asc_prt_line(cp, leftlen,
3359 " termination: %u (%s), bios_ctrl: 0x%x\n",
3360 ep_38C1600->termination_lvd, termstr,
3361 ep_38C1600->bios_ctrl);
3362 ASC_PRT_NEXT();
3363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003365 len = asc_prt_line(cp, leftlen, " Target ID: ");
3366 ASC_PRT_NEXT();
3367 for (i = 0; i <= ADV_MAX_TID; i++) {
3368 len = asc_prt_line(cp, leftlen, " %X", i);
3369 ASC_PRT_NEXT();
3370 }
3371 len = asc_prt_line(cp, leftlen, "\n");
3372 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003374 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3375 word = ep_3550->disc_enable;
3376 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3377 word = ep_38C0800->disc_enable;
3378 } else {
3379 word = ep_38C1600->disc_enable;
3380 }
3381 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3382 ASC_PRT_NEXT();
3383 for (i = 0; i <= ADV_MAX_TID; i++) {
3384 len = asc_prt_line(cp, leftlen, " %c",
3385 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3386 ASC_PRT_NEXT();
3387 }
3388 len = asc_prt_line(cp, leftlen, "\n");
3389 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003391 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3392 word = ep_3550->tagqng_able;
3393 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3394 word = ep_38C0800->tagqng_able;
3395 } else {
3396 word = ep_38C1600->tagqng_able;
3397 }
3398 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3399 ASC_PRT_NEXT();
3400 for (i = 0; i <= ADV_MAX_TID; i++) {
3401 len = asc_prt_line(cp, leftlen, " %c",
3402 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3403 ASC_PRT_NEXT();
3404 }
3405 len = asc_prt_line(cp, leftlen, "\n");
3406 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003408 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3409 word = ep_3550->start_motor;
3410 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3411 word = ep_38C0800->start_motor;
3412 } else {
3413 word = ep_38C1600->start_motor;
3414 }
3415 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3416 ASC_PRT_NEXT();
3417 for (i = 0; i <= ADV_MAX_TID; i++) {
3418 len = asc_prt_line(cp, leftlen, " %c",
3419 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3420 ASC_PRT_NEXT();
3421 }
3422 len = asc_prt_line(cp, leftlen, "\n");
3423 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003425 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3426 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3427 ASC_PRT_NEXT();
3428 for (i = 0; i <= ADV_MAX_TID; i++) {
3429 len = asc_prt_line(cp, leftlen, " %c",
3430 (ep_3550->
3431 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
3432 'Y' : 'N');
3433 ASC_PRT_NEXT();
3434 }
3435 len = asc_prt_line(cp, leftlen, "\n");
3436 ASC_PRT_NEXT();
3437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003439 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3440 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
3441 ASC_PRT_NEXT();
3442 for (i = 0; i <= ADV_MAX_TID; i++) {
3443 len = asc_prt_line(cp, leftlen, " %c",
3444 (ep_3550->
3445 ultra_able & ADV_TID_TO_TIDMASK(i))
3446 ? 'Y' : 'N');
3447 ASC_PRT_NEXT();
3448 }
3449 len = asc_prt_line(cp, leftlen, "\n");
3450 ASC_PRT_NEXT();
3451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003453 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3454 word = ep_3550->wdtr_able;
3455 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3456 word = ep_38C0800->wdtr_able;
3457 } else {
3458 word = ep_38C1600->wdtr_able;
3459 }
3460 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
3461 ASC_PRT_NEXT();
3462 for (i = 0; i <= ADV_MAX_TID; i++) {
3463 len = asc_prt_line(cp, leftlen, " %c",
3464 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3465 ASC_PRT_NEXT();
3466 }
3467 len = asc_prt_line(cp, leftlen, "\n");
3468 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003470 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
3471 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
3472 len = asc_prt_line(cp, leftlen,
3473 " Synchronous Transfer Speed (Mhz):\n ");
3474 ASC_PRT_NEXT();
3475 for (i = 0; i <= ADV_MAX_TID; i++) {
3476 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003478 if (i == 0) {
3479 sdtr_speed = adv_dvc_varp->sdtr_speed1;
3480 } else if (i == 4) {
3481 sdtr_speed = adv_dvc_varp->sdtr_speed2;
3482 } else if (i == 8) {
3483 sdtr_speed = adv_dvc_varp->sdtr_speed3;
3484 } else if (i == 12) {
3485 sdtr_speed = adv_dvc_varp->sdtr_speed4;
3486 }
3487 switch (sdtr_speed & ADV_MAX_TID) {
3488 case 0:
3489 speed_str = "Off";
3490 break;
3491 case 1:
3492 speed_str = " 5";
3493 break;
3494 case 2:
3495 speed_str = " 10";
3496 break;
3497 case 3:
3498 speed_str = " 20";
3499 break;
3500 case 4:
3501 speed_str = " 40";
3502 break;
3503 case 5:
3504 speed_str = " 80";
3505 break;
3506 default:
3507 speed_str = "Unk";
3508 break;
3509 }
3510 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
3511 ASC_PRT_NEXT();
3512 if (i == 7) {
3513 len = asc_prt_line(cp, leftlen, "\n ");
3514 ASC_PRT_NEXT();
3515 }
3516 sdtr_speed >>= 4;
3517 }
3518 len = asc_prt_line(cp, leftlen, "\n");
3519 ASC_PRT_NEXT();
3520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003522 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523}
3524
3525/*
3526 * asc_prt_driver_conf()
3527 *
3528 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3529 * cf. asc_prt_line().
3530 *
3531 * Return the number of characters copied into 'cp'. No more than
3532 * 'cplen' characters will be copied to 'cp'.
3533 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003534static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003536 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003537 int leftlen;
3538 int totlen;
3539 int len;
3540 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003542 leftlen = cplen;
3543 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003545 len = asc_prt_line(cp, leftlen,
3546 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
3547 shost->host_no);
3548 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003550 len = asc_prt_line(cp, leftlen,
3551 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
3552 shost->host_busy, shost->last_reset, shost->max_id,
3553 shost->max_lun, shost->max_channel);
3554 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003556 len = asc_prt_line(cp, leftlen,
3557 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
3558 shost->unique_id, shost->can_queue, shost->this_id,
3559 shost->sg_tablesize, shost->cmd_per_lun);
3560 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003562 len = asc_prt_line(cp, leftlen,
3563 " unchecked_isa_dma %d, use_clustering %d\n",
3564 shost->unchecked_isa_dma, shost->use_clustering);
3565 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003567 len = asc_prt_line(cp, leftlen,
3568 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
3569 boardp->flags, boardp->last_reset, jiffies,
3570 boardp->asc_n_io_port);
3571 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003573 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003574 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003576 if (ASC_NARROW_BOARD(boardp)) {
3577 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3578 } else {
3579 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003582 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583}
3584
3585/*
3586 * asc_prt_asc_board_info()
3587 *
3588 * Print dynamic board configuration information.
3589 *
3590 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3591 * cf. asc_prt_line().
3592 *
3593 * Return the number of characters copied into 'cp'. No more than
3594 * 'cplen' characters will be copied to 'cp'.
3595 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003596static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003598 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003599 int chip_scsi_id;
3600 int leftlen;
3601 int totlen;
3602 int len;
3603 ASC_DVC_VAR *v;
3604 ASC_DVC_CFG *c;
3605 int i;
3606 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003608 v = &boardp->dvc_var.asc_dvc_var;
3609 c = &boardp->dvc_cfg.asc_dvc_cfg;
3610 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003612 leftlen = cplen;
3613 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003615 len = asc_prt_line(cp, leftlen,
3616 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3617 shost->host_no);
3618 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04003620 len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
3621 "mcode_version 0x%x, err_code %u\n",
3622 c->chip_version, c->mcode_date, c->mcode_version,
3623 v->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003624 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003626 /* Current number of commands waiting for the host. */
3627 len = asc_prt_line(cp, leftlen,
3628 " Total Command Pending: %d\n", v->cur_total_qng);
3629 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003631 len = asc_prt_line(cp, leftlen, " Command Queuing:");
3632 ASC_PRT_NEXT();
3633 for (i = 0; i <= ASC_MAX_TID; i++) {
3634 if ((chip_scsi_id == i) ||
3635 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3636 continue;
3637 }
3638 len = asc_prt_line(cp, leftlen, " %X:%c",
3639 i,
3640 (v->
3641 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
3642 'Y' : 'N');
3643 ASC_PRT_NEXT();
3644 }
3645 len = asc_prt_line(cp, leftlen, "\n");
3646 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003648 /* Current number of commands waiting for a device. */
3649 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
3650 ASC_PRT_NEXT();
3651 for (i = 0; i <= ASC_MAX_TID; i++) {
3652 if ((chip_scsi_id == i) ||
3653 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3654 continue;
3655 }
3656 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
3657 ASC_PRT_NEXT();
3658 }
3659 len = asc_prt_line(cp, leftlen, "\n");
3660 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003662 /* Current limit on number of commands that can be sent to a device. */
3663 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
3664 ASC_PRT_NEXT();
3665 for (i = 0; i <= ASC_MAX_TID; i++) {
3666 if ((chip_scsi_id == i) ||
3667 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3668 continue;
3669 }
3670 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
3671 ASC_PRT_NEXT();
3672 }
3673 len = asc_prt_line(cp, leftlen, "\n");
3674 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003676 /* Indicate whether the device has returned queue full status. */
3677 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
3678 ASC_PRT_NEXT();
3679 for (i = 0; i <= ASC_MAX_TID; i++) {
3680 if ((chip_scsi_id == i) ||
3681 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3682 continue;
3683 }
3684 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
3685 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
3686 i, boardp->queue_full_cnt[i]);
3687 } else {
3688 len = asc_prt_line(cp, leftlen, " %X:N", i);
3689 }
3690 ASC_PRT_NEXT();
3691 }
3692 len = asc_prt_line(cp, leftlen, "\n");
3693 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003695 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3696 ASC_PRT_NEXT();
3697 for (i = 0; i <= ASC_MAX_TID; i++) {
3698 if ((chip_scsi_id == i) ||
3699 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3700 continue;
3701 }
3702 len = asc_prt_line(cp, leftlen, " %X:%c",
3703 i,
3704 (v->
3705 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3706 'N');
3707 ASC_PRT_NEXT();
3708 }
3709 len = asc_prt_line(cp, leftlen, "\n");
3710 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003712 for (i = 0; i <= ASC_MAX_TID; i++) {
3713 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003715 if ((chip_scsi_id == i) ||
3716 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3717 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
3718 continue;
3719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003721 len = asc_prt_line(cp, leftlen, " %X:", i);
3722 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003724 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
3725 len = asc_prt_line(cp, leftlen, " Asynchronous");
3726 ASC_PRT_NEXT();
3727 } else {
3728 syn_period_ix =
3729 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
3730 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003732 len = asc_prt_line(cp, leftlen,
3733 " Transfer Period Factor: %d (%d.%d Mhz),",
3734 v->sdtr_period_tbl[syn_period_ix],
3735 250 /
3736 v->sdtr_period_tbl[syn_period_ix],
3737 ASC_TENTHS(250,
3738 v->
3739 sdtr_period_tbl
3740 [syn_period_ix]));
3741 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003743 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
3744 boardp->
3745 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
3746 ASC_PRT_NEXT();
3747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003749 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3750 len = asc_prt_line(cp, leftlen, "*\n");
3751 renegotiate = 1;
3752 } else {
3753 len = asc_prt_line(cp, leftlen, "\n");
3754 }
3755 ASC_PRT_NEXT();
3756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003758 if (renegotiate) {
3759 len = asc_prt_line(cp, leftlen,
3760 " * = Re-negotiation pending before next command.\n");
3761 ASC_PRT_NEXT();
3762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003764 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765}
3766
3767/*
3768 * asc_prt_adv_board_info()
3769 *
3770 * Print dynamic board configuration information.
3771 *
3772 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3773 * cf. asc_prt_line().
3774 *
3775 * Return the number of characters copied into 'cp'. No more than
3776 * 'cplen' characters will be copied to 'cp'.
3777 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003778static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003780 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003781 int leftlen;
3782 int totlen;
3783 int len;
3784 int i;
3785 ADV_DVC_VAR *v;
3786 ADV_DVC_CFG *c;
3787 AdvPortAddr iop_base;
3788 ushort chip_scsi_id;
3789 ushort lramword;
3790 uchar lrambyte;
3791 ushort tagqng_able;
3792 ushort sdtr_able, wdtr_able;
3793 ushort wdtr_done, sdtr_done;
3794 ushort period = 0;
3795 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003797 v = &boardp->dvc_var.adv_dvc_var;
3798 c = &boardp->dvc_cfg.adv_dvc_cfg;
3799 iop_base = v->iop_base;
3800 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003802 leftlen = cplen;
3803 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003805 len = asc_prt_line(cp, leftlen,
3806 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3807 shost->host_no);
3808 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003810 len = asc_prt_line(cp, leftlen,
3811 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
3812 v->iop_base,
3813 AdvReadWordRegister(iop_base,
3814 IOPW_SCSI_CFG1) & CABLE_DETECT,
3815 v->err_code);
3816 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04003818 len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
3819 "mcode_version 0x%x\n", c->chip_version,
3820 c->mcode_date, c->mcode_version);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003821 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003823 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
3824 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
3825 ASC_PRT_NEXT();
3826 for (i = 0; i <= ADV_MAX_TID; i++) {
3827 if ((chip_scsi_id == i) ||
3828 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3829 continue;
3830 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003832 len = asc_prt_line(cp, leftlen, " %X:%c",
3833 i,
3834 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3835 'N');
3836 ASC_PRT_NEXT();
3837 }
3838 len = asc_prt_line(cp, leftlen, "\n");
3839 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003841 len = asc_prt_line(cp, leftlen, " Queue Limit:");
3842 ASC_PRT_NEXT();
3843 for (i = 0; i <= ADV_MAX_TID; i++) {
3844 if ((chip_scsi_id == i) ||
3845 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3846 continue;
3847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003849 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
3850 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003852 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3853 ASC_PRT_NEXT();
3854 }
3855 len = asc_prt_line(cp, leftlen, "\n");
3856 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003858 len = asc_prt_line(cp, leftlen, " Command Pending:");
3859 ASC_PRT_NEXT();
3860 for (i = 0; i <= ADV_MAX_TID; i++) {
3861 if ((chip_scsi_id == i) ||
3862 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3863 continue;
3864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003866 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
3867 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003869 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3870 ASC_PRT_NEXT();
3871 }
3872 len = asc_prt_line(cp, leftlen, "\n");
3873 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003875 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
3876 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
3877 ASC_PRT_NEXT();
3878 for (i = 0; i <= ADV_MAX_TID; i++) {
3879 if ((chip_scsi_id == i) ||
3880 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3881 continue;
3882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003884 len = asc_prt_line(cp, leftlen, " %X:%c",
3885 i,
3886 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3887 'N');
3888 ASC_PRT_NEXT();
3889 }
3890 len = asc_prt_line(cp, leftlen, "\n");
3891 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003893 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
3894 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
3895 ASC_PRT_NEXT();
3896 for (i = 0; i <= ADV_MAX_TID; i++) {
3897 if ((chip_scsi_id == i) ||
3898 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3899 continue;
3900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003902 AdvReadWordLram(iop_base,
3903 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
3904 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003906 len = asc_prt_line(cp, leftlen, " %X:%d",
3907 i, (lramword & 0x8000) ? 16 : 8);
3908 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003910 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
3911 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3912 len = asc_prt_line(cp, leftlen, "*");
3913 ASC_PRT_NEXT();
3914 renegotiate = 1;
3915 }
3916 }
3917 len = asc_prt_line(cp, leftlen, "\n");
3918 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003920 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
3921 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
3922 ASC_PRT_NEXT();
3923 for (i = 0; i <= ADV_MAX_TID; i++) {
3924 if ((chip_scsi_id == i) ||
3925 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3926 continue;
3927 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003929 len = asc_prt_line(cp, leftlen, " %X:%c",
3930 i,
3931 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3932 'N');
3933 ASC_PRT_NEXT();
3934 }
3935 len = asc_prt_line(cp, leftlen, "\n");
3936 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003938 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
3939 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003941 AdvReadWordLram(iop_base,
3942 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
3943 lramword);
3944 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003946 if ((chip_scsi_id == i) ||
3947 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3948 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
3949 continue;
3950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003952 len = asc_prt_line(cp, leftlen, " %X:", i);
3953 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003955 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
3956 len = asc_prt_line(cp, leftlen, " Asynchronous");
3957 ASC_PRT_NEXT();
3958 } else {
3959 len =
3960 asc_prt_line(cp, leftlen,
3961 " Transfer Period Factor: ");
3962 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003964 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
3965 len =
3966 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
3967 ASC_PRT_NEXT();
3968 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
3969 len =
3970 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
3971 ASC_PRT_NEXT();
3972 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003974 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003976 if (period == 0) { /* Should never happen. */
3977 len =
3978 asc_prt_line(cp, leftlen,
3979 "%d (? Mhz), ");
3980 ASC_PRT_NEXT();
3981 } else {
3982 len = asc_prt_line(cp, leftlen,
3983 "%d (%d.%d Mhz),",
3984 period, 250 / period,
3985 ASC_TENTHS(250,
3986 period));
3987 ASC_PRT_NEXT();
3988 }
3989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003991 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
3992 lramword & 0x1F);
3993 ASC_PRT_NEXT();
3994 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003996 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3997 len = asc_prt_line(cp, leftlen, "*\n");
3998 renegotiate = 1;
3999 } else {
4000 len = asc_prt_line(cp, leftlen, "\n");
4001 }
4002 ASC_PRT_NEXT();
4003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004005 if (renegotiate) {
4006 len = asc_prt_line(cp, leftlen,
4007 " * = Re-negotiation pending before next command.\n");
4008 ASC_PRT_NEXT();
4009 }
4010
4011 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012}
4013
4014/*
4015 * asc_proc_copy()
4016 *
4017 * Copy proc information to a read buffer taking into account the current
4018 * read offset in the file and the remaining space in the read buffer.
4019 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004020static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004022 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004024 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004026 ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004027 (unsigned)offset, (unsigned)advoffset, cplen);
4028 if (offset <= advoffset) {
4029 /* Read offset below current offset, copy everything. */
4030 cnt = min(cplen, leftlen);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004031 ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004032 (ulong)curbuf, (ulong)cp, cnt);
4033 memcpy(curbuf, cp, cnt);
4034 } else if (offset < advoffset + cplen) {
4035 /* Read offset within current range, partial copy. */
4036 cnt = (advoffset + cplen) - offset;
4037 cp = (cp + cplen) - cnt;
4038 cnt = min(cnt, leftlen);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004039 ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004040 (ulong)curbuf, (ulong)cp, cnt);
4041 memcpy(curbuf, cp, cnt);
4042 }
4043 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044}
4045
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046#ifdef ADVANSYS_STATS
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047/*
4048 * asc_prt_board_stats()
4049 *
4050 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4051 * cf. asc_prt_line().
4052 *
4053 * Return the number of characters copied into 'cp'. No more than
4054 * 'cplen' characters will be copied to 'cp'.
4055 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004056static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004058 struct asc_board *boardp = shost_priv(shost);
4059 struct asc_stats *s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004061 int leftlen = cplen;
4062 int len, totlen = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004064 len = asc_prt_line(cp, leftlen,
4065 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
4066 shost->host_no);
4067 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004069 len = asc_prt_line(cp, leftlen,
4070 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
4071 s->queuecommand, s->reset, s->biosparam,
4072 s->interrupt);
4073 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004075 len = asc_prt_line(cp, leftlen,
4076 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
4077 s->callback, s->done, s->build_error,
4078 s->adv_build_noreq, s->adv_build_nosg);
4079 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004081 len = asc_prt_line(cp, leftlen,
4082 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
4083 s->exe_noerror, s->exe_busy, s->exe_error,
4084 s->exe_unknown);
4085 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004087 /*
4088 * Display data transfer statistics.
4089 */
4090 if (s->cont_cnt > 0) {
4091 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
4092 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004094 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
4095 s->cont_xfer / 2,
4096 ASC_TENTHS(s->cont_xfer, 2));
4097 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004099 /* Contiguous transfer average size */
4100 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
4101 (s->cont_xfer / 2) / s->cont_cnt,
4102 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
4103 ASC_PRT_NEXT();
4104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004106 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004108 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
4109 s->sg_cnt, s->sg_elem);
4110 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004112 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
4113 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
4114 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004116 /* Scatter gather transfer statistics */
4117 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
4118 s->sg_elem / s->sg_cnt,
4119 ASC_TENTHS(s->sg_elem, s->sg_cnt));
4120 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004122 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
4123 (s->sg_xfer / 2) / s->sg_elem,
4124 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
4125 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004127 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
4128 (s->sg_xfer / 2) / s->sg_cnt,
4129 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
4130 ASC_PRT_NEXT();
4131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004133 /*
4134 * Display request queuing statistics.
4135 */
4136 len = asc_prt_line(cp, leftlen,
4137 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
4138 HZ);
4139 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004141 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143#endif /* ADVANSYS_STATS */
4144
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145/*
Matthew Wilcox51219352007-10-02 21:55:22 -04004146 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
4147 *
4148 * *buffer: I/O buffer
4149 * **start: if inout == FALSE pointer into buffer where user read should start
4150 * offset: current offset into a /proc/scsi/advansys/[0...] file
4151 * length: length of buffer
4152 * hostno: Scsi_Host host_no
4153 * inout: TRUE - user is writing; FALSE - user is reading
4154 *
4155 * Return the number of bytes read from or written to a
4156 * /proc/scsi/advansys/[0...] file.
4157 *
4158 * Note: This function uses the per board buffer 'prtbuf' which is
4159 * allocated when the board is initialized in advansys_detect(). The
4160 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4161 * used to write to the buffer. The way asc_proc_copy() is written
4162 * if 'prtbuf' is too small it will not be overwritten. Instead the
4163 * user just won't get all the available statistics.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 */
Matthew Wilcox51219352007-10-02 21:55:22 -04004165static int
4166advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
4167 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004169 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04004170 char *cp;
4171 int cplen;
4172 int cnt;
4173 int totcnt;
4174 int leftlen;
4175 char *curbuf;
4176 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004178 ASC_DBG(1, "begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
Matthew Wilcox51219352007-10-02 21:55:22 -04004180 /*
4181 * User write not supported.
4182 */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004183 if (inout == TRUE)
4184 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
Matthew Wilcox51219352007-10-02 21:55:22 -04004186 /*
4187 * User read of /proc/scsi/advansys/[0...] file.
4188 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189
Matthew Wilcox51219352007-10-02 21:55:22 -04004190 /* Copy read data starting at the beginning of the buffer. */
4191 *start = buffer;
4192 curbuf = buffer;
4193 advoffset = 0;
4194 totcnt = 0;
4195 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196
Matthew Wilcox51219352007-10-02 21:55:22 -04004197 /*
4198 * Get board configuration information.
4199 *
4200 * advansys_info() returns the board string from its own static buffer.
4201 */
4202 cp = (char *)advansys_info(shost);
4203 strcat(cp, "\n");
4204 cplen = strlen(cp);
4205 /* Copy board information. */
4206 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4207 totcnt += cnt;
4208 leftlen -= cnt;
4209 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004210 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004211 return totcnt;
4212 }
4213 advoffset += cplen;
4214 curbuf += cnt;
4215
4216 /*
4217 * Display Wide Board BIOS Information.
4218 */
Matthew Wilcox9a256fa2007-10-02 21:55:28 -04004219 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004220 cp = boardp->prtbuf;
4221 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
4222 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4223 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4224 cplen);
4225 totcnt += cnt;
4226 leftlen -= cnt;
4227 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004228 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004229 return totcnt;
4230 }
4231 advoffset += cplen;
4232 curbuf += cnt;
4233 }
4234
4235 /*
4236 * Display driver information for each device attached to the board.
4237 */
4238 cp = boardp->prtbuf;
4239 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
4240 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4241 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4242 totcnt += cnt;
4243 leftlen -= cnt;
4244 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004245 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004246 return totcnt;
4247 }
4248 advoffset += cplen;
4249 curbuf += cnt;
4250
4251 /*
4252 * Display EEPROM configuration for the board.
4253 */
4254 cp = boardp->prtbuf;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004255 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004256 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004257 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04004258 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004259 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004260 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4261 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4262 totcnt += cnt;
4263 leftlen -= cnt;
4264 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004265 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004266 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004267 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004268 advoffset += cplen;
4269 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Matthew Wilcox51219352007-10-02 21:55:22 -04004271 /*
4272 * Display driver configuration and information for the board.
4273 */
4274 cp = boardp->prtbuf;
4275 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
4276 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4277 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4278 totcnt += cnt;
4279 leftlen -= cnt;
4280 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004281 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004282 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004283 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004284 advoffset += cplen;
4285 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286
Matthew Wilcox51219352007-10-02 21:55:22 -04004287#ifdef ADVANSYS_STATS
4288 /*
4289 * Display driver statistics for the board.
4290 */
4291 cp = boardp->prtbuf;
4292 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
4293 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4294 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4295 totcnt += cnt;
4296 leftlen -= cnt;
4297 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004298 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004299 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004300 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004301 advoffset += cplen;
4302 curbuf += cnt;
4303#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Matthew Wilcox51219352007-10-02 21:55:22 -04004305 /*
4306 * Display Asc Library dynamic configuration information
4307 * for the board.
4308 */
4309 cp = boardp->prtbuf;
4310 if (ASC_NARROW_BOARD(boardp)) {
4311 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
4312 } else {
4313 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004314 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004315 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4316 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4317 totcnt += cnt;
4318 leftlen -= cnt;
4319 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004320 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004321 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004322 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004323 advoffset += cplen;
4324 curbuf += cnt;
4325
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004326 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004327
4328 return totcnt;
4329}
4330#endif /* CONFIG_PROC_FS */
4331
4332static void asc_scsi_done(struct scsi_cmnd *scp)
4333{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004334 struct asc_board *boardp = shost_priv(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04004335
4336 if (scp->use_sg)
4337 dma_unmap_sg(boardp->dev,
4338 (struct scatterlist *)scp->request_buffer,
4339 scp->use_sg, scp->sc_data_direction);
4340 else if (scp->request_bufflen)
4341 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
4342 scp->request_bufflen, scp->sc_data_direction);
4343
4344 ASC_STATS(scp->device->host, done);
4345
4346 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347}
4348
Matthew Wilcox51219352007-10-02 21:55:22 -04004349static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350{
Matthew Wilcox51219352007-10-02 21:55:22 -04004351 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Matthew Wilcox51219352007-10-02 21:55:22 -04004353 val = AscGetChipControl(iop_base) &
4354 (~
4355 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
4356 CC_CHIP_RESET));
4357 if (bank == 1) {
4358 val |= CC_BANK_ONE;
4359 } else if (bank == 2) {
4360 val |= CC_DIAG | CC_BANK_ONE;
4361 } else {
4362 val &= ~CC_BANK_ONE;
4363 }
4364 AscSetChipControl(iop_base, val);
Matthew Wilcox51219352007-10-02 21:55:22 -04004365}
4366
4367static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
4368{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004369 AscSetBank(iop_base, 1);
Matthew Wilcox51219352007-10-02 21:55:22 -04004370 AscWriteChipIH(iop_base, ins_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004371 AscSetBank(iop_base, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372}
4373
Matthew Wilcox51219352007-10-02 21:55:22 -04004374static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375{
Matthew Wilcox51219352007-10-02 21:55:22 -04004376 AscSetChipControl(iop_base, 0);
4377 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4378 return (0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004379 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004380 return (1);
4381}
4382
4383static int AscStopChip(PortAddr iop_base)
4384{
4385 uchar cc_val;
4386
4387 cc_val =
4388 AscGetChipControl(iop_base) &
4389 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
4390 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
4391 AscSetChipIH(iop_base, INS_HALT);
4392 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4393 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
4394 return (0);
4395 }
4396 return (1);
4397}
4398
4399static int AscIsChipHalted(PortAddr iop_base)
4400{
4401 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4402 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
4403 return (1);
4404 }
4405 }
4406 return (0);
4407}
4408
4409static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
4410{
4411 PortAddr iop_base;
4412 int i = 10;
4413
4414 iop_base = asc_dvc->iop_base;
4415 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
4416 && (i-- > 0)) {
4417 mdelay(100);
4418 }
4419 AscStopChip(iop_base);
4420 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
4421 udelay(60);
4422 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4423 AscSetChipIH(iop_base, INS_HALT);
4424 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
4425 AscSetChipControl(iop_base, CC_HALT);
4426 mdelay(200);
4427 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
4428 AscSetChipStatus(iop_base, 0);
4429 return (AscIsChipHalted(iop_base));
4430}
4431
4432static int AscFindSignature(PortAddr iop_base)
4433{
4434 ushort sig_word;
4435
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004436 ASC_DBG(1, "AscGetChipSignatureByte(0x%x) 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04004437 iop_base, AscGetChipSignatureByte(iop_base));
4438 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004439 ASC_DBG(1, "AscGetChipSignatureWord(0x%x) 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04004440 iop_base, AscGetChipSignatureWord(iop_base));
4441 sig_word = AscGetChipSignatureWord(iop_base);
4442 if ((sig_word == (ushort)ASC_1000_ID0W) ||
4443 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
4444 return (1);
4445 }
4446 }
4447 return (0);
4448}
4449
4450static void AscEnableInterrupt(PortAddr iop_base)
4451{
4452 ushort cfg;
4453
4454 cfg = AscGetChipCfgLsw(iop_base);
4455 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
Matthew Wilcox51219352007-10-02 21:55:22 -04004456}
4457
4458static void AscDisableInterrupt(PortAddr iop_base)
4459{
4460 ushort cfg;
4461
4462 cfg = AscGetChipCfgLsw(iop_base);
4463 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
Matthew Wilcox51219352007-10-02 21:55:22 -04004464}
4465
4466static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
4467{
4468 unsigned char byte_data;
4469 unsigned short word_data;
4470
4471 if (isodd_word(addr)) {
4472 AscSetChipLramAddr(iop_base, addr - 1);
4473 word_data = AscGetChipLramData(iop_base);
4474 byte_data = (word_data >> 8) & 0xFF;
4475 } else {
4476 AscSetChipLramAddr(iop_base, addr);
4477 word_data = AscGetChipLramData(iop_base);
4478 byte_data = word_data & 0xFF;
4479 }
4480 return byte_data;
4481}
4482
4483static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
4484{
4485 ushort word_data;
4486
4487 AscSetChipLramAddr(iop_base, addr);
4488 word_data = AscGetChipLramData(iop_base);
4489 return (word_data);
4490}
4491
4492#if CC_VERY_LONG_SG_LIST
4493static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
4494{
4495 ushort val_low, val_high;
4496 ASC_DCNT dword_data;
4497
4498 AscSetChipLramAddr(iop_base, addr);
4499 val_low = AscGetChipLramData(iop_base);
4500 val_high = AscGetChipLramData(iop_base);
4501 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
4502 return (dword_data);
4503}
4504#endif /* CC_VERY_LONG_SG_LIST */
4505
4506static void
4507AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
4508{
4509 int i;
4510
4511 AscSetChipLramAddr(iop_base, s_addr);
4512 for (i = 0; i < words; i++) {
4513 AscSetChipLramData(iop_base, set_wval);
4514 }
4515}
4516
4517static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
4518{
4519 AscSetChipLramAddr(iop_base, addr);
4520 AscSetChipLramData(iop_base, word_val);
Matthew Wilcox51219352007-10-02 21:55:22 -04004521}
4522
4523static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
4524{
4525 ushort word_data;
4526
4527 if (isodd_word(addr)) {
4528 addr--;
4529 word_data = AscReadLramWord(iop_base, addr);
4530 word_data &= 0x00FF;
4531 word_data |= (((ushort)byte_val << 8) & 0xFF00);
4532 } else {
4533 word_data = AscReadLramWord(iop_base, addr);
4534 word_data &= 0xFF00;
4535 word_data |= ((ushort)byte_val & 0x00FF);
4536 }
4537 AscWriteLramWord(iop_base, addr, word_data);
Matthew Wilcox51219352007-10-02 21:55:22 -04004538}
4539
4540/*
4541 * Copy 2 bytes to LRAM.
4542 *
4543 * The source data is assumed to be in little-endian order in memory
4544 * and is maintained in little-endian order when written to LRAM.
4545 */
4546static void
4547AscMemWordCopyPtrToLram(PortAddr iop_base,
4548 ushort s_addr, uchar *s_buffer, int words)
4549{
4550 int i;
4551
4552 AscSetChipLramAddr(iop_base, s_addr);
4553 for (i = 0; i < 2 * words; i += 2) {
4554 /*
4555 * On a little-endian system the second argument below
4556 * produces a little-endian ushort which is written to
4557 * LRAM in little-endian order. On a big-endian system
4558 * the second argument produces a big-endian ushort which
4559 * is "transparently" byte-swapped by outpw() and written
4560 * in little-endian order to LRAM.
4561 */
4562 outpw(iop_base + IOP_RAM_DATA,
4563 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
4564 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004565}
4566
4567/*
4568 * Copy 4 bytes to LRAM.
4569 *
4570 * The source data is assumed to be in little-endian order in memory
4571 * and is maintained in little-endian order when writen to LRAM.
4572 */
4573static void
4574AscMemDWordCopyPtrToLram(PortAddr iop_base,
4575 ushort s_addr, uchar *s_buffer, int dwords)
4576{
4577 int i;
4578
4579 AscSetChipLramAddr(iop_base, s_addr);
4580 for (i = 0; i < 4 * dwords; i += 4) {
4581 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
4582 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
4583 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004584}
4585
4586/*
4587 * Copy 2 bytes from LRAM.
4588 *
4589 * The source data is assumed to be in little-endian order in LRAM
4590 * and is maintained in little-endian order when written to memory.
4591 */
4592static void
4593AscMemWordCopyPtrFromLram(PortAddr iop_base,
4594 ushort s_addr, uchar *d_buffer, int words)
4595{
4596 int i;
4597 ushort word;
4598
4599 AscSetChipLramAddr(iop_base, s_addr);
4600 for (i = 0; i < 2 * words; i += 2) {
4601 word = inpw(iop_base + IOP_RAM_DATA);
4602 d_buffer[i] = word & 0xff;
4603 d_buffer[i + 1] = (word >> 8) & 0xff;
4604 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004605}
4606
4607static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
4608{
4609 ASC_DCNT sum;
4610 int i;
4611
4612 sum = 0L;
4613 for (i = 0; i < words; i++, s_addr += 2) {
4614 sum += AscReadLramWord(iop_base, s_addr);
4615 }
4616 return (sum);
4617}
4618
4619static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
4620{
4621 uchar i;
4622 ushort s_addr;
4623 PortAddr iop_base;
4624 ushort warn_code;
4625
4626 iop_base = asc_dvc->iop_base;
4627 warn_code = 0;
4628 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
4629 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
4630 64) >> 1));
4631 i = ASC_MIN_ACTIVE_QNO;
4632 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
4633 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4634 (uchar)(i + 1));
4635 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4636 (uchar)(asc_dvc->max_total_qng));
4637 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4638 (uchar)i);
4639 i++;
4640 s_addr += ASC_QBLK_SIZE;
4641 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
4642 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4643 (uchar)(i + 1));
4644 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4645 (uchar)(i - 1));
4646 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4647 (uchar)i);
4648 }
4649 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4650 (uchar)ASC_QLINK_END);
4651 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4652 (uchar)(asc_dvc->max_total_qng - 1));
4653 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4654 (uchar)asc_dvc->max_total_qng);
4655 i++;
4656 s_addr += ASC_QBLK_SIZE;
4657 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
4658 i++, s_addr += ASC_QBLK_SIZE) {
4659 AscWriteLramByte(iop_base,
4660 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
4661 AscWriteLramByte(iop_base,
4662 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
4663 AscWriteLramByte(iop_base,
4664 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
4665 }
4666 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667}
4668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004669static ASC_DCNT
4670AscLoadMicroCode(PortAddr iop_base,
4671 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004673 ASC_DCNT chksum;
4674 ushort mcode_word_size;
4675 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004677 /* Write the microcode buffer starting at LRAM address 0. */
4678 mcode_word_size = (ushort)(mcode_size >> 1);
4679 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
4680 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004682 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004683 ASC_DBG(1, "chksum 0x%lx\n", (ulong)chksum);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004684 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
4685 (ushort)ASC_CODE_SEC_BEG,
4686 (ushort)((mcode_size -
4687 s_addr - (ushort)
4688 ASC_CODE_SEC_BEG) /
4689 2));
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004690 ASC_DBG(1, "mcode_chksum 0x%lx\n", (ulong)mcode_chksum);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004691 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
4692 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004693 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004694}
4695
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004697static uchar _asc_mcode_buf[] = {
4698 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004699 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
4704 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4705 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004706 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004707 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
4708 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
4709 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004710 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004711 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
4712 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
4713 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004714 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004715 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
4716 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
4717 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004718 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004719 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
4720 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
4721 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004722 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004723 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
4724 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
4725 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004726 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004727 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
4728 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
4729 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004730 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004731 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
4732 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
4733 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004734 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004735 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
4736 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
4737 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004738 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004739 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
4740 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
4741 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004742 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004743 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
4744 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
4745 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004746 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004747 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
4748 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
4749 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004750 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004751 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
4752 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
4753 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004754 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004755 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
4756 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
4757 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004758 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004759 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
4760 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
4761 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004762 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004763 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
4764 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
4765 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004766 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004767 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
4768 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
4769 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004770 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004771 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
4772 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
4773 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004774 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004775 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
4776 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
4777 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004778 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004779 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
4780 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
4781 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004782 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004783 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
4784 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
4785 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004786 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004787 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
4788 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
4789 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004790 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004791 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
4792 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
4793 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004794 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004795 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
4796 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
4797 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004798 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004799 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
4800 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
4801 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004802 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004803 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
4804 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
4805 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004806 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004807 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
4808 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
4809 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004810 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004811 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
4812 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
4813 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004814 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004815 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
4816 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
4817 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004818 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004819 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
4820 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
4821 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004822 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004823 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
4824 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
4825 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004826 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004827 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
4828 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
4829 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004830 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004831 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
4832 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
4833 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004834 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004835 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
4836 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
4837 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004838 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004839 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
4840 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
4841 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004842 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004843 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
4844 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
4845 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004846 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004847 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
4848 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
4849 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004850 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004851 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
4852 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
4853 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004854 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004855 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
4856 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
4857 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004858 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004859 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
4860 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
4861 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004862 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004863 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
4864 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
4865 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004866 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004867 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
4868 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
4869 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004870 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004871 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
4872 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
4873 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004874 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004875 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
4876 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
4877 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004878 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004879 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
4880 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
4881 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004882 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004883 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
4884 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
4885 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004886 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004887 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
4888 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
4889 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890};
4891
Matthew Wilcox51219352007-10-02 21:55:22 -04004892static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004893static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004896static unsigned char _adv_asc3550_buf[] = {
4897 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004898 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
4899 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
4900 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004901 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004902 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
4903 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
4904 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004905 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004906 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
4907 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
4908 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004909 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004910 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
4911 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
4912 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004913 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004914 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
4915 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
4916 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004917 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004918 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
4919 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
4920 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004921 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004922 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
4923 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
4924 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004925 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004926 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
4927 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
4928 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004929 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004930 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
4931 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
4932 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004933 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004934 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
4935 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
4936 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004937 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004938 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
4939 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
4940 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004941 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004942 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
4943 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
4944 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004945 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004946 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
4947 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
4948 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004949 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004950 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
4951 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
4952 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004953 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004954 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
4955 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
4956 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004957 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004958 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
4959 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
4960 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004961 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004962 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
4963 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
4964 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004965 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004966 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
4967 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
4968 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004969 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004970 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
4971 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
4972 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004973 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004974 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
4975 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
4976 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004977 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004978 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
4979 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
4980 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004981 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004982 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
4983 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
4984 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004985 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004986 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
4987 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
4988 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004989 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004990 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
4991 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
4992 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004993 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004994 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
4995 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
4996 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004997 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004998 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
4999 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
5000 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005001 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005002 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
5003 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
5004 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005005 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005006 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
5007 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
5008 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005009 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005010 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
5011 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
5012 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005013 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005014 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
5015 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
5016 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005017 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005018 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
5019 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
5020 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005021 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005022 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
5023 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
5024 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005025 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005026 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
5027 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
5028 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005029 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005030 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
5031 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
5032 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005033 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005034 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
5035 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
5036 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005037 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005038 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
5039 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
5040 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005041 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005042 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5043 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
5044 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005045 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005046 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
5047 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
5048 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005049 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005050 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
5051 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
5052 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005053 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005054 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
5055 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
5056 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005057 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005058 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
5059 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
5060 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005061 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005062 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
5063 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
5064 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005065 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005066 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
5067 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
5068 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005069 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005070 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
5071 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
5072 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005073 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005074 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
5075 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
5076 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005077 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005078 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
5079 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
5080 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005081 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005082 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
5083 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
5084 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005085 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005086 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
5087 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
5088 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005089 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005090 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
5091 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
5092 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005093 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005094 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
5095 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
5096 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005097 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005098 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
5099 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
5100 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005101 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005102 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
5103 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
5104 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005105 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005106 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
5107 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
5108 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005109 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005110 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
5111 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
5112 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005113 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005114 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
5115 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
5116 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005117 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005118 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
5119 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
5120 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005121 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005122 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
5123 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
5124 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005125 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005126 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
5127 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
5128 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005129 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005130 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
5131 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
5132 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005133 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005134 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
5135 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
5136 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005137 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005138 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
5139 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
5140 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005141 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005142 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
5143 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
5144 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005145 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005146 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
5147 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
5148 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005149 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005150 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
5151 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
5152 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005153 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005154 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
5155 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
5156 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005157 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005158 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
5159 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
5160 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005161 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005162 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
5163 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
5164 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005165 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005166 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
5167 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
5168 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005169 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005170 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
5171 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
5172 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005173 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005174 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
5175 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
5176 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005177 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005178 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
5179 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
5180 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005181 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005182 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
5183 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
5184 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005185 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005186 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
5187 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
5188 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005189 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005190 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
5191 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
5192 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005193 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005194 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
5195 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
5196 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005197 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005198 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
5199 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
5200 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005201 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005202 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
5203 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
5204 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005205 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005206 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
5207 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
5208 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005209 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005210 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
5211 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
5212 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005213 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005214 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
5215 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
5216 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005217 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005218 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
5219 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
5220 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005221 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005222 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
5223 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
5224 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005225 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005226 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
5227 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
5228 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005229 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005230 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
5231 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
5232 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005233 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005234 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
5235 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
5236 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005237 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005238 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
5239 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
5240 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005241 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005242 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
5243 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
5244 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005245 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005246 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
5247 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
5248 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005249 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005250 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
5251 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
5252 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005253 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005254 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
5255 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
5256 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005257 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005258 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
5259 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
5260 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005261 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005262 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
5263 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
5264 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005265 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005266 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
5267 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
5268 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005269 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005270 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
5271 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
5272 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005273 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005274 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
5275 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
5276 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005277 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005278 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
5279 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
5280 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005281 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005282 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
5283 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
5284 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005285 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005286 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
5287 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
5288 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005289 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005290 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
5291 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
5292 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005293 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005294 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
5295 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
5296 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005297 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005298 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
5299 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
5300 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005301 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005302 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
5303 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
5304 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005305 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005306 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
5307 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
5308 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005309 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005310 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
5311 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
5312 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005313 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005314 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
5315 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316};
5317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005318static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
5319static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320
5321/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005322static unsigned char _adv_asc38C0800_buf[] = {
5323 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005324 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
5325 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
5326 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005327 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005328 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
5329 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
5330 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005331 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005332 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
5333 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
5334 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005335 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005336 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
5337 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
5338 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005339 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005340 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
5341 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
5342 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005343 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005344 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
5345 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
5346 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005347 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005348 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
5349 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
5350 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005351 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005352 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
5353 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
5354 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005355 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005356 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
5357 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
5358 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005359 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005360 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
5361 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
5362 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005363 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005364 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
5365 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
5366 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005367 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005368 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
5369 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5370 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005371 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005372 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
5373 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
5374 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005375 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005376 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
5377 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5378 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005379 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005380 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
5381 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
5382 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005383 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005384 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
5385 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
5386 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005387 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005388 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
5389 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
5390 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005391 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005392 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
5393 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
5394 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005395 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005396 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
5397 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
5398 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005399 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005400 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
5401 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
5402 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005403 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005404 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
5405 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
5406 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005407 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005408 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
5409 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
5410 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005411 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005412 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
5413 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
5414 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005415 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005416 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
5417 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
5418 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005419 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005420 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
5421 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
5422 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005423 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005424 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
5425 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
5426 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005427 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005428 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
5429 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
5430 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005431 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005432 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
5433 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
5434 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005435 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005436 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
5437 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
5438 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005439 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005440 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
5441 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
5442 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005443 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005444 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
5445 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
5446 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005447 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005448 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
5449 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
5450 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005451 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005452 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
5453 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
5454 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005455 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005456 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
5457 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
5458 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005459 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005460 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
5461 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
5462 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005463 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005464 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
5465 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
5466 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005467 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005468 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
5469 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
5470 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005471 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005472 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
5473 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
5474 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005475 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005476 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
5477 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
5478 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005479 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005480 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
5481 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
5482 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005483 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005484 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
5485 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
5486 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005487 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005488 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
5489 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
5490 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005491 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005492 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
5493 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
5494 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005495 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005496 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
5497 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
5498 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005499 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005500 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
5501 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
5502 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005503 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005504 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
5505 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
5506 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005507 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005508 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
5509 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
5510 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005511 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005512 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
5513 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
5514 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005515 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005516 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
5517 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
5518 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005519 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005520 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
5521 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
5522 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005523 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005524 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
5525 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
5526 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005527 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005528 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
5529 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
5530 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005531 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005532 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
5533 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
5534 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005535 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005536 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
5537 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
5538 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005539 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005540 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
5541 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
5542 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005543 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005544 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
5545 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
5546 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005547 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005548 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
5549 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
5550 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005551 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005552 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
5553 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
5554 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005555 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005556 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
5557 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
5558 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005559 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005560 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
5561 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
5562 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005563 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005564 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
5565 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
5566 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005567 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005568 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
5569 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
5570 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005571 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005572 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
5573 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
5574 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005575 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005576 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
5577 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
5578 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005579 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005580 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
5581 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
5582 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005583 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005584 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
5585 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
5586 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005587 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005588 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
5589 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
5590 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005591 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005592 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
5593 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
5594 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005595 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005596 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
5597 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
5598 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005599 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005600 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
5601 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
5602 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005603 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005604 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
5605 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
5606 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005607 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005608 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
5609 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
5610 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005611 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005612 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
5613 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
5614 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005615 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005616 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
5617 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
5618 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005619 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005620 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
5621 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
5622 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005623 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005624 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
5625 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
5626 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005627 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005628 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
5629 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
5630 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005631 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005632 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
5633 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
5634 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005635 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005636 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
5637 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
5638 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005639 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005640 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
5641 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
5642 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005643 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005644 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
5645 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
5646 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005647 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005648 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
5649 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
5650 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005651 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005652 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
5653 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
5654 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005655 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005656 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
5657 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
5658 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005659 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005660 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
5661 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
5662 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005663 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005664 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
5665 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
5666 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005667 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005668 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
5669 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5670 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005671 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005672 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5673 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
5674 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005675 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005676 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
5677 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
5678 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005679 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005680 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
5681 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
5682 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005683 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005684 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
5685 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
5686 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005687 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005688 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
5689 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
5690 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005691 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005692 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
5693 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
5694 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005695 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005696 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
5697 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
5698 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005699 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005700 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
5701 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
5702 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005703 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005704 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
5705 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
5706 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005707 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005708 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
5709 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
5710 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005711 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005712 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
5713 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
5714 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005715 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005716 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
5717 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
5718 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005719 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005720 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
5721 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
5722 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005723 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005724 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
5725 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
5726 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005727 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005728 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
5729 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
5730 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005731 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005732 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
5733 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
5734 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005735 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005736 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
5737 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
5738 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005739 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005740 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
5741 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
5742 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005743 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005744 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
5745 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
5746 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005747 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005748 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
5749 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
5750 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005751 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005752 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
5753 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
5754 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005755 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005756 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
5757 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
5758 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005759 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005760 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
5761 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
5762 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005763 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005764 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
5765 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
5766 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005767 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768};
5769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005770static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
5771static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772
5773/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005774static unsigned char _adv_asc38C1600_buf[] = {
5775 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005776 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
5777 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
5778 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005779 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005780 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
5781 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
5782 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005783 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005784 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
5785 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
5786 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005787 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005788 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
5789 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
5790 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005791 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005792 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
5793 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
5794 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005795 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005796 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
5797 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
5798 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005799 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005800 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
5801 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
5802 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005803 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005804 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
5805 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
5806 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005807 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005808 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
5809 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
5810 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005811 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005812 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
5813 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
5814 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005815 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005816 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
5817 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
5818 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005819 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005820 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
5821 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5822 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005823 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005824 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
5825 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
5826 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005827 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005828 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
5829 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
5830 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005831 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005832 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
5833 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
5834 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005835 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005836 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
5837 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
5838 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005839 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005840 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
5841 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
5842 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005843 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005844 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
5845 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
5846 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005847 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005848 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
5849 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
5850 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005851 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005852 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
5853 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
5854 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005855 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005856 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
5857 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
5858 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005859 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005860 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
5861 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
5862 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005863 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005864 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
5865 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
5866 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005867 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005868 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
5869 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
5870 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005871 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005872 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
5873 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
5874 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005875 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005876 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
5877 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
5878 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005879 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005880 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
5881 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
5882 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005883 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005884 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
5885 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
5886 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005887 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005888 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
5889 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
5890 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005891 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005892 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
5893 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
5894 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005895 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005896 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
5897 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
5898 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005899 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005900 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
5901 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
5902 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005903 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005904 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
5905 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
5906 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005907 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005908 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
5909 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
5910 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005911 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005912 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
5913 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
5914 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005915 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005916 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
5917 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
5918 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005919 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005920 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
5921 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
5922 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005923 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005924 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
5925 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
5926 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005927 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005928 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
5929 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
5930 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005931 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005932 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
5933 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
5934 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005935 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005936 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
5937 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
5938 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005939 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005940 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
5941 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5942 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005943 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005944 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
5945 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
5946 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005947 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005948 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
5949 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
5950 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005951 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005952 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
5953 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
5954 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005955 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005956 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
5957 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
5958 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005959 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005960 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
5961 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
5962 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005963 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005964 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
5965 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
5966 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005967 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005968 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
5969 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
5970 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005971 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005972 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
5973 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
5974 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005975 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005976 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
5977 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
5978 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005979 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005980 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
5981 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
5982 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005983 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005984 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
5985 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
5986 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005987 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005988 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
5989 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
5990 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005991 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005992 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
5993 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
5994 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005995 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005996 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
5997 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
5998 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005999 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006000 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
6001 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
6002 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006003 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006004 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
6005 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
6006 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006007 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006008 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
6009 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
6010 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006011 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006012 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
6013 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
6014 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006015 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006016 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
6017 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
6018 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006019 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006020 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
6021 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
6022 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006023 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006024 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
6025 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
6026 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006027 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006028 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
6029 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
6030 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006031 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006032 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
6033 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
6034 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006035 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006036 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
6037 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
6038 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006039 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006040 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
6041 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
6042 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006043 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006044 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
6045 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
6046 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006047 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006048 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
6049 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
6050 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006051 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006052 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
6053 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
6054 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006055 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006056 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
6057 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
6058 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006059 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006060 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
6061 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
6062 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006063 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006064 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
6065 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
6066 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006067 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006068 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
6069 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
6070 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006071 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006072 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
6073 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
6074 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006075 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006076 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
6077 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
6078 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006079 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006080 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
6081 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
6082 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006083 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006084 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
6085 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
6086 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006087 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006088 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
6089 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
6090 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006091 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006092 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
6093 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
6094 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006095 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006096 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
6097 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
6098 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006099 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006100 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
6101 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
6102 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006103 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006104 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
6105 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
6106 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006107 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006108 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
6109 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
6110 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006111 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006112 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
6113 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
6114 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006115 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006116 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
6117 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
6118 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006119 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006120 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
6121 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
6122 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006123 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006124 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
6125 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
6126 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006127 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006128 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
6129 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
6130 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006131 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006132 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
6133 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
6134 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006135 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006136 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
6137 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
6138 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006139 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006140 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
6141 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
6142 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006143 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006144 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
6145 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
6146 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006147 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006148 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
6149 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
6150 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006151 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006152 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
6153 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
6154 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006155 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006156 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
6157 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
6158 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006159 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006160 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
6161 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
6162 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006163 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006164 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
6165 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
6166 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006167 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006168 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
6169 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
6170 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006171 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006172 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
6173 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
6174 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006175 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006176 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
6177 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
6178 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006179 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006180 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
6181 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
6182 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006183 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006184 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
6185 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
6186 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006187 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006188 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
6189 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
6190 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006191 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006192 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
6193 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
6194 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006195 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006196 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
6197 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
6198 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006199 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006200 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
6201 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
6202 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006203 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006204 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
6205 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
6206 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006207 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006208 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
6209 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
6210 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006211 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006212 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
6213 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
6214 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006215 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006216 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
6217 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
6218 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006219 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006220 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
6221 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
6222 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006223 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006224 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
6225 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
6226 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006227 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006228 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
6229 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
6230 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006231 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006232 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
6233 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
6234 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006235 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006236 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
6237 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
6238 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006239 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006240 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
6241 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
6242 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006243 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006244 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
6245 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
6246 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006247 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006248 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
6249 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
6250 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006251 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006252 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
6253 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
6254 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006255 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006256 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
6257 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
6258 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006259 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006260 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
6261 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
6262 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006263 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006264 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
6265 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
6266 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006267 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006268 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
6269 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
6270 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006271 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006272 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
6273 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
6274 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006275 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006276 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
6277 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
6278 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006279 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006280 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
6281 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
6282 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006283 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006284 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
6285 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
6286 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006287 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006288 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
6289 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
6290 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006291 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006292 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
6293 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
6294 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006295 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006296 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
6297 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
6298 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006299 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006300 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
6301 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
6302 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006303};
6304
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006305static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
6306static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Matthew Wilcox51219352007-10-02 21:55:22 -04006308static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309{
Matthew Wilcox51219352007-10-02 21:55:22 -04006310 PortAddr iop_base;
6311 int i;
6312 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313
Matthew Wilcox51219352007-10-02 21:55:22 -04006314 iop_base = asc_dvc->iop_base;
6315 AscPutRiscVarFreeQHead(iop_base, 1);
6316 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6317 AscPutVarFreeQHead(iop_base, 1);
6318 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6319 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6320 (uchar)((int)asc_dvc->max_total_qng + 1));
6321 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6322 (uchar)((int)asc_dvc->max_total_qng + 2));
6323 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
6324 asc_dvc->max_total_qng);
6325 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6326 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6327 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6328 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6329 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6330 AscPutQDoneInProgress(iop_base, 0);
6331 lram_addr = ASC_QADR_BEG;
6332 for (i = 0; i < 32; i++, lram_addr += 2) {
6333 AscWriteLramWord(iop_base, lram_addr, 0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335}
6336
Matthew Wilcox51219352007-10-02 21:55:22 -04006337static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006338{
Matthew Wilcox51219352007-10-02 21:55:22 -04006339 int i;
6340 ushort warn_code;
6341 PortAddr iop_base;
6342 ASC_PADDR phy_addr;
6343 ASC_DCNT phy_size;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006344
Matthew Wilcox51219352007-10-02 21:55:22 -04006345 iop_base = asc_dvc->iop_base;
6346 warn_code = 0;
6347 for (i = 0; i <= ASC_MAX_TID; i++) {
6348 AscPutMCodeInitSDTRAtID(iop_base, i,
6349 asc_dvc->cfg->sdtr_period_offset[i]);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006350 }
6351
Matthew Wilcox51219352007-10-02 21:55:22 -04006352 AscInitQLinkVar(asc_dvc);
6353 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
6354 asc_dvc->cfg->disc_enable);
6355 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
6356 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006357
Matthew Wilcox51219352007-10-02 21:55:22 -04006358 /* Align overrun buffer on an 8 byte boundary. */
6359 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
6360 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
6361 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
6362 (uchar *)&phy_addr, 1);
6363 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
6364 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
6365 (uchar *)&phy_size, 1);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006366
Matthew Wilcox51219352007-10-02 21:55:22 -04006367 asc_dvc->cfg->mcode_date =
6368 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
6369 asc_dvc->cfg->mcode_version =
6370 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006371
Matthew Wilcox51219352007-10-02 21:55:22 -04006372 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6373 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6374 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
6375 return warn_code;
6376 }
6377 if (AscStartChip(iop_base) != 1) {
6378 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
6379 return warn_code;
6380 }
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006381
Matthew Wilcox51219352007-10-02 21:55:22 -04006382 return warn_code;
6383}
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006384
Matthew Wilcox51219352007-10-02 21:55:22 -04006385static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
6386{
6387 ushort warn_code;
6388 PortAddr iop_base;
6389
6390 iop_base = asc_dvc->iop_base;
6391 warn_code = 0;
6392 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
6393 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
6394 AscResetChipAndScsiBus(asc_dvc);
6395 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6396 }
6397 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
6398 if (asc_dvc->err_code != 0)
6399 return UW_ERR;
6400 if (!AscFindSignature(asc_dvc->iop_base)) {
6401 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
6402 return warn_code;
6403 }
6404 AscDisableInterrupt(iop_base);
6405 warn_code |= AscInitLram(asc_dvc);
6406 if (asc_dvc->err_code != 0)
6407 return UW_ERR;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04006408 ASC_DBG(1, "_asc_mcode_chksum 0x%lx\n", (ulong)_asc_mcode_chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -04006409 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
6410 _asc_mcode_size) != _asc_mcode_chksum) {
6411 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
6412 return warn_code;
6413 }
6414 warn_code |= AscInitMicroCodeVar(asc_dvc);
6415 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
6416 AscEnableInterrupt(iop_base);
6417 return warn_code;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006418}
6419
Linus Torvalds1da177e2005-04-16 15:20:36 -07006420/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006421 * Load the Microcode
6422 *
6423 * Write the microcode image to RISC memory starting at address 0.
6424 *
6425 * The microcode is stored compressed in the following format:
6426 *
6427 * 254 word (508 byte) table indexed by byte code followed
6428 * by the following byte codes:
6429 *
6430 * 1-Byte Code:
6431 * 00: Emit word 0 in table.
6432 * 01: Emit word 1 in table.
6433 * .
6434 * FD: Emit word 253 in table.
6435 *
6436 * Multi-Byte Code:
6437 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
6438 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
6439 *
6440 * Returns 0 or an error if the checksum doesn't match
6441 */
6442static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
6443 int memsize, int chksum)
6444{
6445 int i, j, end, len = 0;
6446 ADV_DCNT sum;
6447
6448 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6449
6450 for (i = 253 * 2; i < size; i++) {
6451 if (buf[i] == 0xff) {
6452 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
6453 for (j = 0; j < buf[i + 1]; j++) {
6454 AdvWriteWordAutoIncLram(iop_base, word);
6455 len += 2;
6456 }
6457 i += 3;
6458 } else if (buf[i] == 0xfe) {
6459 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
6460 AdvWriteWordAutoIncLram(iop_base, word);
6461 i += 2;
6462 len += 2;
6463 } else {
6464 unsigned char off = buf[i] * 2;
6465 unsigned short word = (buf[off + 1] << 8) | buf[off];
6466 AdvWriteWordAutoIncLram(iop_base, word);
6467 len += 2;
6468 }
6469 }
6470
6471 end = len;
6472
6473 while (len < memsize) {
6474 AdvWriteWordAutoIncLram(iop_base, 0);
6475 len += 2;
6476 }
6477
6478 /* Verify the microcode checksum. */
6479 sum = 0;
6480 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6481
6482 for (len = 0; len < end; len += 2) {
6483 sum += AdvReadWordAutoIncLram(iop_base);
6484 }
6485
6486 if (sum != chksum)
6487 return ASC_IERR_MCODE_CHKSUM;
6488
6489 return 0;
6490}
6491
6492/*
Matthew Wilcox51219352007-10-02 21:55:22 -04006493 * DvcGetPhyAddr()
6494 *
6495 * Return the physical address of 'vaddr' and set '*lenp' to the
6496 * number of physically contiguous bytes that follow 'vaddr'.
6497 * 'flag' indicates the type of structure whose physical address
6498 * is being translated.
6499 *
6500 * Note: Because Linux currently doesn't page the kernel and all
6501 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
6502 */
6503ADV_PADDR
6504DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
6505 uchar *vaddr, ADV_SDCNT *lenp, int flag)
6506{
6507 ADV_PADDR paddr = virt_to_bus(vaddr);
6508
Matthew Wilcoxb352f922007-10-02 21:55:33 -04006509 ASC_DBG(4, "vaddr 0x%p, lenp 0x%p *lenp %lu, paddr 0x%lx\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04006510 vaddr, lenp, (ulong)*((ulong *)lenp), (ulong)paddr);
6511
6512 return paddr;
6513}
6514
6515static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
6516{
6517 ADV_CARR_T *carrp;
6518 ADV_SDCNT buf_size;
6519 ADV_PADDR carr_paddr;
6520
6521 BUG_ON(!asc_dvc->carrier_buf);
6522
6523 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
6524 asc_dvc->carr_freelist = NULL;
6525 if (carrp == asc_dvc->carrier_buf) {
6526 buf_size = ADV_CARRIER_BUFSIZE;
6527 } else {
6528 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
6529 }
6530
6531 do {
6532 /* Get physical address of the carrier 'carrp'. */
6533 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
6534 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
6535 (uchar *)carrp,
6536 (ADV_SDCNT *)&contig_len,
6537 ADV_IS_CARRIER_FLAG));
6538
6539 buf_size -= sizeof(ADV_CARR_T);
6540
6541 /*
6542 * If the current carrier is not physically contiguous, then
6543 * maybe there was a page crossing. Try the next carrier
6544 * aligned start address.
6545 */
6546 if (contig_len < sizeof(ADV_CARR_T)) {
6547 carrp++;
6548 continue;
6549 }
6550
6551 carrp->carr_pa = carr_paddr;
6552 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
6553
6554 /*
6555 * Insert the carrier at the beginning of the freelist.
6556 */
6557 carrp->next_vpa =
6558 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
6559 asc_dvc->carr_freelist = carrp;
6560
6561 carrp++;
6562 } while (buf_size > 0);
6563}
6564
6565/*
6566 * Send an idle command to the chip and wait for completion.
6567 *
6568 * Command completion is polled for once per microsecond.
6569 *
6570 * The function can be called from anywhere including an interrupt handler.
6571 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
6572 * functions to prevent reentrancy.
6573 *
6574 * Return Values:
6575 * ADV_TRUE - command completed successfully
6576 * ADV_FALSE - command failed
6577 * ADV_ERROR - command timed out
6578 */
6579static int
6580AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
6581 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
6582{
6583 int result;
6584 ADV_DCNT i, j;
6585 AdvPortAddr iop_base;
6586
6587 iop_base = asc_dvc->iop_base;
6588
6589 /*
6590 * Clear the idle command status which is set by the microcode
6591 * to a non-zero value to indicate when the command is completed.
6592 * The non-zero result is one of the IDLE_CMD_STATUS_* values
6593 */
6594 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
6595
6596 /*
6597 * Write the idle command value after the idle command parameter
6598 * has been written to avoid a race condition. If the order is not
6599 * followed, the microcode may process the idle command before the
6600 * parameters have been written to LRAM.
6601 */
6602 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
6603 cpu_to_le32(idle_cmd_parameter));
6604 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
6605
6606 /*
6607 * Tickle the RISC to tell it to process the idle command.
6608 */
6609 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
6610 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
6611 /*
6612 * Clear the tickle value. In the ASC-3550 the RISC flag
6613 * command 'clr_tickle_b' does not work unless the host
6614 * value is cleared.
6615 */
6616 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
6617 }
6618
6619 /* Wait for up to 100 millisecond for the idle command to timeout. */
6620 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
6621 /* Poll once each microsecond for command completion. */
6622 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
6623 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
6624 result);
6625 if (result != 0)
6626 return result;
6627 udelay(1);
6628 }
6629 }
6630
6631 BUG(); /* The idle command should never timeout. */
6632 return ADV_ERROR;
6633}
6634
6635/*
6636 * Reset SCSI Bus and purge all outstanding requests.
6637 *
6638 * Return Value:
6639 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
6640 * ADV_FALSE(0) - Microcode command failed.
6641 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
6642 * may be hung which requires driver recovery.
6643 */
6644static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
6645{
6646 int status;
6647
6648 /*
6649 * Send the SCSI Bus Reset idle start idle command which asserts
6650 * the SCSI Bus Reset signal.
6651 */
6652 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
6653 if (status != ADV_TRUE) {
6654 return status;
6655 }
6656
6657 /*
6658 * Delay for the specified SCSI Bus Reset hold time.
6659 *
6660 * The hold time delay is done on the host because the RISC has no
6661 * microsecond accurate timer.
6662 */
6663 udelay(ASC_SCSI_RESET_HOLD_TIME_US);
6664
6665 /*
6666 * Send the SCSI Bus Reset end idle command which de-asserts
6667 * the SCSI Bus Reset signal and purges any pending requests.
6668 */
6669 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
6670 if (status != ADV_TRUE) {
6671 return status;
6672 }
6673
6674 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6675
6676 return status;
6677}
6678
6679/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006680 * Initialize the ASC-3550.
6681 *
6682 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
6683 *
6684 * For a non-fatal error return a warning code. If there are no warnings
6685 * then 0 is returned.
6686 *
6687 * Needed after initialization for error recovery.
6688 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006689static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006690{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006691 AdvPortAddr iop_base;
6692 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006693 int begin_addr;
6694 int end_addr;
6695 ushort code_sum;
6696 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006697 int i;
6698 ushort scsi_cfg1;
6699 uchar tid;
6700 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
6701 ushort wdtr_able = 0, sdtr_able, tagqng_able;
6702 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006703
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006704 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006705 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006706 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006708 /*
6709 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
6710 */
6711 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006712 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006713 return ADV_ERROR;
6714 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006716 warn_code = 0;
6717 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006719 /*
6720 * Save the RISC memory BIOS region before writing the microcode.
6721 * The BIOS may already be loaded and using its RISC LRAM region
6722 * so its region must be saved and restored.
6723 *
6724 * Note: This code makes the assumption, which is currently true,
6725 * that a chip reset does not clear RISC LRAM.
6726 */
6727 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6728 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6729 bios_mem[i]);
6730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006732 /*
6733 * Save current per TID negotiated values.
6734 */
6735 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
6736 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006738 bios_version =
6739 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
6740 major = (bios_version >> 12) & 0xF;
6741 minor = (bios_version >> 8) & 0xF;
6742 if (major < 3 || (major == 3 && minor == 1)) {
6743 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
6744 AdvReadWordLram(iop_base, 0x120, wdtr_able);
6745 } else {
6746 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6747 }
6748 }
6749 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
6750 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6751 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6752 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
6753 max_cmd[tid]);
6754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006755
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006756 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
6757 _adv_asc3550_size, ADV_3550_MEMSIZE,
6758 _adv_asc3550_chksum);
6759 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006760 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006761
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006762 /*
6763 * Restore the RISC memory BIOS region.
6764 */
6765 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6766 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6767 bios_mem[i]);
6768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006770 /*
6771 * Calculate and write the microcode code checksum to the microcode
6772 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
6773 */
6774 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
6775 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
6776 code_sum = 0;
6777 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
6778 for (word = begin_addr; word < end_addr; word += 2) {
6779 code_sum += AdvReadWordAutoIncLram(iop_base);
6780 }
6781 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006783 /*
6784 * Read and save microcode version and date.
6785 */
6786 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
6787 asc_dvc->cfg->mcode_date);
6788 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
6789 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006790
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006791 /*
6792 * Set the chip type to indicate the ASC3550.
6793 */
6794 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006796 /*
6797 * If the PCI Configuration Command Register "Parity Error Response
6798 * Control" Bit was clear (0), then set the microcode variable
6799 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
6800 * to ignore DMA parity errors.
6801 */
6802 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
6803 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6804 word |= CONTROL_FLAG_IGNORE_PERR;
6805 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006807
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006808 /*
6809 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
6810 * threshold of 128 bytes. This register is only accessible to the host.
6811 */
6812 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
6813 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006815 /*
6816 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006817 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006818 * device reports it is capable of in Inquiry byte 7.
6819 *
6820 * If SCSI Bus Resets have been disabled, then directly set
6821 * SDTR and WDTR from the EEPROM configuration. This will allow
6822 * the BIOS and warm boot to work without a SCSI bus hang on
6823 * the Inquiry caused by host and target mismatched DTR values.
6824 * Without the SCSI Bus Reset, before an Inquiry a device can't
6825 * be assumed to be in Asynchronous, Narrow mode.
6826 */
6827 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
6828 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
6829 asc_dvc->wdtr_able);
6830 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
6831 asc_dvc->sdtr_able);
6832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006833
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006834 /*
6835 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
6836 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
6837 * bitmask. These values determine the maximum SDTR speed negotiated
6838 * with a device.
6839 *
6840 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
6841 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
6842 * without determining here whether the device supports SDTR.
6843 *
6844 * 4-bit speed SDTR speed name
6845 * =========== ===============
6846 * 0000b (0x0) SDTR disabled
6847 * 0001b (0x1) 5 Mhz
6848 * 0010b (0x2) 10 Mhz
6849 * 0011b (0x3) 20 Mhz (Ultra)
6850 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
6851 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
6852 * 0110b (0x6) Undefined
6853 * .
6854 * 1111b (0xF) Undefined
6855 */
6856 word = 0;
6857 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6858 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
6859 /* Set Ultra speed for TID 'tid'. */
6860 word |= (0x3 << (4 * (tid % 4)));
6861 } else {
6862 /* Set Fast speed for TID 'tid'. */
6863 word |= (0x2 << (4 * (tid % 4)));
6864 }
6865 if (tid == 3) { /* Check if done with sdtr_speed1. */
6866 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
6867 word = 0;
6868 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
6869 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
6870 word = 0;
6871 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
6872 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
6873 word = 0;
6874 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
6875 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
6876 /* End of loop. */
6877 }
6878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006879
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006880 /*
6881 * Set microcode operating variable for the disconnect per TID bitmask.
6882 */
6883 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
6884 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006885
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006886 /*
6887 * Set SCSI_CFG0 Microcode Default Value.
6888 *
6889 * The microcode will set the SCSI_CFG0 register using this value
6890 * after it is started below.
6891 */
6892 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
6893 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
6894 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006896 /*
6897 * Determine SCSI_CFG1 Microcode Default Value.
6898 *
6899 * The microcode will set the SCSI_CFG1 register using this value
6900 * after it is started below.
6901 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006902
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006903 /* Read current SCSI_CFG1 Register value. */
6904 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006906 /*
6907 * If all three connectors are in use, return an error.
6908 */
6909 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
6910 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
6911 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
6912 return ADV_ERROR;
6913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006915 /*
6916 * If the internal narrow cable is reversed all of the SCSI_CTRL
6917 * register signals will be set. Check for and return an error if
6918 * this condition is found.
6919 */
6920 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
6921 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
6922 return ADV_ERROR;
6923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006925 /*
6926 * If this is a differential board and a single-ended device
6927 * is attached to one of the connectors, return an error.
6928 */
6929 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
6930 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
6931 return ADV_ERROR;
6932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006933
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006934 /*
6935 * If automatic termination control is enabled, then set the
6936 * termination value based on a table listed in a_condor.h.
6937 *
6938 * If manual termination was specified with an EEPROM setting
6939 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
6940 * is ready to be 'ored' into SCSI_CFG1.
6941 */
6942 if (asc_dvc->cfg->termination == 0) {
6943 /*
6944 * The software always controls termination by setting TERM_CTL_SEL.
6945 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
6946 */
6947 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006949 switch (scsi_cfg1 & CABLE_DETECT) {
6950 /* TERM_CTL_H: on, TERM_CTL_L: on */
6951 case 0x3:
6952 case 0x7:
6953 case 0xB:
6954 case 0xD:
6955 case 0xE:
6956 case 0xF:
6957 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
6958 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006960 /* TERM_CTL_H: on, TERM_CTL_L: off */
6961 case 0x1:
6962 case 0x5:
6963 case 0x9:
6964 case 0xA:
6965 case 0xC:
6966 asc_dvc->cfg->termination |= TERM_CTL_H;
6967 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006969 /* TERM_CTL_H: off, TERM_CTL_L: off */
6970 case 0x2:
6971 case 0x6:
6972 break;
6973 }
6974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006976 /*
6977 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
6978 */
6979 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006981 /*
6982 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
6983 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
6984 * referenced, because the hardware internally inverts
6985 * the Termination High and Low bits if TERM_POL is set.
6986 */
6987 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006989 /*
6990 * Set SCSI_CFG1 Microcode Default Value
6991 *
6992 * Set filter value and possibly modified termination control
6993 * bits in the Microcode SCSI_CFG1 Register Value.
6994 *
6995 * The microcode will set the SCSI_CFG1 register using this value
6996 * after it is started below.
6997 */
6998 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
6999 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007000
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007001 /*
7002 * Set MEM_CFG Microcode Default Value
7003 *
7004 * The microcode will set the MEM_CFG register using this value
7005 * after it is started below.
7006 *
7007 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7008 * are defined.
7009 *
7010 * ASC-3550 has 8KB internal memory.
7011 */
7012 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7013 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007015 /*
7016 * Set SEL_MASK Microcode Default Value
7017 *
7018 * The microcode will set the SEL_MASK register using this value
7019 * after it is started below.
7020 */
7021 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7022 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007023
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007024 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007025
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007026 /*
7027 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7028 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007030 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7031 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7032 return ADV_ERROR;
7033 }
7034 asc_dvc->carr_freelist = (ADV_CARR_T *)
7035 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007036
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007037 /*
7038 * The first command issued will be placed in the stopper carrier.
7039 */
7040 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007041
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007042 /*
7043 * Set RISC ICQ physical address start value.
7044 */
7045 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007047 /*
7048 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7049 */
7050 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7051 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7052 return ADV_ERROR;
7053 }
7054 asc_dvc->carr_freelist = (ADV_CARR_T *)
7055 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007057 /*
7058 * The first command completed by the RISC will be placed in
7059 * the stopper.
7060 *
7061 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7062 * completed the RISC will set the ASC_RQ_STOPPER bit.
7063 */
7064 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007066 /*
7067 * Set RISC IRQ physical address start value.
7068 */
7069 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7070 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007072 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7073 (ADV_INTR_ENABLE_HOST_INTR |
7074 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007076 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7077 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007079 /* finally, finally, gentlemen, start your engine */
7080 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007082 /*
7083 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7084 * Resets should be performed. The RISC has to be running
7085 * to issue a SCSI Bus Reset.
7086 */
7087 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7088 /*
7089 * If the BIOS Signature is present in memory, restore the
7090 * BIOS Handshake Configuration Table and do not perform
7091 * a SCSI Bus Reset.
7092 */
7093 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7094 0x55AA) {
7095 /*
7096 * Restore per TID negotiated values.
7097 */
7098 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7099 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7100 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7101 tagqng_able);
7102 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7103 AdvWriteByteLram(iop_base,
7104 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7105 max_cmd[tid]);
7106 }
7107 } else {
7108 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7109 warn_code = ASC_WARN_BUSRESET_ERROR;
7110 }
7111 }
7112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007113
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007114 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007115}
7116
7117/*
7118 * Initialize the ASC-38C0800.
7119 *
7120 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
7121 *
7122 * For a non-fatal error return a warning code. If there are no warnings
7123 * then 0 is returned.
7124 *
7125 * Needed after initialization for error recovery.
7126 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007127static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007129 AdvPortAddr iop_base;
7130 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007131 int begin_addr;
7132 int end_addr;
7133 ushort code_sum;
7134 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007135 int i;
7136 ushort scsi_cfg1;
7137 uchar byte;
7138 uchar tid;
7139 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7140 ushort wdtr_able, sdtr_able, tagqng_able;
7141 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007143 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007144 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007145 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007146
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007147 /*
7148 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
7149 */
7150 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
7151 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7152 return ADV_ERROR;
7153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007154
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007155 warn_code = 0;
7156 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007157
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007158 /*
7159 * Save the RISC memory BIOS region before writing the microcode.
7160 * The BIOS may already be loaded and using its RISC LRAM region
7161 * so its region must be saved and restored.
7162 *
7163 * Note: This code makes the assumption, which is currently true,
7164 * that a chip reset does not clear RISC LRAM.
7165 */
7166 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7167 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7168 bios_mem[i]);
7169 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007171 /*
7172 * Save current per TID negotiated values.
7173 */
7174 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7175 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7176 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7177 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7178 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7179 max_cmd[tid]);
7180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007181
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007182 /*
7183 * RAM BIST (RAM Built-In Self Test)
7184 *
7185 * Address : I/O base + offset 0x38h register (byte).
7186 * Function: Bit 7-6(RW) : RAM mode
7187 * Normal Mode : 0x00
7188 * Pre-test Mode : 0x40
7189 * RAM Test Mode : 0x80
7190 * Bit 5 : unused
7191 * Bit 4(RO) : Done bit
7192 * Bit 3-0(RO) : Status
7193 * Host Error : 0x08
7194 * Int_RAM Error : 0x04
7195 * RISC Error : 0x02
7196 * SCSI Error : 0x01
7197 * No Error : 0x00
7198 *
7199 * Note: RAM BIST code should be put right here, before loading the
7200 * microcode and after saving the RISC memory BIOS region.
7201 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007202
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007203 /*
7204 * LRAM Pre-test
7205 *
7206 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7207 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7208 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7209 * to NORMAL_MODE, return an error too.
7210 */
7211 for (i = 0; i < 2; i++) {
7212 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007213 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007214 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7215 if ((byte & RAM_TEST_DONE) == 0
7216 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007217 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007218 return ADV_ERROR;
7219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007221 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007222 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007223 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7224 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007225 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007226 return ADV_ERROR;
7227 }
7228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007230 /*
7231 * LRAM Test - It takes about 1.5 ms to run through the test.
7232 *
7233 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7234 * If Done bit not set or Status not 0, save register byte, set the
7235 * err_code, and return an error.
7236 */
7237 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007238 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007240 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7241 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7242 /* Get here if Done bit not set or Status not 0. */
7243 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007244 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007245 return ADV_ERROR;
7246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007248 /* We need to reset back to normal mode after LRAM test passes. */
7249 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007250
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007251 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
7252 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
7253 _adv_asc38C0800_chksum);
7254 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007255 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007256
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007257 /*
7258 * Restore the RISC memory BIOS region.
7259 */
7260 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7261 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7262 bios_mem[i]);
7263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007265 /*
7266 * Calculate and write the microcode code checksum to the microcode
7267 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7268 */
7269 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7270 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7271 code_sum = 0;
7272 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7273 for (word = begin_addr; word < end_addr; word += 2) {
7274 code_sum += AdvReadWordAutoIncLram(iop_base);
7275 }
7276 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007278 /*
7279 * Read microcode version and date.
7280 */
7281 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7282 asc_dvc->cfg->mcode_date);
7283 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7284 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007286 /*
7287 * Set the chip type to indicate the ASC38C0800.
7288 */
7289 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007291 /*
7292 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7293 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7294 * cable detection and then we are able to read C_DET[3:0].
7295 *
7296 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7297 * Microcode Default Value' section below.
7298 */
7299 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7300 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7301 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007303 /*
7304 * If the PCI Configuration Command Register "Parity Error Response
7305 * Control" Bit was clear (0), then set the microcode variable
7306 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7307 * to ignore DMA parity errors.
7308 */
7309 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7310 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7311 word |= CONTROL_FLAG_IGNORE_PERR;
7312 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007315 /*
7316 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
7317 * bits for the default FIFO threshold.
7318 *
7319 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
7320 *
7321 * For DMA Errata #4 set the BC_THRESH_ENB bit.
7322 */
7323 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7324 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
7325 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007327 /*
7328 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007329 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007330 * device reports it is capable of in Inquiry byte 7.
7331 *
7332 * If SCSI Bus Resets have been disabled, then directly set
7333 * SDTR and WDTR from the EEPROM configuration. This will allow
7334 * the BIOS and warm boot to work without a SCSI bus hang on
7335 * the Inquiry caused by host and target mismatched DTR values.
7336 * Without the SCSI Bus Reset, before an Inquiry a device can't
7337 * be assumed to be in Asynchronous, Narrow mode.
7338 */
7339 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7340 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7341 asc_dvc->wdtr_able);
7342 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7343 asc_dvc->sdtr_able);
7344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007345
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007346 /*
7347 * Set microcode operating variables for DISC and SDTR_SPEED1,
7348 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7349 * configuration values.
7350 *
7351 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7352 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7353 * without determining here whether the device supports SDTR.
7354 */
7355 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7356 asc_dvc->cfg->disc_enable);
7357 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7358 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7359 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7360 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007361
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007362 /*
7363 * Set SCSI_CFG0 Microcode Default Value.
7364 *
7365 * The microcode will set the SCSI_CFG0 register using this value
7366 * after it is started below.
7367 */
7368 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7369 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7370 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 /*
7373 * Determine SCSI_CFG1 Microcode Default Value.
7374 *
7375 * The microcode will set the SCSI_CFG1 register using this value
7376 * after it is started below.
7377 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007379 /* Read current SCSI_CFG1 Register value. */
7380 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007381
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007382 /*
7383 * If the internal narrow cable is reversed all of the SCSI_CTRL
7384 * register signals will be set. Check for and return an error if
7385 * this condition is found.
7386 */
7387 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7388 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7389 return ADV_ERROR;
7390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007392 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007393 * All kind of combinations of devices attached to one of four
7394 * connectors are acceptable except HVD device attached. For example,
7395 * LVD device can be attached to SE connector while SE device attached
7396 * to LVD connector. If LVD device attached to SE connector, it only
7397 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007398 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007399 * If an HVD device is attached to one of LVD connectors, return an
7400 * error. However, there is no way to detect HVD device attached to
7401 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007402 */
7403 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007404 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007405 return ADV_ERROR;
7406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007407
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007408 /*
7409 * If either SE or LVD automatic termination control is enabled, then
7410 * set the termination value based on a table listed in a_condor.h.
7411 *
7412 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007413 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
7414 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007415 */
7416 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
7417 /* SE automatic termination control is enabled. */
7418 switch (scsi_cfg1 & C_DET_SE) {
7419 /* TERM_SE_HI: on, TERM_SE_LO: on */
7420 case 0x1:
7421 case 0x2:
7422 case 0x3:
7423 asc_dvc->cfg->termination |= TERM_SE;
7424 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007425
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007426 /* TERM_SE_HI: on, TERM_SE_LO: off */
7427 case 0x0:
7428 asc_dvc->cfg->termination |= TERM_SE_HI;
7429 break;
7430 }
7431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007432
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007433 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
7434 /* LVD automatic termination control is enabled. */
7435 switch (scsi_cfg1 & C_DET_LVD) {
7436 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
7437 case 0x4:
7438 case 0x8:
7439 case 0xC:
7440 asc_dvc->cfg->termination |= TERM_LVD;
7441 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007442
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007443 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
7444 case 0x0:
7445 break;
7446 }
7447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007449 /*
7450 * Clear any set TERM_SE and TERM_LVD bits.
7451 */
7452 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007453
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007454 /*
7455 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
7456 */
7457 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007458
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007459 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007460 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
7461 * bits and set possibly modified termination control bits in the
7462 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007463 */
7464 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007466 /*
7467 * Set SCSI_CFG1 Microcode Default Value
7468 *
7469 * Set possibly modified termination control and reset DIS_TERM_DRV
7470 * bits in the Microcode SCSI_CFG1 Register Value.
7471 *
7472 * The microcode will set the SCSI_CFG1 register using this value
7473 * after it is started below.
7474 */
7475 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007476
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007477 /*
7478 * Set MEM_CFG Microcode Default Value
7479 *
7480 * The microcode will set the MEM_CFG register using this value
7481 * after it is started below.
7482 *
7483 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7484 * are defined.
7485 *
7486 * ASC-38C0800 has 16KB internal memory.
7487 */
7488 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7489 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007490
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007491 /*
7492 * Set SEL_MASK Microcode Default Value
7493 *
7494 * The microcode will set the SEL_MASK register using this value
7495 * after it is started below.
7496 */
7497 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7498 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007499
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007500 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007501
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007502 /*
7503 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7504 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007505
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007506 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7507 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7508 return ADV_ERROR;
7509 }
7510 asc_dvc->carr_freelist = (ADV_CARR_T *)
7511 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007512
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007513 /*
7514 * The first command issued will be placed in the stopper carrier.
7515 */
7516 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007517
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007518 /*
7519 * Set RISC ICQ physical address start value.
7520 * carr_pa is LE, must be native before write
7521 */
7522 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007524 /*
7525 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7526 */
7527 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7528 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7529 return ADV_ERROR;
7530 }
7531 asc_dvc->carr_freelist = (ADV_CARR_T *)
7532 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007533
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007534 /*
7535 * The first command completed by the RISC will be placed in
7536 * the stopper.
7537 *
7538 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7539 * completed the RISC will set the ASC_RQ_STOPPER bit.
7540 */
7541 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007542
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007543 /*
7544 * Set RISC IRQ physical address start value.
7545 *
7546 * carr_pa is LE, must be native before write *
7547 */
7548 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7549 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007550
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007551 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7552 (ADV_INTR_ENABLE_HOST_INTR |
7553 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007554
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007555 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7556 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007557
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007558 /* finally, finally, gentlemen, start your engine */
7559 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007560
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007561 /*
7562 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7563 * Resets should be performed. The RISC has to be running
7564 * to issue a SCSI Bus Reset.
7565 */
7566 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7567 /*
7568 * If the BIOS Signature is present in memory, restore the
7569 * BIOS Handshake Configuration Table and do not perform
7570 * a SCSI Bus Reset.
7571 */
7572 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7573 0x55AA) {
7574 /*
7575 * Restore per TID negotiated values.
7576 */
7577 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7578 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7579 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7580 tagqng_able);
7581 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7582 AdvWriteByteLram(iop_base,
7583 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7584 max_cmd[tid]);
7585 }
7586 } else {
7587 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7588 warn_code = ASC_WARN_BUSRESET_ERROR;
7589 }
7590 }
7591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007592
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007593 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007594}
7595
7596/*
7597 * Initialize the ASC-38C1600.
7598 *
7599 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
7600 *
7601 * For a non-fatal error return a warning code. If there are no warnings
7602 * then 0 is returned.
7603 *
7604 * Needed after initialization for error recovery.
7605 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007606static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007607{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007608 AdvPortAddr iop_base;
7609 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007610 int begin_addr;
7611 int end_addr;
7612 ushort code_sum;
7613 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007614 int i;
7615 ushort scsi_cfg1;
7616 uchar byte;
7617 uchar tid;
7618 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7619 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
7620 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007622 /* If there is already an error, don't continue. */
7623 if (asc_dvc->err_code != 0) {
7624 return ADV_ERROR;
7625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007626
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007627 /*
7628 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
7629 */
7630 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
7631 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7632 return ADV_ERROR;
7633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007634
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007635 warn_code = 0;
7636 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007637
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007638 /*
7639 * Save the RISC memory BIOS region before writing the microcode.
7640 * The BIOS may already be loaded and using its RISC LRAM region
7641 * so its region must be saved and restored.
7642 *
7643 * Note: This code makes the assumption, which is currently true,
7644 * that a chip reset does not clear RISC LRAM.
7645 */
7646 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7647 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7648 bios_mem[i]);
7649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007651 /*
7652 * Save current per TID negotiated values.
7653 */
7654 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7655 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7656 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
7657 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7658 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7659 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7660 max_cmd[tid]);
7661 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007662
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007663 /*
7664 * RAM BIST (Built-In Self Test)
7665 *
7666 * Address : I/O base + offset 0x38h register (byte).
7667 * Function: Bit 7-6(RW) : RAM mode
7668 * Normal Mode : 0x00
7669 * Pre-test Mode : 0x40
7670 * RAM Test Mode : 0x80
7671 * Bit 5 : unused
7672 * Bit 4(RO) : Done bit
7673 * Bit 3-0(RO) : Status
7674 * Host Error : 0x08
7675 * Int_RAM Error : 0x04
7676 * RISC Error : 0x02
7677 * SCSI Error : 0x01
7678 * No Error : 0x00
7679 *
7680 * Note: RAM BIST code should be put right here, before loading the
7681 * microcode and after saving the RISC memory BIOS region.
7682 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007683
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007684 /*
7685 * LRAM Pre-test
7686 *
7687 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7688 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7689 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7690 * to NORMAL_MODE, return an error too.
7691 */
7692 for (i = 0; i < 2; i++) {
7693 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007694 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007695 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7696 if ((byte & RAM_TEST_DONE) == 0
7697 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007698 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007699 return ADV_ERROR;
7700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007702 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007703 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007704 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7705 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007706 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007707 return ADV_ERROR;
7708 }
7709 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007711 /*
7712 * LRAM Test - It takes about 1.5 ms to run through the test.
7713 *
7714 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7715 * If Done bit not set or Status not 0, save register byte, set the
7716 * err_code, and return an error.
7717 */
7718 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007719 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007720
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007721 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7722 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7723 /* Get here if Done bit not set or Status not 0. */
7724 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007725 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007726 return ADV_ERROR;
7727 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007728
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007729 /* We need to reset back to normal mode after LRAM test passes. */
7730 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007731
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007732 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
7733 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
7734 _adv_asc38C1600_chksum);
7735 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007736 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007738 /*
7739 * Restore the RISC memory BIOS region.
7740 */
7741 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7742 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7743 bios_mem[i]);
7744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007745
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007746 /*
7747 * Calculate and write the microcode code checksum to the microcode
7748 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7749 */
7750 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7751 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7752 code_sum = 0;
7753 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7754 for (word = begin_addr; word < end_addr; word += 2) {
7755 code_sum += AdvReadWordAutoIncLram(iop_base);
7756 }
7757 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007759 /*
7760 * Read microcode version and date.
7761 */
7762 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7763 asc_dvc->cfg->mcode_date);
7764 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7765 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007767 /*
7768 * Set the chip type to indicate the ASC38C1600.
7769 */
7770 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007771
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007772 /*
7773 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7774 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7775 * cable detection and then we are able to read C_DET[3:0].
7776 *
7777 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7778 * Microcode Default Value' section below.
7779 */
7780 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7781 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7782 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007783
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007784 /*
7785 * If the PCI Configuration Command Register "Parity Error Response
7786 * Control" Bit was clear (0), then set the microcode variable
7787 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7788 * to ignore DMA parity errors.
7789 */
7790 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7791 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7792 word |= CONTROL_FLAG_IGNORE_PERR;
7793 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007796 /*
7797 * If the BIOS control flag AIPP (Asynchronous Information
7798 * Phase Protection) disable bit is not set, then set the firmware
7799 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
7800 * AIPP checking and encoding.
7801 */
7802 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
7803 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7804 word |= CONTROL_FLAG_ENABLE_AIPP;
7805 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007807
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007808 /*
7809 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
7810 * and START_CTL_TH [3:2].
7811 */
7812 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7813 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007815 /*
7816 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007817 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007818 * device reports it is capable of in Inquiry byte 7.
7819 *
7820 * If SCSI Bus Resets have been disabled, then directly set
7821 * SDTR and WDTR from the EEPROM configuration. This will allow
7822 * the BIOS and warm boot to work without a SCSI bus hang on
7823 * the Inquiry caused by host and target mismatched DTR values.
7824 * Without the SCSI Bus Reset, before an Inquiry a device can't
7825 * be assumed to be in Asynchronous, Narrow mode.
7826 */
7827 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7828 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7829 asc_dvc->wdtr_able);
7830 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7831 asc_dvc->sdtr_able);
7832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007833
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007834 /*
7835 * Set microcode operating variables for DISC and SDTR_SPEED1,
7836 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7837 * configuration values.
7838 *
7839 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7840 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7841 * without determining here whether the device supports SDTR.
7842 */
7843 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7844 asc_dvc->cfg->disc_enable);
7845 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7846 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7847 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7848 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007850 /*
7851 * Set SCSI_CFG0 Microcode Default Value.
7852 *
7853 * The microcode will set the SCSI_CFG0 register using this value
7854 * after it is started below.
7855 */
7856 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7857 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7858 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007860 /*
7861 * Calculate SCSI_CFG1 Microcode Default Value.
7862 *
7863 * The microcode will set the SCSI_CFG1 register using this value
7864 * after it is started below.
7865 *
7866 * Each ASC-38C1600 function has only two cable detect bits.
7867 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
7868 */
7869 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007870
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007871 /*
7872 * If the cable is reversed all of the SCSI_CTRL register signals
7873 * will be set. Check for and return an error if this condition is
7874 * found.
7875 */
7876 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7877 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7878 return ADV_ERROR;
7879 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007881 /*
7882 * Each ASC-38C1600 function has two connectors. Only an HVD device
7883 * can not be connected to either connector. An LVD device or SE device
7884 * may be connected to either connecor. If an SE device is connected,
7885 * then at most Ultra speed (20 Mhz) can be used on both connectors.
7886 *
7887 * If an HVD device is attached, return an error.
7888 */
7889 if (scsi_cfg1 & HVD) {
7890 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
7891 return ADV_ERROR;
7892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007893
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007894 /*
7895 * Each function in the ASC-38C1600 uses only the SE cable detect and
7896 * termination because there are two connectors for each function. Each
7897 * function may use either LVD or SE mode. Corresponding the SE automatic
7898 * termination control EEPROM bits are used for each function. Each
7899 * function has its own EEPROM. If SE automatic control is enabled for
7900 * the function, then set the termination value based on a table listed
7901 * in a_condor.h.
7902 *
7903 * If manual termination is specified in the EEPROM for the function,
7904 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
7905 * ready to be 'ored' into SCSI_CFG1.
7906 */
7907 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06007908 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007909 /* SE automatic termination control is enabled. */
7910 switch (scsi_cfg1 & C_DET_SE) {
7911 /* TERM_SE_HI: on, TERM_SE_LO: on */
7912 case 0x1:
7913 case 0x2:
7914 case 0x3:
7915 asc_dvc->cfg->termination |= TERM_SE;
7916 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007917
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007918 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06007919 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007920 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
7921 } else {
7922 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
7923 asc_dvc->cfg->termination |= TERM_SE_HI;
7924 }
7925 break;
7926 }
7927 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007929 /*
7930 * Clear any set TERM_SE bits.
7931 */
7932 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007933
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007934 /*
7935 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
7936 */
7937 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007938
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007939 /*
7940 * Clear Big Endian and Terminator Polarity bits and set possibly
7941 * modified termination control bits in the Microcode SCSI_CFG1
7942 * Register Value.
7943 *
7944 * Big Endian bit is not used even on big endian machines.
7945 */
7946 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007948 /*
7949 * Set SCSI_CFG1 Microcode Default Value
7950 *
7951 * Set possibly modified termination control bits in the Microcode
7952 * SCSI_CFG1 Register Value.
7953 *
7954 * The microcode will set the SCSI_CFG1 register using this value
7955 * after it is started below.
7956 */
7957 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007959 /*
7960 * Set MEM_CFG Microcode Default Value
7961 *
7962 * The microcode will set the MEM_CFG register using this value
7963 * after it is started below.
7964 *
7965 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7966 * are defined.
7967 *
7968 * ASC-38C1600 has 32KB internal memory.
7969 *
7970 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
7971 * out a special 16K Adv Library and Microcode version. After the issue
7972 * resolved, we should turn back to the 32K support. Both a_condor.h and
7973 * mcode.sas files also need to be updated.
7974 *
7975 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7976 * BIOS_EN | RAM_SZ_32KB);
7977 */
7978 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7979 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007981 /*
7982 * Set SEL_MASK Microcode Default Value
7983 *
7984 * The microcode will set the SEL_MASK register using this value
7985 * after it is started below.
7986 */
7987 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7988 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007989
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007990 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007992 /*
7993 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7994 */
7995 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7996 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7997 return ADV_ERROR;
7998 }
7999 asc_dvc->carr_freelist = (ADV_CARR_T *)
8000 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008002 /*
8003 * The first command issued will be placed in the stopper carrier.
8004 */
8005 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008006
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008007 /*
8008 * Set RISC ICQ physical address start value. Initialize the
8009 * COMMA register to the same value otherwise the RISC will
8010 * prematurely detect a command is available.
8011 */
8012 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
8013 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
8014 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008015
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008016 /*
8017 * Set-up the RISC->Host Initiator Response Queue (IRQ).
8018 */
8019 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
8020 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8021 return ADV_ERROR;
8022 }
8023 asc_dvc->carr_freelist = (ADV_CARR_T *)
8024 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008025
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008026 /*
8027 * The first command completed by the RISC will be placed in
8028 * the stopper.
8029 *
8030 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
8031 * completed the RISC will set the ASC_RQ_STOPPER bit.
8032 */
8033 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008035 /*
8036 * Set RISC IRQ physical address start value.
8037 */
8038 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
8039 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008040
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008041 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
8042 (ADV_INTR_ENABLE_HOST_INTR |
8043 ADV_INTR_ENABLE_GLOBAL_INTR));
8044 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
8045 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008047 /* finally, finally, gentlemen, start your engine */
8048 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008049
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008050 /*
8051 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
8052 * Resets should be performed. The RISC has to be running
8053 * to issue a SCSI Bus Reset.
8054 */
8055 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
8056 /*
8057 * If the BIOS Signature is present in memory, restore the
8058 * per TID microcode operating variables.
8059 */
8060 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
8061 0x55AA) {
8062 /*
8063 * Restore per TID negotiated values.
8064 */
8065 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8066 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8067 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8068 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
8069 tagqng_able);
8070 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
8071 AdvWriteByteLram(iop_base,
8072 ASC_MC_NUMBER_OF_MAX_CMD + tid,
8073 max_cmd[tid]);
8074 }
8075 } else {
8076 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
8077 warn_code = ASC_WARN_BUSRESET_ERROR;
8078 }
8079 }
8080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008082 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008083}
8084
8085/*
Matthew Wilcox51219352007-10-02 21:55:22 -04008086 * Reset chip and SCSI Bus.
8087 *
8088 * Return Value:
8089 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
8090 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
8091 */
8092static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
8093{
8094 int status;
8095 ushort wdtr_able, sdtr_able, tagqng_able;
8096 ushort ppr_able = 0;
8097 uchar tid, max_cmd[ADV_MAX_TID + 1];
8098 AdvPortAddr iop_base;
8099 ushort bios_sig;
8100
8101 iop_base = asc_dvc->iop_base;
8102
8103 /*
8104 * Save current per TID negotiated values.
8105 */
8106 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8107 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8108 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8109 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8110 }
8111 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8112 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8113 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8114 max_cmd[tid]);
8115 }
8116
8117 /*
8118 * Force the AdvInitAsc3550/38C0800Driver() function to
8119 * perform a SCSI Bus Reset by clearing the BIOS signature word.
8120 * The initialization functions assumes a SCSI Bus Reset is not
8121 * needed if the BIOS signature word is present.
8122 */
8123 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8124 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
8125
8126 /*
8127 * Stop chip and reset it.
8128 */
8129 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
8130 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
8131 mdelay(100);
8132 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
8133 ADV_CTRL_REG_CMD_WR_IO_REG);
8134
8135 /*
8136 * Reset Adv Library error code, if any, and try
8137 * re-initializing the chip.
8138 */
8139 asc_dvc->err_code = 0;
8140 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8141 status = AdvInitAsc38C1600Driver(asc_dvc);
8142 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8143 status = AdvInitAsc38C0800Driver(asc_dvc);
8144 } else {
8145 status = AdvInitAsc3550Driver(asc_dvc);
8146 }
8147
8148 /* Translate initialization return value to status value. */
8149 if (status == 0) {
8150 status = ADV_TRUE;
8151 } else {
8152 status = ADV_FALSE;
8153 }
8154
8155 /*
8156 * Restore the BIOS signature word.
8157 */
8158 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8159
8160 /*
8161 * Restore per TID negotiated values.
8162 */
8163 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8164 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8165 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8166 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8167 }
8168 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8169 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8170 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8171 max_cmd[tid]);
8172 }
8173
8174 return status;
8175}
8176
8177/*
8178 * adv_async_callback() - Adv Library asynchronous event callback function.
8179 */
8180static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
8181{
8182 switch (code) {
8183 case ADV_ASYNC_SCSI_BUS_RESET_DET:
8184 /*
8185 * The firmware detected a SCSI Bus reset.
8186 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008187 ASC_DBG(0, "ADV_ASYNC_SCSI_BUS_RESET_DET\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008188 break;
8189
8190 case ADV_ASYNC_RDMA_FAILURE:
8191 /*
8192 * Handle RDMA failure by resetting the SCSI Bus and
8193 * possibly the chip if it is unresponsive. Log the error
8194 * with a unique code.
8195 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008196 ASC_DBG(0, "ADV_ASYNC_RDMA_FAILURE\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008197 AdvResetChipAndSB(adv_dvc_varp);
8198 break;
8199
8200 case ADV_HOST_SCSI_BUS_RESET:
8201 /*
8202 * Host generated SCSI bus reset occurred.
8203 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008204 ASC_DBG(0, "ADV_HOST_SCSI_BUS_RESET\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008205 break;
8206
8207 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008208 ASC_DBG(0, "unknown code 0x%x\n", code);
Matthew Wilcox51219352007-10-02 21:55:22 -04008209 break;
8210 }
8211}
8212
8213/*
8214 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
8215 *
8216 * Callback function for the Wide SCSI Adv Library.
8217 */
8218static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
8219{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008220 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04008221 adv_req_t *reqp;
8222 adv_sgblk_t *sgblkp;
8223 struct scsi_cmnd *scp;
8224 struct Scsi_Host *shost;
8225 ADV_DCNT resid_cnt;
8226
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008227 ASC_DBG(1, "adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04008228 (ulong)adv_dvc_varp, (ulong)scsiqp);
8229 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
8230
8231 /*
8232 * Get the adv_req_t structure for the command that has been
8233 * completed. The adv_req_t structure actually contains the
8234 * completed ADV_SCSI_REQ_Q structure.
8235 */
8236 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008237 ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp);
Matthew Wilcox51219352007-10-02 21:55:22 -04008238 if (reqp == NULL) {
8239 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
8240 return;
8241 }
8242
8243 /*
8244 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
8245 * command that has been completed.
8246 *
8247 * Note: The adv_req_t request structure and adv_sgblk_t structure,
8248 * if any, are dropped, because a board structure pointer can not be
8249 * determined.
8250 */
8251 scp = reqp->cmndp;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008252 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04008253 if (scp == NULL) {
8254 ASC_PRINT
8255 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
8256 return;
8257 }
8258 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
8259
8260 shost = scp->device->host;
8261 ASC_STATS(shost, callback);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008262 ASC_DBG(1, "shost 0x%p\n", shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04008263
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008264 boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04008265 BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
8266
8267 /*
8268 * 'done_status' contains the command's ending status.
8269 */
8270 switch (scsiqp->done_status) {
8271 case QD_NO_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008272 ASC_DBG(2, "QD_NO_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008273 scp->result = 0;
8274
8275 /*
8276 * Check for an underrun condition.
8277 *
8278 * If there was no error and an underrun condition, then
8279 * then return the number of underrun bytes.
8280 */
8281 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
8282 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
8283 resid_cnt <= scp->request_bufflen) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008284 ASC_DBG(1, "underrun condition %lu bytes\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04008285 (ulong)resid_cnt);
8286 scp->resid = resid_cnt;
8287 }
8288 break;
8289
8290 case QD_WITH_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008291 ASC_DBG(2, "QD_WITH_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008292 switch (scsiqp->host_status) {
8293 case QHSTA_NO_ERROR:
8294 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008295 ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008296 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
8297 sizeof(scp->sense_buffer));
8298 /*
8299 * Note: The 'status_byte()' macro used by
8300 * target drivers defined in scsi.h shifts the
8301 * status byte returned by host drivers right
8302 * by 1 bit. This is why target drivers also
8303 * use right shifted status byte definitions.
8304 * For instance target drivers use
8305 * CHECK_CONDITION, defined to 0x1, instead of
8306 * the SCSI defined check condition value of
8307 * 0x2. Host drivers are supposed to return
8308 * the status byte as it is defined by SCSI.
8309 */
8310 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
8311 STATUS_BYTE(scsiqp->scsi_status);
8312 } else {
8313 scp->result = STATUS_BYTE(scsiqp->scsi_status);
8314 }
8315 break;
8316
8317 default:
8318 /* Some other QHSTA error occurred. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008319 ASC_DBG(1, "host_status 0x%x\n", scsiqp->host_status);
Matthew Wilcox51219352007-10-02 21:55:22 -04008320 scp->result = HOST_BYTE(DID_BAD_TARGET);
8321 break;
8322 }
8323 break;
8324
8325 case QD_ABORTED_BY_HOST:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008326 ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008327 scp->result =
8328 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
8329 break;
8330
8331 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008332 ASC_DBG(1, "done_status 0x%x\n", scsiqp->done_status);
Matthew Wilcox51219352007-10-02 21:55:22 -04008333 scp->result =
8334 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
8335 break;
8336 }
8337
8338 /*
8339 * If the 'init_tidmask' bit isn't already set for the target and the
8340 * current request finished normally, then set the bit for the target
8341 * to indicate that a device is present.
8342 */
8343 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
8344 scsiqp->done_status == QD_NO_ERROR &&
8345 scsiqp->host_status == QHSTA_NO_ERROR) {
8346 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
8347 }
8348
8349 asc_scsi_done(scp);
8350
8351 /*
8352 * Free all 'adv_sgblk_t' structures allocated for the request.
8353 */
8354 while ((sgblkp = reqp->sgblkp) != NULL) {
8355 /* Remove 'sgblkp' from the request list. */
8356 reqp->sgblkp = sgblkp->next_sgblkp;
8357
8358 /* Add 'sgblkp' to the board free list. */
8359 sgblkp->next_sgblkp = boardp->adv_sgblkp;
8360 boardp->adv_sgblkp = sgblkp;
8361 }
8362
8363 /*
8364 * Free the adv_req_t structure used with the command by adding
8365 * it back to the board free list.
8366 */
8367 reqp->next_reqp = boardp->adv_reqp;
8368 boardp->adv_reqp = reqp;
8369
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008370 ASC_DBG(1, "done\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008371}
8372
8373/*
8374 * Adv Library Interrupt Service Routine
8375 *
8376 * This function is called by a driver's interrupt service routine.
8377 * The function disables and re-enables interrupts.
8378 *
8379 * When a microcode idle command is completed, the ADV_DVC_VAR
8380 * 'idle_cmd_done' field is set to ADV_TRUE.
8381 *
8382 * Note: AdvISR() can be called when interrupts are disabled or even
8383 * when there is no hardware interrupt condition present. It will
8384 * always check for completed idle commands and microcode requests.
8385 * This is an important feature that shouldn't be changed because it
8386 * allows commands to be completed from polling mode loops.
8387 *
8388 * Return:
8389 * ADV_TRUE(1) - interrupt was pending
8390 * ADV_FALSE(0) - no interrupt was pending
8391 */
8392static int AdvISR(ADV_DVC_VAR *asc_dvc)
8393{
8394 AdvPortAddr iop_base;
8395 uchar int_stat;
8396 ushort target_bit;
8397 ADV_CARR_T *free_carrp;
8398 ADV_VADDR irq_next_vpa;
8399 ADV_SCSI_REQ_Q *scsiq;
8400
8401 iop_base = asc_dvc->iop_base;
8402
8403 /* Reading the register clears the interrupt. */
8404 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
8405
8406 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
8407 ADV_INTR_STATUS_INTRC)) == 0) {
8408 return ADV_FALSE;
8409 }
8410
8411 /*
8412 * Notify the driver of an asynchronous microcode condition by
8413 * calling the adv_async_callback function. The function
8414 * is passed the microcode ASC_MC_INTRB_CODE byte value.
8415 */
8416 if (int_stat & ADV_INTR_STATUS_INTRB) {
8417 uchar intrb_code;
8418
8419 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
8420
8421 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
8422 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8423 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
8424 asc_dvc->carr_pending_cnt != 0) {
8425 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
8426 ADV_TICKLE_A);
8427 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
8428 AdvWriteByteRegister(iop_base,
8429 IOPB_TICKLE,
8430 ADV_TICKLE_NOP);
8431 }
8432 }
8433 }
8434
8435 adv_async_callback(asc_dvc, intrb_code);
8436 }
8437
8438 /*
8439 * Check if the IRQ stopper carrier contains a completed request.
8440 */
8441 while (((irq_next_vpa =
8442 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
8443 /*
8444 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
8445 * The RISC will have set 'areq_vpa' to a virtual address.
8446 *
8447 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
8448 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
8449 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
8450 * in AdvExeScsiQueue().
8451 */
8452 scsiq = (ADV_SCSI_REQ_Q *)
8453 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
8454
8455 /*
8456 * Request finished with good status and the queue was not
8457 * DMAed to host memory by the firmware. Set all status fields
8458 * to indicate good status.
8459 */
8460 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
8461 scsiq->done_status = QD_NO_ERROR;
8462 scsiq->host_status = scsiq->scsi_status = 0;
8463 scsiq->data_cnt = 0L;
8464 }
8465
8466 /*
8467 * Advance the stopper pointer to the next carrier
8468 * ignoring the lower four bits. Free the previous
8469 * stopper carrier.
8470 */
8471 free_carrp = asc_dvc->irq_sp;
8472 asc_dvc->irq_sp = (ADV_CARR_T *)
8473 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
8474
8475 free_carrp->next_vpa =
8476 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
8477 asc_dvc->carr_freelist = free_carrp;
8478 asc_dvc->carr_pending_cnt--;
8479
8480 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
8481
8482 /*
8483 * Clear request microcode control flag.
8484 */
8485 scsiq->cntl = 0;
8486
8487 /*
8488 * Notify the driver of the completed request by passing
8489 * the ADV_SCSI_REQ_Q pointer to its callback function.
8490 */
8491 scsiq->a_flag |= ADV_SCSIQ_DONE;
8492 adv_isr_callback(asc_dvc, scsiq);
8493 /*
8494 * Note: After the driver callback function is called, 'scsiq'
8495 * can no longer be referenced.
8496 *
8497 * Fall through and continue processing other completed
8498 * requests...
8499 */
8500 }
8501 return ADV_TRUE;
8502}
8503
8504static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
8505{
8506 if (asc_dvc->err_code == 0) {
8507 asc_dvc->err_code = err_code;
8508 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8509 err_code);
8510 }
8511 return err_code;
8512}
8513
8514static void AscAckInterrupt(PortAddr iop_base)
8515{
8516 uchar host_flag;
8517 uchar risc_flag;
8518 ushort loop;
8519
8520 loop = 0;
8521 do {
8522 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8523 if (loop++ > 0x7FFF) {
8524 break;
8525 }
8526 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8527 host_flag =
8528 AscReadLramByte(iop_base,
8529 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8530 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8531 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8532 AscSetChipStatus(iop_base, CIW_INT_ACK);
8533 loop = 0;
8534 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8535 AscSetChipStatus(iop_base, CIW_INT_ACK);
8536 if (loop++ > 3) {
8537 break;
8538 }
8539 }
8540 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
Matthew Wilcox51219352007-10-02 21:55:22 -04008541}
8542
8543static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
8544{
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -04008545 const uchar *period_table;
Matthew Wilcox51219352007-10-02 21:55:22 -04008546 int max_index;
8547 int min_index;
8548 int i;
8549
8550 period_table = asc_dvc->sdtr_period_tbl;
8551 max_index = (int)asc_dvc->max_sdtr_index;
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -04008552 min_index = (int)asc_dvc->min_sdtr_index;
Matthew Wilcox51219352007-10-02 21:55:22 -04008553 if ((syn_time <= period_table[max_index])) {
8554 for (i = min_index; i < (max_index - 1); i++) {
8555 if (syn_time <= period_table[i]) {
8556 return (uchar)i;
8557 }
8558 }
8559 return (uchar)max_index;
8560 } else {
8561 return (uchar)(max_index + 1);
8562 }
8563}
8564
8565static uchar
8566AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
8567{
8568 EXT_MSG sdtr_buf;
8569 uchar sdtr_period_index;
8570 PortAddr iop_base;
8571
8572 iop_base = asc_dvc->iop_base;
8573 sdtr_buf.msg_type = EXTENDED_MESSAGE;
8574 sdtr_buf.msg_len = MS_SDTR_LEN;
8575 sdtr_buf.msg_req = EXTENDED_SDTR;
8576 sdtr_buf.xfer_period = sdtr_period;
8577 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8578 sdtr_buf.req_ack_offset = sdtr_offset;
8579 sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8580 if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
8581 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8582 (uchar *)&sdtr_buf,
8583 sizeof(EXT_MSG) >> 1);
8584 return ((sdtr_period_index << 4) | sdtr_offset);
8585 } else {
8586 sdtr_buf.req_ack_offset = 0;
8587 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8588 (uchar *)&sdtr_buf,
8589 sizeof(EXT_MSG) >> 1);
8590 return 0;
8591 }
8592}
8593
8594static uchar
8595AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
8596{
8597 uchar byte;
8598 uchar sdtr_period_ix;
8599
8600 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -04008601 if (sdtr_period_ix > asc_dvc->max_sdtr_index)
Matthew Wilcox51219352007-10-02 21:55:22 -04008602 return 0xFF;
Matthew Wilcox51219352007-10-02 21:55:22 -04008603 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8604 return byte;
8605}
8606
8607static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
8608{
8609 ASC_SCSI_BIT_ID_TYPE org_id;
8610 int i;
8611 int sta = TRUE;
8612
8613 AscSetBank(iop_base, 1);
8614 org_id = AscReadChipDvcID(iop_base);
8615 for (i = 0; i <= ASC_MAX_TID; i++) {
8616 if (org_id == (0x01 << i))
8617 break;
8618 }
8619 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8620 AscWriteChipDvcID(iop_base, id);
8621 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8622 AscSetBank(iop_base, 0);
8623 AscSetChipSyn(iop_base, sdtr_data);
8624 if (AscGetChipSyn(iop_base) != sdtr_data) {
8625 sta = FALSE;
8626 }
8627 } else {
8628 sta = FALSE;
8629 }
8630 AscSetBank(iop_base, 1);
8631 AscWriteChipDvcID(iop_base, org_id);
8632 AscSetBank(iop_base, 0);
8633 return (sta);
8634}
8635
8636static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
8637{
8638 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8639 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8640}
8641
8642static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
8643{
8644 EXT_MSG ext_msg;
8645 EXT_MSG out_msg;
8646 ushort halt_q_addr;
8647 int sdtr_accept;
8648 ushort int_halt_code;
8649 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8650 ASC_SCSI_BIT_ID_TYPE target_id;
8651 PortAddr iop_base;
8652 uchar tag_code;
8653 uchar q_status;
8654 uchar halt_qp;
8655 uchar sdtr_data;
8656 uchar target_ix;
8657 uchar q_cntl, tid_no;
8658 uchar cur_dvc_qng;
8659 uchar asyn_sdtr;
8660 uchar scsi_status;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008661 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04008662
8663 BUG_ON(!asc_dvc->drv_ptr);
8664 boardp = asc_dvc->drv_ptr;
8665
8666 iop_base = asc_dvc->iop_base;
8667 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
8668
8669 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8670 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8671 target_ix = AscReadLramByte(iop_base,
8672 (ushort)(halt_q_addr +
8673 (ushort)ASC_SCSIQ_B_TARGET_IX));
8674 q_cntl = AscReadLramByte(iop_base,
8675 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8676 tid_no = ASC_TIX_TO_TID(target_ix);
8677 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8678 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8679 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8680 } else {
8681 asyn_sdtr = 0;
8682 }
8683 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8684 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8685 AscSetChipSDTR(iop_base, 0, tid_no);
8686 boardp->sdtr_data[tid_no] = 0;
8687 }
8688 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8689 return (0);
8690 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8691 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8692 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8693 boardp->sdtr_data[tid_no] = asyn_sdtr;
8694 }
8695 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8696 return (0);
8697 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
8698 AscMemWordCopyPtrFromLram(iop_base,
8699 ASCV_MSGIN_BEG,
8700 (uchar *)&ext_msg,
8701 sizeof(EXT_MSG) >> 1);
8702
8703 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8704 ext_msg.msg_req == EXTENDED_SDTR &&
8705 ext_msg.msg_len == MS_SDTR_LEN) {
8706 sdtr_accept = TRUE;
8707 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
8708
8709 sdtr_accept = FALSE;
8710 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8711 }
8712 if ((ext_msg.xfer_period <
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -04008713 asc_dvc->sdtr_period_tbl[asc_dvc->min_sdtr_index])
Matthew Wilcox51219352007-10-02 21:55:22 -04008714 || (ext_msg.xfer_period >
8715 asc_dvc->sdtr_period_tbl[asc_dvc->
8716 max_sdtr_index])) {
8717 sdtr_accept = FALSE;
8718 ext_msg.xfer_period =
8719 asc_dvc->sdtr_period_tbl[asc_dvc->
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -04008720 min_sdtr_index];
Matthew Wilcox51219352007-10-02 21:55:22 -04008721 }
8722 if (sdtr_accept) {
8723 sdtr_data =
8724 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8725 ext_msg.req_ack_offset);
8726 if ((sdtr_data == 0xFF)) {
8727
8728 q_cntl |= QC_MSG_OUT;
8729 asc_dvc->init_sdtr &= ~target_id;
8730 asc_dvc->sdtr_done &= ~target_id;
8731 AscSetChipSDTR(iop_base, asyn_sdtr,
8732 tid_no);
8733 boardp->sdtr_data[tid_no] = asyn_sdtr;
8734 }
8735 }
8736 if (ext_msg.req_ack_offset == 0) {
8737
8738 q_cntl &= ~QC_MSG_OUT;
8739 asc_dvc->init_sdtr &= ~target_id;
8740 asc_dvc->sdtr_done &= ~target_id;
8741 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8742 } else {
8743 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04008744 q_cntl &= ~QC_MSG_OUT;
8745 asc_dvc->sdtr_done |= target_id;
8746 asc_dvc->init_sdtr |= target_id;
8747 asc_dvc->pci_fix_asyn_xfer &=
8748 ~target_id;
8749 sdtr_data =
8750 AscCalSDTRData(asc_dvc,
8751 ext_msg.xfer_period,
8752 ext_msg.
8753 req_ack_offset);
8754 AscSetChipSDTR(iop_base, sdtr_data,
8755 tid_no);
8756 boardp->sdtr_data[tid_no] = sdtr_data;
8757 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04008758 q_cntl |= QC_MSG_OUT;
8759 AscMsgOutSDTR(asc_dvc,
8760 ext_msg.xfer_period,
8761 ext_msg.req_ack_offset);
8762 asc_dvc->pci_fix_asyn_xfer &=
8763 ~target_id;
8764 sdtr_data =
8765 AscCalSDTRData(asc_dvc,
8766 ext_msg.xfer_period,
8767 ext_msg.
8768 req_ack_offset);
8769 AscSetChipSDTR(iop_base, sdtr_data,
8770 tid_no);
8771 boardp->sdtr_data[tid_no] = sdtr_data;
8772 asc_dvc->sdtr_done |= target_id;
8773 asc_dvc->init_sdtr |= target_id;
8774 }
8775 }
8776
8777 AscWriteLramByte(iop_base,
8778 (ushort)(halt_q_addr +
8779 (ushort)ASC_SCSIQ_B_CNTL),
8780 q_cntl);
8781 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8782 return (0);
8783 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8784 ext_msg.msg_req == EXTENDED_WDTR &&
8785 ext_msg.msg_len == MS_WDTR_LEN) {
8786
8787 ext_msg.wdtr_width = 0;
8788 AscMemWordCopyPtrToLram(iop_base,
8789 ASCV_MSGOUT_BEG,
8790 (uchar *)&ext_msg,
8791 sizeof(EXT_MSG) >> 1);
8792 q_cntl |= QC_MSG_OUT;
8793 AscWriteLramByte(iop_base,
8794 (ushort)(halt_q_addr +
8795 (ushort)ASC_SCSIQ_B_CNTL),
8796 q_cntl);
8797 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8798 return (0);
8799 } else {
8800
8801 ext_msg.msg_type = MESSAGE_REJECT;
8802 AscMemWordCopyPtrToLram(iop_base,
8803 ASCV_MSGOUT_BEG,
8804 (uchar *)&ext_msg,
8805 sizeof(EXT_MSG) >> 1);
8806 q_cntl |= QC_MSG_OUT;
8807 AscWriteLramByte(iop_base,
8808 (ushort)(halt_q_addr +
8809 (ushort)ASC_SCSIQ_B_CNTL),
8810 q_cntl);
8811 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8812 return (0);
8813 }
8814 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
8815
8816 q_cntl |= QC_REQ_SENSE;
8817
8818 if ((asc_dvc->init_sdtr & target_id) != 0) {
8819
8820 asc_dvc->sdtr_done &= ~target_id;
8821
8822 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8823 q_cntl |= QC_MSG_OUT;
8824 AscMsgOutSDTR(asc_dvc,
8825 asc_dvc->
8826 sdtr_period_tbl[(sdtr_data >> 4) &
8827 (uchar)(asc_dvc->
8828 max_sdtr_index -
8829 1)],
8830 (uchar)(sdtr_data & (uchar)
8831 ASC_SYN_MAX_OFFSET));
8832 }
8833
8834 AscWriteLramByte(iop_base,
8835 (ushort)(halt_q_addr +
8836 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8837
8838 tag_code = AscReadLramByte(iop_base,
8839 (ushort)(halt_q_addr + (ushort)
8840 ASC_SCSIQ_B_TAG_CODE));
8841 tag_code &= 0xDC;
8842 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
8843 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
8844 ) {
8845
8846 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
8847 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
8848
8849 }
8850 AscWriteLramByte(iop_base,
8851 (ushort)(halt_q_addr +
8852 (ushort)ASC_SCSIQ_B_TAG_CODE),
8853 tag_code);
8854
8855 q_status = AscReadLramByte(iop_base,
8856 (ushort)(halt_q_addr + (ushort)
8857 ASC_SCSIQ_B_STATUS));
8858 q_status |= (QS_READY | QS_BUSY);
8859 AscWriteLramByte(iop_base,
8860 (ushort)(halt_q_addr +
8861 (ushort)ASC_SCSIQ_B_STATUS),
8862 q_status);
8863
8864 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
8865 scsi_busy &= ~target_id;
8866 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8867
8868 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8869 return (0);
8870 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
8871
8872 AscMemWordCopyPtrFromLram(iop_base,
8873 ASCV_MSGOUT_BEG,
8874 (uchar *)&out_msg,
8875 sizeof(EXT_MSG) >> 1);
8876
8877 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
8878 (out_msg.msg_len == MS_SDTR_LEN) &&
8879 (out_msg.msg_req == EXTENDED_SDTR)) {
8880
8881 asc_dvc->init_sdtr &= ~target_id;
8882 asc_dvc->sdtr_done &= ~target_id;
8883 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8884 boardp->sdtr_data[tid_no] = asyn_sdtr;
8885 }
8886 q_cntl &= ~QC_MSG_OUT;
8887 AscWriteLramByte(iop_base,
8888 (ushort)(halt_q_addr +
8889 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8890 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8891 return (0);
8892 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
8893
8894 scsi_status = AscReadLramByte(iop_base,
8895 (ushort)((ushort)halt_q_addr +
8896 (ushort)
8897 ASC_SCSIQ_SCSI_STATUS));
8898 cur_dvc_qng =
8899 AscReadLramByte(iop_base,
8900 (ushort)((ushort)ASC_QADR_BEG +
8901 (ushort)target_ix));
8902 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
8903
8904 scsi_busy = AscReadLramByte(iop_base,
8905 (ushort)ASCV_SCSIBUSY_B);
8906 scsi_busy |= target_id;
8907 AscWriteLramByte(iop_base,
8908 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8909 asc_dvc->queue_full_or_busy |= target_id;
8910
8911 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
8912 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
8913 cur_dvc_qng -= 1;
8914 asc_dvc->max_dvc_qng[tid_no] =
8915 cur_dvc_qng;
8916
8917 AscWriteLramByte(iop_base,
8918 (ushort)((ushort)
8919 ASCV_MAX_DVC_QNG_BEG
8920 + (ushort)
8921 tid_no),
8922 cur_dvc_qng);
8923
8924 /*
8925 * Set the device queue depth to the
8926 * number of active requests when the
8927 * QUEUE FULL condition was encountered.
8928 */
8929 boardp->queue_full |= target_id;
8930 boardp->queue_full_cnt[tid_no] =
8931 cur_dvc_qng;
8932 }
8933 }
8934 }
8935 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8936 return (0);
8937 }
8938#if CC_VERY_LONG_SG_LIST
8939 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
8940 uchar q_no;
8941 ushort q_addr;
8942 uchar sg_wk_q_no;
8943 uchar first_sg_wk_q_no;
8944 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
8945 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
8946 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
8947 ushort sg_list_dwords;
8948 ushort sg_entry_cnt;
8949 uchar next_qp;
8950 int i;
8951
8952 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
8953 if (q_no == ASC_QLINK_END)
8954 return 0;
8955
8956 q_addr = ASC_QNO_TO_QADDR(q_no);
8957
8958 /*
8959 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
8960 * structure pointer using a macro provided by the driver.
8961 * The ASC_SCSI_REQ pointer provides a pointer to the
8962 * host ASC_SG_HEAD structure.
8963 */
8964 /* Read request's SRB pointer. */
8965 scsiq = (ASC_SCSI_Q *)
8966 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
8967 (ushort)
8968 (q_addr +
8969 ASC_SCSIQ_D_SRBPTR))));
8970
8971 /*
8972 * Get request's first and working SG queue.
8973 */
8974 sg_wk_q_no = AscReadLramByte(iop_base,
8975 (ushort)(q_addr +
8976 ASC_SCSIQ_B_SG_WK_QP));
8977
8978 first_sg_wk_q_no = AscReadLramByte(iop_base,
8979 (ushort)(q_addr +
8980 ASC_SCSIQ_B_FIRST_SG_WK_QP));
8981
8982 /*
8983 * Reset request's working SG queue back to the
8984 * first SG queue.
8985 */
8986 AscWriteLramByte(iop_base,
8987 (ushort)(q_addr +
8988 (ushort)ASC_SCSIQ_B_SG_WK_QP),
8989 first_sg_wk_q_no);
8990
8991 sg_head = scsiq->sg_head;
8992
8993 /*
8994 * Set sg_entry_cnt to the number of SG elements
8995 * that will be completed on this interrupt.
8996 *
8997 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
8998 * SG elements. The data_cnt and data_addr fields which
8999 * add 1 to the SG element capacity are not used when
9000 * restarting SG handling after a halt.
9001 */
9002 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
9003 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
9004
9005 /*
9006 * Keep track of remaining number of SG elements that
9007 * will need to be handled on the next interrupt.
9008 */
9009 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
9010 } else {
9011 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
9012 scsiq->remain_sg_entry_cnt = 0;
9013 }
9014
9015 /*
9016 * Copy SG elements into the list of allocated SG queues.
9017 *
9018 * Last index completed is saved in scsiq->next_sg_index.
9019 */
9020 next_qp = first_sg_wk_q_no;
9021 q_addr = ASC_QNO_TO_QADDR(next_qp);
9022 scsi_sg_q.sg_head_qp = q_no;
9023 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9024 for (i = 0; i < sg_head->queue_cnt; i++) {
9025 scsi_sg_q.seq_no = i + 1;
9026 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9027 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9028 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9029 /*
9030 * After very first SG queue RISC FW uses next
9031 * SG queue first element then checks sg_list_cnt
9032 * against zero and then decrements, so set
9033 * sg_list_cnt 1 less than number of SG elements
9034 * in each SG queue.
9035 */
9036 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
9037 scsi_sg_q.sg_cur_list_cnt =
9038 ASC_SG_LIST_PER_Q - 1;
9039 } else {
9040 /*
9041 * This is the last SG queue in the list of
9042 * allocated SG queues. If there are more
9043 * SG elements than will fit in the allocated
9044 * queues, then set the QCSG_SG_XFER_MORE flag.
9045 */
9046 if (scsiq->remain_sg_entry_cnt != 0) {
9047 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9048 } else {
9049 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
9050 }
9051 /* equals sg_entry_cnt * 2 */
9052 sg_list_dwords = sg_entry_cnt << 1;
9053 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
9054 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
9055 sg_entry_cnt = 0;
9056 }
9057
9058 scsi_sg_q.q_no = next_qp;
9059 AscMemWordCopyPtrToLram(iop_base,
9060 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9061 (uchar *)&scsi_sg_q,
9062 sizeof(ASC_SG_LIST_Q) >> 1);
9063
9064 AscMemDWordCopyPtrToLram(iop_base,
9065 q_addr + ASC_SGQ_LIST_BEG,
9066 (uchar *)&sg_head->
9067 sg_list[scsiq->next_sg_index],
9068 sg_list_dwords);
9069
9070 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
9071
9072 /*
9073 * If the just completed SG queue contained the
9074 * last SG element, then no more SG queues need
9075 * to be written.
9076 */
9077 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
9078 break;
9079 }
9080
9081 next_qp = AscReadLramByte(iop_base,
9082 (ushort)(q_addr +
9083 ASC_SCSIQ_B_FWD));
9084 q_addr = ASC_QNO_TO_QADDR(next_qp);
9085 }
9086
9087 /*
9088 * Clear the halt condition so the RISC will be restarted
9089 * after the return.
9090 */
9091 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9092 return (0);
9093 }
9094#endif /* CC_VERY_LONG_SG_LIST */
9095 return (0);
9096}
9097
9098/*
9099 * void
9100 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9101 *
9102 * Calling/Exit State:
9103 * none
9104 *
9105 * Description:
9106 * Input an ASC_QDONE_INFO structure from the chip
9107 */
9108static void
9109DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9110{
9111 int i;
9112 ushort word;
9113
9114 AscSetChipLramAddr(iop_base, s_addr);
9115 for (i = 0; i < 2 * words; i += 2) {
9116 if (i == 10) {
9117 continue;
9118 }
9119 word = inpw(iop_base + IOP_RAM_DATA);
9120 inbuf[i] = word & 0xff;
9121 inbuf[i + 1] = (word >> 8) & 0xff;
9122 }
9123 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
9124}
9125
9126static uchar
9127_AscCopyLramScsiDoneQ(PortAddr iop_base,
9128 ushort q_addr,
9129 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
9130{
9131 ushort _val;
9132 uchar sg_queue_cnt;
9133
9134 DvcGetQinfo(iop_base,
9135 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
9136 (uchar *)scsiq,
9137 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
9138
9139 _val = AscReadLramWord(iop_base,
9140 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
9141 scsiq->q_status = (uchar)_val;
9142 scsiq->q_no = (uchar)(_val >> 8);
9143 _val = AscReadLramWord(iop_base,
9144 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
9145 scsiq->cntl = (uchar)_val;
9146 sg_queue_cnt = (uchar)(_val >> 8);
9147 _val = AscReadLramWord(iop_base,
9148 (ushort)(q_addr +
9149 (ushort)ASC_SCSIQ_B_SENSE_LEN));
9150 scsiq->sense_len = (uchar)_val;
9151 scsiq->extra_bytes = (uchar)(_val >> 8);
9152
9153 /*
9154 * Read high word of remain bytes from alternate location.
9155 */
9156 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
9157 (ushort)(q_addr +
9158 (ushort)
9159 ASC_SCSIQ_W_ALT_DC1)))
9160 << 16);
9161 /*
9162 * Read low word of remain bytes from original location.
9163 */
9164 scsiq->remain_bytes += AscReadLramWord(iop_base,
9165 (ushort)(q_addr + (ushort)
9166 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
9167
9168 scsiq->remain_bytes &= max_dma_count;
9169 return sg_queue_cnt;
9170}
9171
9172/*
9173 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
9174 *
9175 * Interrupt callback function for the Narrow SCSI Asc Library.
9176 */
9177static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9178{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009179 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04009180 struct scsi_cmnd *scp;
9181 struct Scsi_Host *shost;
9182
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009183 ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
Matthew Wilcox51219352007-10-02 21:55:22 -04009184 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
9185
9186 /*
9187 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
9188 * command that has been completed.
9189 */
9190 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009191 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009192
9193 if (scp == NULL) {
9194 ASC_PRINT("asc_isr_callback: scp is NULL\n");
9195 return;
9196 }
9197 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
9198
9199 shost = scp->device->host;
9200 ASC_STATS(shost, callback);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009201 ASC_DBG(1, "shost 0x%p\n", shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009202
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009203 boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009204 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
9205
9206 /*
9207 * 'qdonep' contains the command's ending status.
9208 */
9209 switch (qdonep->d3.done_stat) {
9210 case QD_NO_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009211 ASC_DBG(2, "QD_NO_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009212 scp->result = 0;
9213
9214 /*
9215 * Check for an underrun condition.
9216 *
9217 * If there was no error and an underrun condition, then
9218 * return the number of underrun bytes.
9219 */
9220 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
9221 qdonep->remain_bytes <= scp->request_bufflen) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009222 ASC_DBG(1, "underrun condition %u bytes\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04009223 (unsigned)qdonep->remain_bytes);
9224 scp->resid = qdonep->remain_bytes;
9225 }
9226 break;
9227
9228 case QD_WITH_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009229 ASC_DBG(2, "QD_WITH_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009230 switch (qdonep->d3.host_stat) {
9231 case QHSTA_NO_ERROR:
9232 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009233 ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009234 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
9235 sizeof(scp->sense_buffer));
9236 /*
9237 * Note: The 'status_byte()' macro used by
9238 * target drivers defined in scsi.h shifts the
9239 * status byte returned by host drivers right
9240 * by 1 bit. This is why target drivers also
9241 * use right shifted status byte definitions.
9242 * For instance target drivers use
9243 * CHECK_CONDITION, defined to 0x1, instead of
9244 * the SCSI defined check condition value of
9245 * 0x2. Host drivers are supposed to return
9246 * the status byte as it is defined by SCSI.
9247 */
9248 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
9249 STATUS_BYTE(qdonep->d3.scsi_stat);
9250 } else {
9251 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
9252 }
9253 break;
9254
9255 default:
9256 /* QHSTA error occurred */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009257 ASC_DBG(1, "host_stat 0x%x\n", qdonep->d3.host_stat);
Matthew Wilcox51219352007-10-02 21:55:22 -04009258 scp->result = HOST_BYTE(DID_BAD_TARGET);
9259 break;
9260 }
9261 break;
9262
9263 case QD_ABORTED_BY_HOST:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009264 ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009265 scp->result =
9266 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
9267 scsi_msg) |
9268 STATUS_BYTE(qdonep->d3.scsi_stat);
9269 break;
9270
9271 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009272 ASC_DBG(1, "done_stat 0x%x\n", qdonep->d3.done_stat);
Matthew Wilcox51219352007-10-02 21:55:22 -04009273 scp->result =
9274 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
9275 scsi_msg) |
9276 STATUS_BYTE(qdonep->d3.scsi_stat);
9277 break;
9278 }
9279
9280 /*
9281 * If the 'init_tidmask' bit isn't already set for the target and the
9282 * current request finished normally, then set the bit for the target
9283 * to indicate that a device is present.
9284 */
9285 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
9286 qdonep->d3.done_stat == QD_NO_ERROR &&
9287 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
9288 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
9289 }
9290
9291 asc_scsi_done(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009292}
9293
9294static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
9295{
9296 uchar next_qp;
9297 uchar n_q_used;
9298 uchar sg_list_qp;
9299 uchar sg_queue_cnt;
9300 uchar q_cnt;
9301 uchar done_q_tail;
9302 uchar tid_no;
9303 ASC_SCSI_BIT_ID_TYPE scsi_busy;
9304 ASC_SCSI_BIT_ID_TYPE target_id;
9305 PortAddr iop_base;
9306 ushort q_addr;
9307 ushort sg_q_addr;
9308 uchar cur_target_qng;
9309 ASC_QDONE_INFO scsiq_buf;
9310 ASC_QDONE_INFO *scsiq;
9311 int false_overrun;
9312
9313 iop_base = asc_dvc->iop_base;
9314 n_q_used = 1;
9315 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
9316 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
9317 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
9318 next_qp = AscReadLramByte(iop_base,
9319 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
9320 if (next_qp != ASC_QLINK_END) {
9321 AscPutVarDoneQTail(iop_base, next_qp);
9322 q_addr = ASC_QNO_TO_QADDR(next_qp);
9323 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
9324 asc_dvc->max_dma_count);
9325 AscWriteLramByte(iop_base,
9326 (ushort)(q_addr +
9327 (ushort)ASC_SCSIQ_B_STATUS),
9328 (uchar)(scsiq->
9329 q_status & (uchar)~(QS_READY |
9330 QS_ABORTED)));
9331 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
9332 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
9333 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
9334 sg_q_addr = q_addr;
9335 sg_list_qp = next_qp;
9336 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
9337 sg_list_qp = AscReadLramByte(iop_base,
9338 (ushort)(sg_q_addr
9339 + (ushort)
9340 ASC_SCSIQ_B_FWD));
9341 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
9342 if (sg_list_qp == ASC_QLINK_END) {
9343 AscSetLibErrorCode(asc_dvc,
9344 ASCQ_ERR_SG_Q_LINKS);
9345 scsiq->d3.done_stat = QD_WITH_ERROR;
9346 scsiq->d3.host_stat =
9347 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
9348 goto FATAL_ERR_QDONE;
9349 }
9350 AscWriteLramByte(iop_base,
9351 (ushort)(sg_q_addr + (ushort)
9352 ASC_SCSIQ_B_STATUS),
9353 QS_FREE);
9354 }
9355 n_q_used = sg_queue_cnt + 1;
9356 AscPutVarDoneQTail(iop_base, sg_list_qp);
9357 }
9358 if (asc_dvc->queue_full_or_busy & target_id) {
9359 cur_target_qng = AscReadLramByte(iop_base,
9360 (ushort)((ushort)
9361 ASC_QADR_BEG
9362 + (ushort)
9363 scsiq->d2.
9364 target_ix));
9365 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
9366 scsi_busy = AscReadLramByte(iop_base, (ushort)
9367 ASCV_SCSIBUSY_B);
9368 scsi_busy &= ~target_id;
9369 AscWriteLramByte(iop_base,
9370 (ushort)ASCV_SCSIBUSY_B,
9371 scsi_busy);
9372 asc_dvc->queue_full_or_busy &= ~target_id;
9373 }
9374 }
9375 if (asc_dvc->cur_total_qng >= n_q_used) {
9376 asc_dvc->cur_total_qng -= n_q_used;
9377 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
9378 asc_dvc->cur_dvc_qng[tid_no]--;
9379 }
9380 } else {
9381 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
9382 scsiq->d3.done_stat = QD_WITH_ERROR;
9383 goto FATAL_ERR_QDONE;
9384 }
9385 if ((scsiq->d2.srb_ptr == 0UL) ||
9386 ((scsiq->q_status & QS_ABORTED) != 0)) {
9387 return (0x11);
9388 } else if (scsiq->q_status == QS_DONE) {
9389 false_overrun = FALSE;
9390 if (scsiq->extra_bytes != 0) {
9391 scsiq->remain_bytes +=
9392 (ADV_DCNT)scsiq->extra_bytes;
9393 }
9394 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
9395 if (scsiq->d3.host_stat ==
9396 QHSTA_M_DATA_OVER_RUN) {
9397 if ((scsiq->
9398 cntl & (QC_DATA_IN | QC_DATA_OUT))
9399 == 0) {
9400 scsiq->d3.done_stat =
9401 QD_NO_ERROR;
9402 scsiq->d3.host_stat =
9403 QHSTA_NO_ERROR;
9404 } else if (false_overrun) {
9405 scsiq->d3.done_stat =
9406 QD_NO_ERROR;
9407 scsiq->d3.host_stat =
9408 QHSTA_NO_ERROR;
9409 }
9410 } else if (scsiq->d3.host_stat ==
9411 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
9412 AscStopChip(iop_base);
9413 AscSetChipControl(iop_base,
9414 (uchar)(CC_SCSI_RESET
9415 | CC_HALT));
9416 udelay(60);
9417 AscSetChipControl(iop_base, CC_HALT);
9418 AscSetChipStatus(iop_base,
9419 CIW_CLR_SCSI_RESET_INT);
9420 AscSetChipStatus(iop_base, 0);
9421 AscSetChipControl(iop_base, 0);
9422 }
9423 }
9424 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9425 asc_isr_callback(asc_dvc, scsiq);
9426 } else {
9427 if ((AscReadLramByte(iop_base,
9428 (ushort)(q_addr + (ushort)
9429 ASC_SCSIQ_CDB_BEG))
9430 == START_STOP)) {
9431 asc_dvc->unit_not_ready &= ~target_id;
9432 if (scsiq->d3.done_stat != QD_NO_ERROR) {
9433 asc_dvc->start_motor &=
9434 ~target_id;
9435 }
9436 }
9437 }
9438 return (1);
9439 } else {
9440 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
9441 FATAL_ERR_QDONE:
9442 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9443 asc_isr_callback(asc_dvc, scsiq);
9444 }
9445 return (0x80);
9446 }
9447 }
9448 return (0);
9449}
9450
9451static int AscISR(ASC_DVC_VAR *asc_dvc)
9452{
9453 ASC_CS_TYPE chipstat;
9454 PortAddr iop_base;
9455 ushort saved_ram_addr;
9456 uchar ctrl_reg;
9457 uchar saved_ctrl_reg;
9458 int int_pending;
9459 int status;
9460 uchar host_flag;
9461
9462 iop_base = asc_dvc->iop_base;
9463 int_pending = FALSE;
9464
9465 if (AscIsIntPending(iop_base) == 0)
9466 return int_pending;
9467
9468 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
9469 return ERR;
9470 }
9471 if (asc_dvc->in_critical_cnt != 0) {
9472 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
9473 return ERR;
9474 }
9475 if (asc_dvc->is_in_int) {
9476 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
9477 return ERR;
9478 }
9479 asc_dvc->is_in_int = TRUE;
9480 ctrl_reg = AscGetChipControl(iop_base);
9481 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
9482 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
9483 chipstat = AscGetChipStatus(iop_base);
9484 if (chipstat & CSW_SCSI_RESET_LATCH) {
9485 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
9486 int i = 10;
9487 int_pending = TRUE;
9488 asc_dvc->sdtr_done = 0;
9489 saved_ctrl_reg &= (uchar)(~CC_HALT);
9490 while ((AscGetChipStatus(iop_base) &
9491 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
9492 mdelay(100);
9493 }
9494 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
9495 AscSetChipControl(iop_base, CC_HALT);
9496 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9497 AscSetChipStatus(iop_base, 0);
9498 chipstat = AscGetChipStatus(iop_base);
9499 }
9500 }
9501 saved_ram_addr = AscGetChipLramAddr(iop_base);
9502 host_flag = AscReadLramByte(iop_base,
9503 ASCV_HOST_FLAG_B) &
9504 (uchar)(~ASC_HOST_FLAG_IN_ISR);
9505 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
9506 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
9507 if ((chipstat & CSW_INT_PENDING) || (int_pending)) {
9508 AscAckInterrupt(iop_base);
9509 int_pending = TRUE;
9510 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
9511 if (AscIsrChipHalted(asc_dvc) == ERR) {
9512 goto ISR_REPORT_QDONE_FATAL_ERROR;
9513 } else {
9514 saved_ctrl_reg &= (uchar)(~CC_HALT);
9515 }
9516 } else {
9517 ISR_REPORT_QDONE_FATAL_ERROR:
9518 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
9519 while (((status =
9520 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
9521 }
9522 } else {
9523 do {
9524 if ((status =
9525 AscIsrQDone(asc_dvc)) == 1) {
9526 break;
9527 }
9528 } while (status == 0x11);
9529 }
9530 if ((status & 0x80) != 0)
9531 int_pending = ERR;
9532 }
9533 }
9534 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9535 AscSetChipLramAddr(iop_base, saved_ram_addr);
9536 AscSetChipControl(iop_base, saved_ctrl_reg);
9537 asc_dvc->is_in_int = FALSE;
9538 return int_pending;
9539}
9540
9541/*
9542 * advansys_reset()
9543 *
9544 * Reset the bus associated with the command 'scp'.
9545 *
9546 * This function runs its own thread. Interrupts must be blocked but
9547 * sleeping is allowed and no locking other than for host structures is
9548 * required. Returns SUCCESS or FAILED.
9549 */
9550static int advansys_reset(struct scsi_cmnd *scp)
9551{
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009552 struct Scsi_Host *shost = scp->device->host;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009553 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009554 unsigned long flags;
Matthew Wilcox51219352007-10-02 21:55:22 -04009555 int status;
9556 int ret = SUCCESS;
9557
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009558 ASC_DBG(1, "0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009559
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009560 ASC_STATS(shost, reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04009561
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009562 scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009563
9564 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009565 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009566
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009567 /* Reset the chip and SCSI bus. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009568 ASC_DBG(1, "before AscInitAsc1000Driver()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009569 status = AscInitAsc1000Driver(asc_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009570
9571 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009572 if (asc_dvc->err_code) {
9573 scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
9574 "0x%x\n", asc_dvc->err_code);
Matthew Wilcox51219352007-10-02 21:55:22 -04009575 ret = FAILED;
9576 } else if (status) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009577 scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
9578 "0x%x\n", status);
Matthew Wilcox51219352007-10-02 21:55:22 -04009579 } else {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009580 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9581 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009582 }
9583
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009584 ASC_DBG(1, "after AscInitAsc1000Driver()\n");
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009585 spin_lock_irqsave(shost->host_lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009586 } else {
9587 /*
Matthew Wilcox51219352007-10-02 21:55:22 -04009588 * If the suggest reset bus flags are set, then reset the bus.
9589 * Otherwise only reset the device.
9590 */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009591 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009592
9593 /*
9594 * Reset the target's SCSI bus.
9595 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009596 ASC_DBG(1, "before AdvResetChipAndSB()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009597 switch (AdvResetChipAndSB(adv_dvc)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04009598 case ASC_TRUE:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009599 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9600 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009601 break;
9602 case ASC_FALSE:
9603 default:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009604 scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009605 ret = FAILED;
9606 break;
9607 }
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009608 spin_lock_irqsave(shost->host_lock, flags);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009609 AdvISR(adv_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009610 }
Matthew Wilcox51219352007-10-02 21:55:22 -04009611
9612 /* Save the time of the most recently completed reset. */
9613 boardp->last_reset = jiffies;
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009614 spin_unlock_irqrestore(shost->host_lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009615
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009616 ASC_DBG(1, "ret %d\n", ret);
Matthew Wilcox51219352007-10-02 21:55:22 -04009617
9618 return ret;
9619}
9620
9621/*
9622 * advansys_biosparam()
9623 *
9624 * Translate disk drive geometry if the "BIOS greater than 1 GB"
9625 * support is enabled for a drive.
9626 *
9627 * ip (information pointer) is an int array with the following definition:
9628 * ip[0]: heads
9629 * ip[1]: sectors
9630 * ip[2]: cylinders
9631 */
9632static int
9633advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
9634 sector_t capacity, int ip[])
9635{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009636 struct asc_board *boardp = shost_priv(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04009637
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009638 ASC_DBG(1, "begin\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009639 ASC_STATS(sdev->host, biosparam);
Matthew Wilcox51219352007-10-02 21:55:22 -04009640 if (ASC_NARROW_BOARD(boardp)) {
9641 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
9642 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
9643 ip[0] = 255;
9644 ip[1] = 63;
9645 } else {
9646 ip[0] = 64;
9647 ip[1] = 32;
9648 }
9649 } else {
9650 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
9651 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
9652 ip[0] = 255;
9653 ip[1] = 63;
9654 } else {
9655 ip[0] = 64;
9656 ip[1] = 32;
9657 }
9658 }
9659 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009660 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009661 return 0;
9662}
9663
9664/*
9665 * First-level interrupt handler.
9666 *
9667 * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host.
9668 */
9669static irqreturn_t advansys_interrupt(int irq, void *dev_id)
9670{
Matthew Wilcox51219352007-10-02 21:55:22 -04009671 struct Scsi_Host *shost = dev_id;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009672 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009673 irqreturn_t result = IRQ_NONE;
9674
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009675 ASC_DBG(2, "boardp 0x%p\n", boardp);
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009676 spin_lock(shost->host_lock);
Matthew Wilcox51219352007-10-02 21:55:22 -04009677 if (ASC_NARROW_BOARD(boardp)) {
9678 if (AscIsIntPending(shost->io_port)) {
9679 result = IRQ_HANDLED;
9680 ASC_STATS(shost, interrupt);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009681 ASC_DBG(1, "before AscISR()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009682 AscISR(&boardp->dvc_var.asc_dvc_var);
9683 }
9684 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009685 ASC_DBG(1, "before AdvISR()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009686 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
9687 result = IRQ_HANDLED;
9688 ASC_STATS(shost, interrupt);
9689 }
9690 }
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009691 spin_unlock(shost->host_lock);
Matthew Wilcox51219352007-10-02 21:55:22 -04009692
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009693 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009694 return result;
9695}
9696
9697static int AscHostReqRiscHalt(PortAddr iop_base)
9698{
9699 int count = 0;
9700 int sta = 0;
9701 uchar saved_stop_code;
9702
9703 if (AscIsChipHalted(iop_base))
9704 return (1);
9705 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
9706 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9707 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
9708 do {
9709 if (AscIsChipHalted(iop_base)) {
9710 sta = 1;
9711 break;
9712 }
9713 mdelay(100);
9714 } while (count++ < 20);
9715 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
9716 return (sta);
9717}
9718
9719static int
9720AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
9721{
9722 int sta = FALSE;
9723
9724 if (AscHostReqRiscHalt(iop_base)) {
9725 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9726 AscStartChip(iop_base);
9727 }
9728 return sta;
9729}
9730
9731static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
9732{
9733 char type = sdev->type;
9734 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
9735
9736 if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN))
9737 return;
9738 if (asc_dvc->init_sdtr & tid_bits)
9739 return;
9740
9741 if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0))
9742 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9743
9744 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
9745 if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) ||
9746 (type == TYPE_ROM) || (type == TYPE_TAPE))
9747 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9748
9749 if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
9750 AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id,
9751 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
9752}
9753
9754static void
9755advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
9756{
9757 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
9758 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
9759
9760 if (sdev->lun == 0) {
9761 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
9762 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
9763 asc_dvc->init_sdtr |= tid_bit;
9764 } else {
9765 asc_dvc->init_sdtr &= ~tid_bit;
9766 }
9767
9768 if (orig_init_sdtr != asc_dvc->init_sdtr)
9769 AscAsyncFix(asc_dvc, sdev);
9770 }
9771
9772 if (sdev->tagged_supported) {
9773 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
9774 if (sdev->lun == 0) {
9775 asc_dvc->cfg->can_tagged_qng |= tid_bit;
9776 asc_dvc->use_tagged_qng |= tid_bit;
9777 }
9778 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9779 asc_dvc->max_dvc_qng[sdev->id]);
9780 }
9781 } else {
9782 if (sdev->lun == 0) {
9783 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
9784 asc_dvc->use_tagged_qng &= ~tid_bit;
9785 }
9786 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9787 }
9788
9789 if ((sdev->lun == 0) &&
9790 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
9791 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
9792 asc_dvc->cfg->disc_enable);
9793 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
9794 asc_dvc->use_tagged_qng);
9795 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
9796 asc_dvc->cfg->can_tagged_qng);
9797
9798 asc_dvc->max_dvc_qng[sdev->id] =
9799 asc_dvc->cfg->max_tag_qng[sdev->id];
9800 AscWriteLramByte(asc_dvc->iop_base,
9801 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
9802 asc_dvc->max_dvc_qng[sdev->id]);
9803 }
9804}
9805
9806/*
9807 * Wide Transfers
9808 *
9809 * If the EEPROM enabled WDTR for the device and the device supports wide
9810 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
9811 * write the new value to the microcode.
9812 */
9813static void
9814advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
9815{
9816 unsigned short cfg_word;
9817 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9818 if ((cfg_word & tidmask) != 0)
9819 return;
9820
9821 cfg_word |= tidmask;
9822 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9823
9824 /*
9825 * Clear the microcode SDTR and WDTR negotiation done indicators for
9826 * the target to cause it to negotiate with the new setting set above.
9827 * WDTR when accepted causes the target to enter asynchronous mode, so
9828 * SDTR must be negotiated.
9829 */
9830 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9831 cfg_word &= ~tidmask;
9832 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9833 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
9834 cfg_word &= ~tidmask;
9835 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
9836}
9837
9838/*
9839 * Synchronous Transfers
9840 *
9841 * If the EEPROM enabled SDTR for the device and the device
9842 * supports synchronous transfers, then turn on the device's
9843 * 'sdtr_able' bit. Write the new value to the microcode.
9844 */
9845static void
9846advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
9847{
9848 unsigned short cfg_word;
9849 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
9850 if ((cfg_word & tidmask) != 0)
9851 return;
9852
9853 cfg_word |= tidmask;
9854 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
9855
9856 /*
9857 * Clear the microcode "SDTR negotiation" done indicator for the
9858 * target to cause it to negotiate with the new setting set above.
9859 */
9860 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9861 cfg_word &= ~tidmask;
9862 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9863}
9864
9865/*
9866 * PPR (Parallel Protocol Request) Capable
9867 *
9868 * If the device supports DT mode, then it must be PPR capable.
9869 * The PPR message will be used in place of the SDTR and WDTR
9870 * messages to negotiate synchronous speed and offset, transfer
9871 * width, and protocol options.
9872 */
9873static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
9874 AdvPortAddr iop_base, unsigned short tidmask)
9875{
9876 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
9877 adv_dvc->ppr_able |= tidmask;
9878 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
9879}
9880
9881static void
9882advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
9883{
9884 AdvPortAddr iop_base = adv_dvc->iop_base;
9885 unsigned short tidmask = 1 << sdev->id;
9886
9887 if (sdev->lun == 0) {
9888 /*
9889 * Handle WDTR, SDTR, and Tag Queuing. If the feature
9890 * is enabled in the EEPROM and the device supports the
9891 * feature, then enable it in the microcode.
9892 */
9893
9894 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
9895 advansys_wide_enable_wdtr(iop_base, tidmask);
9896 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
9897 advansys_wide_enable_sdtr(iop_base, tidmask);
9898 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
9899 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
9900
9901 /*
9902 * Tag Queuing is disabled for the BIOS which runs in polled
9903 * mode and would see no benefit from Tag Queuing. Also by
9904 * disabling Tag Queuing in the BIOS devices with Tag Queuing
9905 * bugs will at least work with the BIOS.
9906 */
9907 if ((adv_dvc->tagqng_able & tidmask) &&
9908 sdev->tagged_supported) {
9909 unsigned short cfg_word;
9910 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
9911 cfg_word |= tidmask;
9912 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
9913 cfg_word);
9914 AdvWriteByteLram(iop_base,
9915 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
9916 adv_dvc->max_dvc_qng);
9917 }
9918 }
9919
9920 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
9921 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9922 adv_dvc->max_dvc_qng);
9923 } else {
9924 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9925 }
9926}
9927
9928/*
9929 * Set the number of commands to queue per device for the
9930 * specified host adapter.
9931 */
9932static int advansys_slave_configure(struct scsi_device *sdev)
9933{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009934 struct asc_board *boardp = shost_priv(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04009935
Matthew Wilcox51219352007-10-02 21:55:22 -04009936 if (ASC_NARROW_BOARD(boardp))
9937 advansys_narrow_slave_configure(sdev,
9938 &boardp->dvc_var.asc_dvc_var);
9939 else
9940 advansys_wide_slave_configure(sdev,
9941 &boardp->dvc_var.adv_dvc_var);
9942
9943 return 0;
9944}
9945
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009946static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
Matthew Wilcox05848b62007-10-02 21:55:25 -04009947 struct asc_scsi_q *asc_scsi_q)
Matthew Wilcox51219352007-10-02 21:55:22 -04009948{
Matthew Wilcox05848b62007-10-02 21:55:25 -04009949 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
Matthew Wilcox51219352007-10-02 21:55:22 -04009950
9951 /*
9952 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
9953 */
Matthew Wilcox05848b62007-10-02 21:55:25 -04009954 asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009955
9956 /*
9957 * Build the ASC_SCSI_Q request.
9958 */
Matthew Wilcox05848b62007-10-02 21:55:25 -04009959 asc_scsi_q->cdbptr = &scp->cmnd[0];
9960 asc_scsi_q->q2.cdb_len = scp->cmd_len;
9961 asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
9962 asc_scsi_q->q1.target_lun = scp->device->lun;
9963 asc_scsi_q->q2.target_ix =
Matthew Wilcox51219352007-10-02 21:55:22 -04009964 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
Matthew Wilcox05848b62007-10-02 21:55:25 -04009965 asc_scsi_q->q1.sense_addr =
Matthew Wilcox51219352007-10-02 21:55:22 -04009966 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
Matthew Wilcox05848b62007-10-02 21:55:25 -04009967 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
Matthew Wilcox51219352007-10-02 21:55:22 -04009968
9969 /*
9970 * If there are any outstanding requests for the current target,
9971 * then every 255th request send an ORDERED request. This heuristic
9972 * tries to retain the benefit of request sorting while preventing
9973 * request starvation. 255 is the max number of tags or pending commands
9974 * a device may have outstanding.
9975 *
9976 * The request count is incremented below for every successfully
9977 * started request.
9978 *
9979 */
9980 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
9981 (boardp->reqcnt[scp->device->id] % 255) == 0) {
Matthew Wilcox05848b62007-10-02 21:55:25 -04009982 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -04009983 } else {
Matthew Wilcox05848b62007-10-02 21:55:25 -04009984 asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -04009985 }
9986
9987 /*
9988 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
9989 * buffer command.
9990 */
9991 if (scp->use_sg == 0) {
9992 /*
9993 * CDB request of single contiguous buffer.
9994 */
9995 ASC_STATS(scp->device->host, cont_cnt);
9996 scp->SCp.dma_handle = scp->request_bufflen ?
9997 dma_map_single(boardp->dev, scp->request_buffer,
9998 scp->request_bufflen,
9999 scp->sc_data_direction) : 0;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010000 asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
10001 asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen);
Matthew Wilcox51219352007-10-02 21:55:22 -040010002 ASC_STATS_ADD(scp->device->host, cont_xfer,
10003 ASC_CEILING(scp->request_bufflen, 512));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010004 asc_scsi_q->q1.sg_queue_cnt = 0;
10005 asc_scsi_q->sg_head = NULL;
Matthew Wilcox51219352007-10-02 21:55:22 -040010006 } else {
10007 /*
10008 * CDB scatter-gather request list.
10009 */
10010 int sgcnt;
10011 int use_sg;
10012 struct scatterlist *slp;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010013 struct asc_sg_head *asc_sg_head;
Matthew Wilcox51219352007-10-02 21:55:22 -040010014
10015 slp = (struct scatterlist *)scp->request_buffer;
10016 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10017 scp->sc_data_direction);
10018
10019 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040010020 scmd_printk(KERN_ERR, scp, "use_sg %d > "
10021 "sg_tablesize %d\n", use_sg,
10022 scp->device->host->sg_tablesize);
Matthew Wilcox51219352007-10-02 21:55:22 -040010023 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10024 scp->sc_data_direction);
10025 scp->result = HOST_BYTE(DID_ERROR);
10026 return ASC_ERROR;
10027 }
10028
10029 ASC_STATS(scp->device->host, sg_cnt);
10030
Matthew Wilcox05848b62007-10-02 21:55:25 -040010031 asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
10032 use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
10033 if (!asc_sg_head) {
10034 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10035 scp->sc_data_direction);
10036 scp->result = HOST_BYTE(DID_SOFT_ERROR);
10037 return ASC_ERROR;
10038 }
Matthew Wilcox51219352007-10-02 21:55:22 -040010039
Matthew Wilcox05848b62007-10-02 21:55:25 -040010040 asc_scsi_q->q1.cntl |= QC_SG_HEAD;
10041 asc_scsi_q->sg_head = asc_sg_head;
10042 asc_scsi_q->q1.data_cnt = 0;
10043 asc_scsi_q->q1.data_addr = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040010044 /* This is a byte value, otherwise it would need to be swapped. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010045 asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
Matthew Wilcox51219352007-10-02 21:55:22 -040010046 ASC_STATS_ADD(scp->device->host, sg_elem,
Matthew Wilcox05848b62007-10-02 21:55:25 -040010047 asc_sg_head->entry_cnt);
Matthew Wilcox51219352007-10-02 21:55:22 -040010048
10049 /*
10050 * Convert scatter-gather list into ASC_SG_HEAD list.
10051 */
10052 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010053 asc_sg_head->sg_list[sgcnt].addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010054 cpu_to_le32(sg_dma_address(slp));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010055 asc_sg_head->sg_list[sgcnt].bytes =
Matthew Wilcox51219352007-10-02 21:55:22 -040010056 cpu_to_le32(sg_dma_len(slp));
10057 ASC_STATS_ADD(scp->device->host, sg_xfer,
10058 ASC_CEILING(sg_dma_len(slp), 512));
10059 }
10060 }
10061
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010062 ASC_DBG_PRT_ASC_SCSI_Q(2, asc_scsi_q);
Matthew Wilcox51219352007-10-02 21:55:22 -040010063 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10064
10065 return ASC_NOERROR;
10066}
10067
10068/*
10069 * Build scatter-gather list for Adv Library (Wide Board).
10070 *
10071 * Additional ADV_SG_BLOCK structures will need to be allocated
10072 * if the total number of scatter-gather elements exceeds
10073 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
10074 * assumed to be physically contiguous.
10075 *
10076 * Return:
10077 * ADV_SUCCESS(1) - SG List successfully created
10078 * ADV_ERROR(-1) - SG List creation failed
10079 */
10080static int
Matthew Wilcoxd2411492007-10-02 21:55:31 -040010081adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
Matthew Wilcox51219352007-10-02 21:55:22 -040010082 int use_sg)
10083{
10084 adv_sgblk_t *sgblkp;
10085 ADV_SCSI_REQ_Q *scsiqp;
10086 struct scatterlist *slp;
10087 int sg_elem_cnt;
10088 ADV_SG_BLOCK *sg_block, *prev_sg_block;
10089 ADV_PADDR sg_block_paddr;
10090 int i;
10091
10092 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10093 slp = (struct scatterlist *)scp->request_buffer;
10094 sg_elem_cnt = use_sg;
10095 prev_sg_block = NULL;
10096 reqp->sgblkp = NULL;
10097
10098 for (;;) {
10099 /*
10100 * Allocate a 'adv_sgblk_t' structure from the board free
10101 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
10102 * (15) scatter-gather elements.
10103 */
10104 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010105 ASC_DBG(1, "no free adv_sgblk_t\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040010106 ASC_STATS(scp->device->host, adv_build_nosg);
10107
10108 /*
10109 * Allocation failed. Free 'adv_sgblk_t' structures
10110 * already allocated for the request.
10111 */
10112 while ((sgblkp = reqp->sgblkp) != NULL) {
10113 /* Remove 'sgblkp' from the request list. */
10114 reqp->sgblkp = sgblkp->next_sgblkp;
10115
10116 /* Add 'sgblkp' to the board free list. */
10117 sgblkp->next_sgblkp = boardp->adv_sgblkp;
10118 boardp->adv_sgblkp = sgblkp;
10119 }
10120 return ASC_BUSY;
10121 }
10122
10123 /* Complete 'adv_sgblk_t' board allocation. */
10124 boardp->adv_sgblkp = sgblkp->next_sgblkp;
10125 sgblkp->next_sgblkp = NULL;
10126
10127 /*
10128 * Get 8 byte aligned virtual and physical addresses
10129 * for the allocated ADV_SG_BLOCK structure.
10130 */
10131 sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
10132 sg_block_paddr = virt_to_bus(sg_block);
10133
10134 /*
10135 * Check if this is the first 'adv_sgblk_t' for the
10136 * request.
10137 */
10138 if (reqp->sgblkp == NULL) {
10139 /* Request's first scatter-gather block. */
10140 reqp->sgblkp = sgblkp;
10141
10142 /*
10143 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
10144 * address pointers.
10145 */
10146 scsiqp->sg_list_ptr = sg_block;
10147 scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
10148 } else {
10149 /* Request's second or later scatter-gather block. */
10150 sgblkp->next_sgblkp = reqp->sgblkp;
10151 reqp->sgblkp = sgblkp;
10152
10153 /*
10154 * Point the previous ADV_SG_BLOCK structure to
10155 * the newly allocated ADV_SG_BLOCK structure.
10156 */
10157 prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
10158 }
10159
10160 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
10161 sg_block->sg_list[i].sg_addr =
10162 cpu_to_le32(sg_dma_address(slp));
10163 sg_block->sg_list[i].sg_count =
10164 cpu_to_le32(sg_dma_len(slp));
10165 ASC_STATS_ADD(scp->device->host, sg_xfer,
10166 ASC_CEILING(sg_dma_len(slp), 512));
10167
10168 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
10169 sg_block->sg_cnt = i + 1;
10170 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
10171 return ADV_SUCCESS;
10172 }
10173 slp++;
10174 }
10175 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
10176 prev_sg_block = sg_block;
10177 }
10178}
10179
10180/*
10181 * Build a request structure for the Adv Library (Wide Board).
10182 *
10183 * If an adv_req_t can not be allocated to issue the request,
10184 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
10185 *
10186 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
10187 * microcode for DMA addresses or math operations are byte swapped
10188 * to little-endian order.
10189 */
10190static int
Matthew Wilcoxd2411492007-10-02 21:55:31 -040010191adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
Matthew Wilcox51219352007-10-02 21:55:22 -040010192 ADV_SCSI_REQ_Q **adv_scsiqpp)
10193{
10194 adv_req_t *reqp;
10195 ADV_SCSI_REQ_Q *scsiqp;
10196 int i;
10197 int ret;
10198
10199 /*
10200 * Allocate an adv_req_t structure from the board to execute
10201 * the command.
10202 */
10203 if (boardp->adv_reqp == NULL) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010204 ASC_DBG(1, "no free adv_req_t\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040010205 ASC_STATS(scp->device->host, adv_build_noreq);
10206 return ASC_BUSY;
10207 } else {
10208 reqp = boardp->adv_reqp;
10209 boardp->adv_reqp = reqp->next_reqp;
10210 reqp->next_reqp = NULL;
10211 }
10212
10213 /*
10214 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
10215 */
10216 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10217
10218 /*
10219 * Initialize the structure.
10220 */
10221 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
10222
10223 /*
10224 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
10225 */
10226 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
10227
10228 /*
10229 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
10230 */
10231 reqp->cmndp = scp;
10232
10233 /*
10234 * Build the ADV_SCSI_REQ_Q request.
10235 */
10236
10237 /* Set CDB length and copy it to the request structure. */
10238 scsiqp->cdb_len = scp->cmd_len;
10239 /* Copy first 12 CDB bytes to cdb[]. */
10240 for (i = 0; i < scp->cmd_len && i < 12; i++) {
10241 scsiqp->cdb[i] = scp->cmnd[i];
10242 }
10243 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
10244 for (; i < scp->cmd_len; i++) {
10245 scsiqp->cdb16[i - 12] = scp->cmnd[i];
10246 }
10247
10248 scsiqp->target_id = scp->device->id;
10249 scsiqp->target_lun = scp->device->lun;
10250
10251 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
10252 scsiqp->sense_len = sizeof(scp->sense_buffer);
10253
10254 /*
10255 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
10256 * buffer command.
10257 */
10258
10259 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10260 scsiqp->vdata_addr = scp->request_buffer;
10261 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
10262
10263 if (scp->use_sg == 0) {
10264 /*
10265 * CDB request of single contiguous buffer.
10266 */
10267 reqp->sgblkp = NULL;
10268 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10269 if (scp->request_bufflen) {
10270 scsiqp->vdata_addr = scp->request_buffer;
10271 scp->SCp.dma_handle =
10272 dma_map_single(boardp->dev, scp->request_buffer,
10273 scp->request_bufflen,
10274 scp->sc_data_direction);
10275 } else {
10276 scsiqp->vdata_addr = NULL;
10277 scp->SCp.dma_handle = 0;
10278 }
10279 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
10280 scsiqp->sg_list_ptr = NULL;
10281 scsiqp->sg_real_addr = 0;
10282 ASC_STATS(scp->device->host, cont_cnt);
10283 ASC_STATS_ADD(scp->device->host, cont_xfer,
10284 ASC_CEILING(scp->request_bufflen, 512));
10285 } else {
10286 /*
10287 * CDB scatter-gather request list.
10288 */
10289 struct scatterlist *slp;
10290 int use_sg;
10291
10292 slp = (struct scatterlist *)scp->request_buffer;
10293 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10294 scp->sc_data_direction);
10295
10296 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040010297 scmd_printk(KERN_ERR, scp, "use_sg %d > "
10298 "ADV_MAX_SG_LIST %d\n", use_sg,
Matthew Wilcox51219352007-10-02 21:55:22 -040010299 scp->device->host->sg_tablesize);
10300 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10301 scp->sc_data_direction);
10302 scp->result = HOST_BYTE(DID_ERROR);
10303
10304 /*
10305 * Free the 'adv_req_t' structure by adding it back
10306 * to the board free list.
10307 */
10308 reqp->next_reqp = boardp->adv_reqp;
10309 boardp->adv_reqp = reqp;
10310
10311 return ASC_ERROR;
10312 }
10313
10314 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
10315 if (ret != ADV_SUCCESS) {
10316 /*
10317 * Free the adv_req_t structure by adding it back to
10318 * the board free list.
10319 */
10320 reqp->next_reqp = boardp->adv_reqp;
10321 boardp->adv_reqp = reqp;
10322
10323 return ret;
10324 }
10325
10326 ASC_STATS(scp->device->host, sg_cnt);
10327 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
10328 }
10329
10330 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
10331 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10332
10333 *adv_scsiqpp = scsiqp;
10334
10335 return ASC_NOERROR;
10336}
10337
10338static int AscSgListToQueue(int sg_list)
10339{
10340 int n_sg_list_qs;
10341
10342 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
10343 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
10344 n_sg_list_qs++;
10345 return n_sg_list_qs + 1;
10346}
10347
10348static uint
10349AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
10350{
10351 uint cur_used_qs;
10352 uint cur_free_qs;
10353 ASC_SCSI_BIT_ID_TYPE target_id;
10354 uchar tid_no;
10355
10356 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
10357 tid_no = ASC_TIX_TO_TID(target_ix);
10358 if ((asc_dvc->unit_not_ready & target_id) ||
10359 (asc_dvc->queue_full_or_busy & target_id)) {
10360 return 0;
10361 }
10362 if (n_qs == 1) {
10363 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10364 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
10365 } else {
10366 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10367 (uint) ASC_MIN_FREE_Q;
10368 }
10369 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
10370 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
10371 if (asc_dvc->cur_dvc_qng[tid_no] >=
10372 asc_dvc->max_dvc_qng[tid_no]) {
10373 return 0;
10374 }
10375 return cur_free_qs;
10376 }
10377 if (n_qs > 1) {
10378 if ((n_qs > asc_dvc->last_q_shortage)
10379 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
10380 asc_dvc->last_q_shortage = n_qs;
10381 }
10382 }
10383 return 0;
10384}
10385
10386static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
10387{
10388 ushort q_addr;
10389 uchar next_qp;
10390 uchar q_status;
10391
10392 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10393 q_status = (uchar)AscReadLramByte(iop_base,
10394 (ushort)(q_addr +
10395 ASC_SCSIQ_B_STATUS));
10396 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10397 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END))
10398 return next_qp;
10399 return ASC_QLINK_END;
10400}
10401
10402static uchar
10403AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
10404{
10405 uchar i;
10406
10407 for (i = 0; i < n_free_q; i++) {
10408 free_q_head = AscAllocFreeQueue(iop_base, free_q_head);
10409 if (free_q_head == ASC_QLINK_END)
10410 break;
10411 }
10412 return free_q_head;
10413}
10414
10415/*
10416 * void
10417 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10418 *
10419 * Calling/Exit State:
10420 * none
10421 *
10422 * Description:
10423 * Output an ASC_SCSI_Q structure to the chip
10424 */
10425static void
10426DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10427{
10428 int i;
10429
10430 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
10431 AscSetChipLramAddr(iop_base, s_addr);
10432 for (i = 0; i < 2 * words; i += 2) {
10433 if (i == 4 || i == 20) {
10434 continue;
10435 }
10436 outpw(iop_base + IOP_RAM_DATA,
10437 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
10438 }
10439}
10440
10441static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10442{
10443 ushort q_addr;
10444 uchar tid_no;
10445 uchar sdtr_data;
10446 uchar syn_period_ix;
10447 uchar syn_offset;
10448 PortAddr iop_base;
10449
10450 iop_base = asc_dvc->iop_base;
10451 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
10452 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
10453 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
10454 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10455 syn_period_ix =
10456 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
10457 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
10458 AscMsgOutSDTR(asc_dvc,
10459 asc_dvc->sdtr_period_tbl[syn_period_ix],
10460 syn_offset);
10461 scsiq->q1.cntl |= QC_MSG_OUT;
10462 }
10463 q_addr = ASC_QNO_TO_QADDR(q_no);
10464 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
10465 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10466 }
10467 scsiq->q1.status = QS_FREE;
10468 AscMemWordCopyPtrToLram(iop_base,
10469 q_addr + ASC_SCSIQ_CDB_BEG,
10470 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
10471
10472 DvcPutScsiQ(iop_base,
10473 q_addr + ASC_SCSIQ_CPY_BEG,
10474 (uchar *)&scsiq->q1.cntl,
10475 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
10476 AscWriteLramWord(iop_base,
10477 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
10478 (ushort)(((ushort)scsiq->q1.
10479 q_no << 8) | (ushort)QS_READY));
10480 return 1;
10481}
10482
10483static int
10484AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10485{
10486 int sta;
10487 int i;
10488 ASC_SG_HEAD *sg_head;
10489 ASC_SG_LIST_Q scsi_sg_q;
10490 ASC_DCNT saved_data_addr;
10491 ASC_DCNT saved_data_cnt;
10492 PortAddr iop_base;
10493 ushort sg_list_dwords;
10494 ushort sg_index;
10495 ushort sg_entry_cnt;
10496 ushort q_addr;
10497 uchar next_qp;
10498
10499 iop_base = asc_dvc->iop_base;
10500 sg_head = scsiq->sg_head;
10501 saved_data_addr = scsiq->q1.data_addr;
10502 saved_data_cnt = scsiq->q1.data_cnt;
10503 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
10504 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
10505#if CC_VERY_LONG_SG_LIST
10506 /*
10507 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
10508 * then not all SG elements will fit in the allocated queues.
10509 * The rest of the SG elements will be copied when the RISC
10510 * completes the SG elements that fit and halts.
10511 */
10512 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10513 /*
10514 * Set sg_entry_cnt to be the number of SG elements that
10515 * will fit in the allocated SG queues. It is minus 1, because
10516 * the first SG element is handled above. ASC_MAX_SG_LIST is
10517 * already inflated by 1 to account for this. For example it
10518 * may be 50 which is 1 + 7 queues * 7 SG elements.
10519 */
10520 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
10521
10522 /*
10523 * Keep track of remaining number of SG elements that will
10524 * need to be handled from a_isr.c.
10525 */
10526 scsiq->remain_sg_entry_cnt =
10527 sg_head->entry_cnt - ASC_MAX_SG_LIST;
10528 } else {
10529#endif /* CC_VERY_LONG_SG_LIST */
10530 /*
10531 * Set sg_entry_cnt to be the number of SG elements that
10532 * will fit in the allocated SG queues. It is minus 1, because
10533 * the first SG element is handled above.
10534 */
10535 sg_entry_cnt = sg_head->entry_cnt - 1;
10536#if CC_VERY_LONG_SG_LIST
10537 }
10538#endif /* CC_VERY_LONG_SG_LIST */
10539 if (sg_entry_cnt != 0) {
10540 scsiq->q1.cntl |= QC_SG_HEAD;
10541 q_addr = ASC_QNO_TO_QADDR(q_no);
10542 sg_index = 1;
10543 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
10544 scsi_sg_q.sg_head_qp = q_no;
10545 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
10546 for (i = 0; i < sg_head->queue_cnt; i++) {
10547 scsi_sg_q.seq_no = i + 1;
10548 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
10549 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
10550 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
10551 if (i == 0) {
10552 scsi_sg_q.sg_list_cnt =
10553 ASC_SG_LIST_PER_Q;
10554 scsi_sg_q.sg_cur_list_cnt =
10555 ASC_SG_LIST_PER_Q;
10556 } else {
10557 scsi_sg_q.sg_list_cnt =
10558 ASC_SG_LIST_PER_Q - 1;
10559 scsi_sg_q.sg_cur_list_cnt =
10560 ASC_SG_LIST_PER_Q - 1;
10561 }
10562 } else {
10563#if CC_VERY_LONG_SG_LIST
10564 /*
10565 * This is the last SG queue in the list of
10566 * allocated SG queues. If there are more
10567 * SG elements than will fit in the allocated
10568 * queues, then set the QCSG_SG_XFER_MORE flag.
10569 */
10570 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10571 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
10572 } else {
10573#endif /* CC_VERY_LONG_SG_LIST */
10574 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
10575#if CC_VERY_LONG_SG_LIST
10576 }
10577#endif /* CC_VERY_LONG_SG_LIST */
10578 sg_list_dwords = sg_entry_cnt << 1;
10579 if (i == 0) {
10580 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
10581 scsi_sg_q.sg_cur_list_cnt =
10582 sg_entry_cnt;
10583 } else {
10584 scsi_sg_q.sg_list_cnt =
10585 sg_entry_cnt - 1;
10586 scsi_sg_q.sg_cur_list_cnt =
10587 sg_entry_cnt - 1;
10588 }
10589 sg_entry_cnt = 0;
10590 }
10591 next_qp = AscReadLramByte(iop_base,
10592 (ushort)(q_addr +
10593 ASC_SCSIQ_B_FWD));
10594 scsi_sg_q.q_no = next_qp;
10595 q_addr = ASC_QNO_TO_QADDR(next_qp);
10596 AscMemWordCopyPtrToLram(iop_base,
10597 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
10598 (uchar *)&scsi_sg_q,
10599 sizeof(ASC_SG_LIST_Q) >> 1);
10600 AscMemDWordCopyPtrToLram(iop_base,
10601 q_addr + ASC_SGQ_LIST_BEG,
10602 (uchar *)&sg_head->
10603 sg_list[sg_index],
10604 sg_list_dwords);
10605 sg_index += ASC_SG_LIST_PER_Q;
10606 scsiq->next_sg_index = sg_index;
10607 }
10608 } else {
10609 scsiq->q1.cntl &= ~QC_SG_HEAD;
10610 }
10611 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
10612 scsiq->q1.data_addr = saved_data_addr;
10613 scsiq->q1.data_cnt = saved_data_cnt;
10614 return (sta);
10615}
10616
10617static int
10618AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
10619{
10620 PortAddr iop_base;
10621 uchar free_q_head;
10622 uchar next_qp;
10623 uchar tid_no;
10624 uchar target_ix;
10625 int sta;
10626
10627 iop_base = asc_dvc->iop_base;
10628 target_ix = scsiq->q2.target_ix;
10629 tid_no = ASC_TIX_TO_TID(target_ix);
10630 sta = 0;
10631 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
10632 if (n_q_required > 1) {
10633 next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head,
10634 (uchar)n_q_required);
10635 if (next_qp != ASC_QLINK_END) {
10636 asc_dvc->last_q_shortage = 0;
10637 scsiq->sg_head->queue_cnt = n_q_required - 1;
10638 scsiq->q1.q_no = free_q_head;
10639 sta = AscPutReadySgListQueue(asc_dvc, scsiq,
10640 free_q_head);
10641 }
10642 } else if (n_q_required == 1) {
10643 next_qp = AscAllocFreeQueue(iop_base, free_q_head);
10644 if (next_qp != ASC_QLINK_END) {
10645 scsiq->q1.q_no = free_q_head;
10646 sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head);
10647 }
10648 }
10649 if (sta == 1) {
10650 AscPutVarFreeQHead(iop_base, next_qp);
10651 asc_dvc->cur_total_qng += n_q_required;
10652 asc_dvc->cur_dvc_qng[tid_no]++;
10653 }
10654 return sta;
10655}
10656
10657#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
10658static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
10659 INQUIRY,
10660 REQUEST_SENSE,
10661 READ_CAPACITY,
10662 READ_TOC,
10663 MODE_SELECT,
10664 MODE_SENSE,
10665 MODE_SELECT_10,
10666 MODE_SENSE_10,
10667 0xFF,
10668 0xFF,
10669 0xFF,
10670 0xFF,
10671 0xFF,
10672 0xFF,
10673 0xFF,
10674 0xFF
10675};
10676
10677static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
10678{
10679 PortAddr iop_base;
10680 int sta;
10681 int n_q_required;
10682 int disable_syn_offset_one_fix;
10683 int i;
10684 ASC_PADDR addr;
10685 ushort sg_entry_cnt = 0;
10686 ushort sg_entry_cnt_minus_one = 0;
10687 uchar target_ix;
10688 uchar tid_no;
10689 uchar sdtr_data;
10690 uchar extra_bytes;
10691 uchar scsi_cmd;
10692 uchar disable_cmd;
10693 ASC_SG_HEAD *sg_head;
10694 ASC_DCNT data_cnt;
10695
10696 iop_base = asc_dvc->iop_base;
10697 sg_head = scsiq->sg_head;
10698 if (asc_dvc->err_code != 0)
10699 return (ERR);
10700 scsiq->q1.q_no = 0;
10701 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
10702 scsiq->q1.extra_bytes = 0;
10703 }
10704 sta = 0;
10705 target_ix = scsiq->q2.target_ix;
10706 tid_no = ASC_TIX_TO_TID(target_ix);
10707 n_q_required = 1;
10708 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
10709 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
10710 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
10711 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10712 AscMsgOutSDTR(asc_dvc,
10713 asc_dvc->
10714 sdtr_period_tbl[(sdtr_data >> 4) &
10715 (uchar)(asc_dvc->
10716 max_sdtr_index -
10717 1)],
10718 (uchar)(sdtr_data & (uchar)
10719 ASC_SYN_MAX_OFFSET));
10720 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
10721 }
10722 }
10723 if (asc_dvc->in_critical_cnt != 0) {
10724 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
10725 return (ERR);
10726 }
10727 asc_dvc->in_critical_cnt++;
10728 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10729 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
10730 asc_dvc->in_critical_cnt--;
10731 return (ERR);
10732 }
10733#if !CC_VERY_LONG_SG_LIST
10734 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10735 asc_dvc->in_critical_cnt--;
10736 return (ERR);
10737 }
10738#endif /* !CC_VERY_LONG_SG_LIST */
10739 if (sg_entry_cnt == 1) {
10740 scsiq->q1.data_addr =
10741 (ADV_PADDR)sg_head->sg_list[0].addr;
10742 scsiq->q1.data_cnt =
10743 (ADV_DCNT)sg_head->sg_list[0].bytes;
10744 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
10745 }
10746 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
10747 }
10748 scsi_cmd = scsiq->cdbptr[0];
10749 disable_syn_offset_one_fix = FALSE;
10750 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
10751 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
10752 if (scsiq->q1.cntl & QC_SG_HEAD) {
10753 data_cnt = 0;
10754 for (i = 0; i < sg_entry_cnt; i++) {
10755 data_cnt +=
10756 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
10757 bytes);
10758 }
10759 } else {
10760 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
10761 }
10762 if (data_cnt != 0UL) {
10763 if (data_cnt < 512UL) {
10764 disable_syn_offset_one_fix = TRUE;
10765 } else {
10766 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
10767 i++) {
10768 disable_cmd =
10769 _syn_offset_one_disable_cmd[i];
10770 if (disable_cmd == 0xFF) {
10771 break;
10772 }
10773 if (scsi_cmd == disable_cmd) {
10774 disable_syn_offset_one_fix =
10775 TRUE;
10776 break;
10777 }
10778 }
10779 }
10780 }
10781 }
10782 if (disable_syn_offset_one_fix) {
10783 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10784 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
10785 ASC_TAG_FLAG_DISABLE_DISCONNECT);
10786 } else {
10787 scsiq->q2.tag_code &= 0x27;
10788 }
10789 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10790 if (asc_dvc->bug_fix_cntl) {
10791 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10792 if ((scsi_cmd == READ_6) ||
10793 (scsi_cmd == READ_10)) {
10794 addr =
10795 (ADV_PADDR)le32_to_cpu(sg_head->
10796 sg_list
10797 [sg_entry_cnt_minus_one].
10798 addr) +
10799 (ADV_DCNT)le32_to_cpu(sg_head->
10800 sg_list
10801 [sg_entry_cnt_minus_one].
10802 bytes);
10803 extra_bytes =
10804 (uchar)((ushort)addr & 0x0003);
10805 if ((extra_bytes != 0)
10806 &&
10807 ((scsiq->q2.
10808 tag_code &
10809 ASC_TAG_FLAG_EXTRA_BYTES)
10810 == 0)) {
10811 scsiq->q2.tag_code |=
10812 ASC_TAG_FLAG_EXTRA_BYTES;
10813 scsiq->q1.extra_bytes =
10814 extra_bytes;
10815 data_cnt =
10816 le32_to_cpu(sg_head->
10817 sg_list
10818 [sg_entry_cnt_minus_one].
10819 bytes);
10820 data_cnt -=
10821 (ASC_DCNT) extra_bytes;
10822 sg_head->
10823 sg_list
10824 [sg_entry_cnt_minus_one].
10825 bytes =
10826 cpu_to_le32(data_cnt);
10827 }
10828 }
10829 }
10830 }
10831 sg_head->entry_to_copy = sg_head->entry_cnt;
10832#if CC_VERY_LONG_SG_LIST
10833 /*
10834 * Set the sg_entry_cnt to the maximum possible. The rest of
10835 * the SG elements will be copied when the RISC completes the
10836 * SG elements that fit and halts.
10837 */
10838 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10839 sg_entry_cnt = ASC_MAX_SG_LIST;
10840 }
10841#endif /* CC_VERY_LONG_SG_LIST */
10842 n_q_required = AscSgListToQueue(sg_entry_cnt);
10843 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
10844 (uint) n_q_required)
10845 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
10846 if ((sta =
10847 AscSendScsiQueue(asc_dvc, scsiq,
10848 n_q_required)) == 1) {
10849 asc_dvc->in_critical_cnt--;
10850 return (sta);
10851 }
10852 }
10853 } else {
10854 if (asc_dvc->bug_fix_cntl) {
10855 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10856 if ((scsi_cmd == READ_6) ||
10857 (scsi_cmd == READ_10)) {
10858 addr =
10859 le32_to_cpu(scsiq->q1.data_addr) +
10860 le32_to_cpu(scsiq->q1.data_cnt);
10861 extra_bytes =
10862 (uchar)((ushort)addr & 0x0003);
10863 if ((extra_bytes != 0)
10864 &&
10865 ((scsiq->q2.
10866 tag_code &
10867 ASC_TAG_FLAG_EXTRA_BYTES)
10868 == 0)) {
10869 data_cnt =
10870 le32_to_cpu(scsiq->q1.
10871 data_cnt);
10872 if (((ushort)data_cnt & 0x01FF)
10873 == 0) {
10874 scsiq->q2.tag_code |=
10875 ASC_TAG_FLAG_EXTRA_BYTES;
10876 data_cnt -= (ASC_DCNT)
10877 extra_bytes;
10878 scsiq->q1.data_cnt =
10879 cpu_to_le32
10880 (data_cnt);
10881 scsiq->q1.extra_bytes =
10882 extra_bytes;
10883 }
10884 }
10885 }
10886 }
10887 }
10888 n_q_required = 1;
10889 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
10890 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
10891 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
10892 n_q_required)) == 1) {
10893 asc_dvc->in_critical_cnt--;
10894 return (sta);
10895 }
10896 }
10897 }
10898 asc_dvc->in_critical_cnt--;
10899 return (sta);
10900}
10901
10902/*
10903 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
10904 *
10905 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
10906 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
10907 * RISC to notify it a new command is ready to be executed.
10908 *
10909 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
10910 * set to SCSI_MAX_RETRY.
10911 *
10912 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
10913 * for DMA addresses or math operations are byte swapped to little-endian
10914 * order.
10915 *
10916 * Return:
10917 * ADV_SUCCESS(1) - The request was successfully queued.
10918 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
10919 * request completes.
10920 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
10921 * host IC error.
10922 */
10923static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
10924{
10925 AdvPortAddr iop_base;
10926 ADV_DCNT req_size;
10927 ADV_PADDR req_paddr;
10928 ADV_CARR_T *new_carrp;
10929
10930 /*
10931 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
10932 */
10933 if (scsiq->target_id > ADV_MAX_TID) {
10934 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
10935 scsiq->done_status = QD_WITH_ERROR;
10936 return ADV_ERROR;
10937 }
10938
10939 iop_base = asc_dvc->iop_base;
10940
10941 /*
10942 * Allocate a carrier ensuring at least one carrier always
10943 * remains on the freelist and initialize fields.
10944 */
10945 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
10946 return ADV_BUSY;
10947 }
10948 asc_dvc->carr_freelist = (ADV_CARR_T *)
10949 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
10950 asc_dvc->carr_pending_cnt++;
10951
10952 /*
10953 * Set the carrier to be a stopper by setting 'next_vpa'
10954 * to the stopper value. The current stopper will be changed
10955 * below to point to the new stopper.
10956 */
10957 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
10958
10959 /*
10960 * Clear the ADV_SCSI_REQ_Q done flag.
10961 */
10962 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
10963
10964 req_size = sizeof(ADV_SCSI_REQ_Q);
10965 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
10966 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
10967
10968 BUG_ON(req_paddr & 31);
10969 BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q));
10970
10971 /* Wait for assertion before making little-endian */
10972 req_paddr = cpu_to_le32(req_paddr);
10973
10974 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
10975 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
10976 scsiq->scsiq_rptr = req_paddr;
10977
10978 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
10979 /*
10980 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
10981 * order during initialization.
10982 */
10983 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
10984
10985 /*
10986 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
10987 * the microcode. The newly allocated stopper will become the new
10988 * stopper.
10989 */
10990 asc_dvc->icq_sp->areq_vpa = req_paddr;
10991
10992 /*
10993 * Set the 'next_vpa' pointer for the old stopper to be the
10994 * physical address of the new stopper. The RISC can only
10995 * follow physical addresses.
10996 */
10997 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
10998
10999 /*
11000 * Set the host adapter stopper pointer to point to the new carrier.
11001 */
11002 asc_dvc->icq_sp = new_carrp;
11003
11004 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
11005 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
11006 /*
11007 * Tickle the RISC to tell it to read its Command Queue Head pointer.
11008 */
11009 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
11010 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
11011 /*
11012 * Clear the tickle value. In the ASC-3550 the RISC flag
11013 * command 'clr_tickle_a' does not work unless the host
11014 * value is cleared.
11015 */
11016 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
11017 ADV_TICKLE_NOP);
11018 }
11019 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
11020 /*
11021 * Notify the RISC a carrier is ready by writing the physical
11022 * address of the new carrier stopper to the COMMA register.
11023 */
11024 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
11025 le32_to_cpu(new_carrp->carr_pa));
11026 }
11027
11028 return ADV_SUCCESS;
11029}
11030
11031/*
11032 * Execute a single 'Scsi_Cmnd'.
11033 *
11034 * The function 'done' is called when the request has been completed.
11035 *
11036 * Scsi_Cmnd:
11037 *
11038 * host - board controlling device
11039 * device - device to send command
11040 * target - target of device
11041 * lun - lun of device
11042 * cmd_len - length of SCSI CDB
11043 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
11044 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
11045 *
11046 * if (use_sg == 0) {
11047 * request_buffer - buffer address for request
11048 * request_bufflen - length of request buffer
11049 * } else {
11050 * request_buffer - pointer to scatterlist structure
11051 * }
11052 *
11053 * sense_buffer - sense command buffer
11054 *
11055 * result (4 bytes of an int):
11056 * Byte Meaning
11057 * 0 SCSI Status Byte Code
11058 * 1 SCSI One Byte Message Code
11059 * 2 Host Error Code
11060 * 3 Mid-Level Error Code
11061 *
11062 * host driver fields:
11063 * SCp - Scsi_Pointer used for command processing status
11064 * scsi_done - used to save caller's done function
11065 * host_scribble - used for pointer to another struct scsi_cmnd
11066 *
11067 * If this function returns ASC_NOERROR the request will be completed
11068 * from the interrupt handler.
11069 *
11070 * If this function returns ASC_ERROR the host error code has been set,
11071 * and the called must call asc_scsi_done.
11072 *
11073 * If ASC_BUSY is returned the request will be returned to the midlayer
11074 * and re-tried later.
11075 */
11076static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
11077{
Matthew Wilcox41d24932007-10-02 21:55:24 -040011078 int ret, err_code;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011079 struct asc_board *boardp = shost_priv(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040011080
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011081 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011082
11083 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011084 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox05848b62007-10-02 21:55:25 -040011085 struct asc_scsi_q asc_scsi_q;
Matthew Wilcox51219352007-10-02 21:55:22 -040011086
Matthew Wilcox41d24932007-10-02 21:55:24 -040011087 /* asc_build_req() can not return ASC_BUSY. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040011088 ret = asc_build_req(boardp, scp, &asc_scsi_q);
11089 if (ret == ASC_ERROR) {
Matthew Wilcox51219352007-10-02 21:55:22 -040011090 ASC_STATS(scp->device->host, build_error);
11091 return ASC_ERROR;
11092 }
11093
Matthew Wilcox41d24932007-10-02 21:55:24 -040011094 ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
Matthew Wilcox05848b62007-10-02 21:55:25 -040011095 kfree(asc_scsi_q.sg_head);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011096 err_code = asc_dvc->err_code;
Matthew Wilcox51219352007-10-02 21:55:22 -040011097 } else {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011098 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
11099 ADV_SCSI_REQ_Q *adv_scsiqp;
Matthew Wilcox51219352007-10-02 21:55:22 -040011100
Matthew Wilcox51219352007-10-02 21:55:22 -040011101 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
11102 case ASC_NOERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011103 ASC_DBG(3, "adv_build_req ASC_NOERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011104 break;
11105 case ASC_BUSY:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011106 ASC_DBG(1, "adv_build_req ASC_BUSY\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011107 /*
11108 * The asc_stats fields 'adv_build_noreq' and
11109 * 'adv_build_nosg' count wide board busy conditions.
11110 * They are updated in adv_build_req and
11111 * adv_get_sglist, respectively.
11112 */
11113 return ASC_BUSY;
11114 case ASC_ERROR:
11115 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011116 ASC_DBG(1, "adv_build_req ASC_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011117 ASC_STATS(scp->device->host, build_error);
11118 return ASC_ERROR;
11119 }
11120
Matthew Wilcox41d24932007-10-02 21:55:24 -040011121 ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp);
11122 err_code = adv_dvc->err_code;
11123 }
11124
11125 switch (ret) {
11126 case ASC_NOERROR:
11127 ASC_STATS(scp->device->host, exe_noerror);
11128 /*
11129 * Increment monotonically increasing per device
11130 * successful request counter. Wrapping doesn't matter.
11131 */
11132 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011133 ASC_DBG(1, "ExeScsiQueue() ASC_NOERROR\n");
Matthew Wilcox41d24932007-10-02 21:55:24 -040011134 break;
11135 case ASC_BUSY:
11136 ASC_STATS(scp->device->host, exe_busy);
11137 break;
11138 case ASC_ERROR:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011139 scmd_printk(KERN_ERR, scp, "ExeScsiQueue() ASC_ERROR, "
11140 "err_code 0x%x\n", err_code);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011141 ASC_STATS(scp->device->host, exe_error);
11142 scp->result = HOST_BYTE(DID_ERROR);
11143 break;
11144 default:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011145 scmd_printk(KERN_ERR, scp, "ExeScsiQueue() unknown, "
11146 "err_code 0x%x\n", err_code);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011147 ASC_STATS(scp->device->host, exe_unknown);
11148 scp->result = HOST_BYTE(DID_ERROR);
11149 break;
Matthew Wilcox51219352007-10-02 21:55:22 -040011150 }
11151
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011152 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011153 return ret;
11154}
11155
11156/*
11157 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
11158 *
11159 * This function always returns 0. Command return status is saved
11160 * in the 'scp' result field.
11161 */
11162static int
11163advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
11164{
11165 struct Scsi_Host *shost = scp->device->host;
Matthew Wilcox51219352007-10-02 21:55:22 -040011166 int asc_res, result = 0;
11167
11168 ASC_STATS(shost, queuecommand);
11169 scp->scsi_done = done;
11170
Matthew Wilcox51219352007-10-02 21:55:22 -040011171 asc_res = asc_execute_scsi_cmnd(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011172
11173 switch (asc_res) {
11174 case ASC_NOERROR:
11175 break;
11176 case ASC_BUSY:
11177 result = SCSI_MLQUEUE_HOST_BUSY;
11178 break;
11179 case ASC_ERROR:
11180 default:
11181 asc_scsi_done(scp);
11182 break;
11183 }
11184
11185 return result;
11186}
11187
11188static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
11189{
11190 PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11191 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
11192 return inpw(eisa_cfg_iop);
11193}
11194
11195/*
11196 * Return the BIOS address of the adapter at the specified
11197 * I/O port and with the specified bus type.
11198 */
11199static unsigned short __devinit
11200AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
11201{
11202 unsigned short cfg_lsw;
11203 unsigned short bios_addr;
11204
11205 /*
11206 * The PCI BIOS is re-located by the motherboard BIOS. Because
11207 * of this the driver can not determine where a PCI BIOS is
11208 * loaded and executes.
11209 */
11210 if (bus_type & ASC_IS_PCI)
11211 return 0;
11212
11213 if ((bus_type & ASC_IS_EISA) != 0) {
11214 cfg_lsw = AscGetEisaChipCfg(iop_base);
11215 cfg_lsw &= 0x000F;
11216 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
11217 return bios_addr;
11218 }
11219
11220 cfg_lsw = AscGetChipCfgLsw(iop_base);
11221
11222 /*
11223 * ISA PnP uses the top bit as the 32K BIOS flag
11224 */
11225 if (bus_type == ASC_IS_ISAPNP)
11226 cfg_lsw &= 0x7FFF;
11227 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
11228 return bios_addr;
11229}
11230
11231static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
11232{
11233 ushort cfg_lsw;
11234
11235 if (AscGetChipScsiID(iop_base) == new_host_id) {
11236 return (new_host_id);
11237 }
11238 cfg_lsw = AscGetChipCfgLsw(iop_base);
11239 cfg_lsw &= 0xF8FF;
11240 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
11241 AscSetChipCfgLsw(iop_base, cfg_lsw);
11242 return (AscGetChipScsiID(iop_base));
11243}
11244
11245static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
11246{
11247 unsigned char sc;
11248
11249 AscSetBank(iop_base, 1);
11250 sc = inp(iop_base + IOP_REG_SC);
11251 AscSetBank(iop_base, 0);
11252 return sc;
11253}
11254
11255static unsigned char __devinit
11256AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
11257{
11258 if (bus_type & ASC_IS_EISA) {
11259 PortAddr eisa_iop;
11260 unsigned char revision;
11261 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11262 (PortAddr) ASC_EISA_REV_IOP_MASK;
11263 revision = inp(eisa_iop);
11264 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
11265 }
11266 return AscGetChipVerNo(iop_base);
11267}
11268
Matthew Wilcox51219352007-10-02 21:55:22 -040011269#ifdef CONFIG_ISA
11270static void __devinit AscEnableIsaDma(uchar dma_channel)
11271{
11272 if (dma_channel < 4) {
11273 outp(0x000B, (ushort)(0xC0 | dma_channel));
11274 outp(0x000A, dma_channel);
11275 } else if (dma_channel < 8) {
11276 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
11277 outp(0x00D4, (ushort)(dma_channel - 4));
11278 }
Matthew Wilcox51219352007-10-02 21:55:22 -040011279}
11280#endif /* CONFIG_ISA */
11281
11282static int AscStopQueueExe(PortAddr iop_base)
11283{
11284 int count = 0;
11285
11286 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
11287 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
11288 ASC_STOP_REQ_RISC_STOP);
11289 do {
11290 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
11291 ASC_STOP_ACK_RISC_STOP) {
11292 return (1);
11293 }
11294 mdelay(100);
11295 } while (count++ < 20);
11296 }
11297 return (0);
11298}
11299
11300static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
11301{
11302 if (bus_type & ASC_IS_ISA)
11303 return ASC_MAX_ISA_DMA_COUNT;
11304 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
11305 return ASC_MAX_VL_DMA_COUNT;
11306 return ASC_MAX_PCI_DMA_COUNT;
11307}
11308
11309#ifdef CONFIG_ISA
11310static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
11311{
11312 ushort channel;
11313
11314 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
11315 if (channel == 0x03)
11316 return (0);
11317 else if (channel == 0x00)
11318 return (7);
11319 return (channel + 4);
11320}
11321
11322static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
11323{
11324 ushort cfg_lsw;
11325 uchar value;
11326
11327 if ((dma_channel >= 5) && (dma_channel <= 7)) {
11328 if (dma_channel == 7)
11329 value = 0x00;
11330 else
11331 value = dma_channel - 4;
11332 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
11333 cfg_lsw |= value;
11334 AscSetChipCfgLsw(iop_base, cfg_lsw);
11335 return (AscGetIsaDmaChannel(iop_base));
11336 }
11337 return 0;
11338}
11339
11340static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
11341{
11342 uchar speed_value;
11343
11344 AscSetBank(iop_base, 1);
11345 speed_value = AscReadChipDmaSpeed(iop_base);
11346 speed_value &= 0x07;
11347 AscSetBank(iop_base, 0);
11348 return speed_value;
11349}
11350
11351static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
11352{
11353 speed_value &= 0x07;
11354 AscSetBank(iop_base, 1);
11355 AscWriteChipDmaSpeed(iop_base, speed_value);
11356 AscSetBank(iop_base, 0);
11357 return AscGetIsaDmaSpeed(iop_base);
11358}
11359#endif /* CONFIG_ISA */
11360
11361static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
11362{
11363 int i;
11364 PortAddr iop_base;
11365 ushort warn_code;
11366 uchar chip_version;
11367
11368 iop_base = asc_dvc->iop_base;
11369 warn_code = 0;
11370 asc_dvc->err_code = 0;
11371 if ((asc_dvc->bus_type &
11372 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
11373 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
11374 }
11375 AscSetChipControl(iop_base, CC_HALT);
11376 AscSetChipStatus(iop_base, 0);
11377 asc_dvc->bug_fix_cntl = 0;
11378 asc_dvc->pci_fix_asyn_xfer = 0;
11379 asc_dvc->pci_fix_asyn_xfer_always = 0;
11380 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
11381 asc_dvc->sdtr_done = 0;
11382 asc_dvc->cur_total_qng = 0;
11383 asc_dvc->is_in_int = 0;
11384 asc_dvc->in_critical_cnt = 0;
11385 asc_dvc->last_q_shortage = 0;
11386 asc_dvc->use_tagged_qng = 0;
11387 asc_dvc->no_scam = 0;
11388 asc_dvc->unit_not_ready = 0;
11389 asc_dvc->queue_full_or_busy = 0;
11390 asc_dvc->redo_scam = 0;
11391 asc_dvc->res2 = 0;
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -040011392 asc_dvc->min_sdtr_index = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040011393 asc_dvc->cfg->can_tagged_qng = 0;
11394 asc_dvc->cfg->cmd_qng_enabled = 0;
11395 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
11396 asc_dvc->init_sdtr = 0;
11397 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
11398 asc_dvc->scsi_reset_wait = 3;
11399 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
11400 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
11401 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
11402 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
11403 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
Matthew Wilcox51219352007-10-02 21:55:22 -040011404 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
11405 asc_dvc->cfg->chip_version = chip_version;
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -040011406 asc_dvc->sdtr_period_tbl = asc_syn_xfer_period;
Matthew Wilcox51219352007-10-02 21:55:22 -040011407 asc_dvc->max_sdtr_index = 7;
11408 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
11409 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
11410 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -040011411 asc_dvc->sdtr_period_tbl = asc_syn_ultra_xfer_period;
Matthew Wilcox51219352007-10-02 21:55:22 -040011412 asc_dvc->max_sdtr_index = 15;
11413 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
11414 AscSetExtraControl(iop_base,
11415 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11416 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
11417 AscSetExtraControl(iop_base,
11418 (SEC_ACTIVE_NEGATE |
11419 SEC_ENABLE_FILTER));
11420 }
11421 }
11422 if (asc_dvc->bus_type == ASC_IS_PCI) {
11423 AscSetExtraControl(iop_base,
11424 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11425 }
11426
11427 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
11428#ifdef CONFIG_ISA
11429 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
11430 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
11431 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
11432 asc_dvc->bus_type = ASC_IS_ISAPNP;
11433 }
11434 asc_dvc->cfg->isa_dma_channel =
11435 (uchar)AscGetIsaDmaChannel(iop_base);
11436 }
11437#endif /* CONFIG_ISA */
11438 for (i = 0; i <= ASC_MAX_TID; i++) {
11439 asc_dvc->cur_dvc_qng[i] = 0;
11440 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
11441 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
11442 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
11443 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
11444 }
11445 return warn_code;
11446}
11447
11448static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
11449{
11450 int retry;
11451
11452 for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) {
11453 unsigned char read_back;
11454 AscSetChipEEPCmd(iop_base, cmd_reg);
11455 mdelay(1);
11456 read_back = AscGetChipEEPCmd(iop_base);
11457 if (read_back == cmd_reg)
11458 return 1;
11459 }
11460 return 0;
11461}
11462
11463static void __devinit AscWaitEEPRead(void)
11464{
11465 mdelay(1);
11466}
11467
11468static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
11469{
11470 ushort read_wval;
11471 uchar cmd_reg;
11472
11473 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11474 AscWaitEEPRead();
11475 cmd_reg = addr | ASC_EEP_CMD_READ;
11476 AscWriteEEPCmdReg(iop_base, cmd_reg);
11477 AscWaitEEPRead();
11478 read_wval = AscGetChipEEPData(iop_base);
11479 AscWaitEEPRead();
11480 return read_wval;
11481}
11482
11483static ushort __devinit
11484AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11485{
11486 ushort wval;
11487 ushort sum;
11488 ushort *wbuf;
11489 int cfg_beg;
11490 int cfg_end;
11491 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11492 int s_addr;
11493
11494 wbuf = (ushort *)cfg_buf;
11495 sum = 0;
11496 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
11497 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11498 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11499 sum += *wbuf;
11500 }
11501 if (bus_type & ASC_IS_VL) {
11502 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11503 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11504 } else {
11505 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11506 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11507 }
11508 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11509 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11510 if (s_addr <= uchar_end_in_config) {
11511 /*
11512 * Swap all char fields - must unswap bytes already swapped
11513 * by AscReadEEPWord().
11514 */
11515 *wbuf = le16_to_cpu(wval);
11516 } else {
11517 /* Don't swap word field at the end - cntl field. */
11518 *wbuf = wval;
11519 }
11520 sum += wval; /* Checksum treats all EEPROM data as words. */
11521 }
11522 /*
11523 * Read the checksum word which will be compared against 'sum'
11524 * by the caller. Word field already swapped.
11525 */
11526 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11527 return sum;
11528}
11529
11530static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
11531{
11532 PortAddr iop_base;
11533 ushort q_addr;
11534 ushort saved_word;
11535 int sta;
11536
11537 iop_base = asc_dvc->iop_base;
11538 sta = 0;
11539 q_addr = ASC_QNO_TO_QADDR(241);
11540 saved_word = AscReadLramWord(iop_base, q_addr);
11541 AscSetChipLramAddr(iop_base, q_addr);
11542 AscSetChipLramData(iop_base, 0x55AA);
11543 mdelay(10);
11544 AscSetChipLramAddr(iop_base, q_addr);
11545 if (AscGetChipLramData(iop_base) == 0x55AA) {
11546 sta = 1;
11547 AscWriteLramWord(iop_base, q_addr, saved_word);
11548 }
11549 return (sta);
11550}
11551
11552static void __devinit AscWaitEEPWrite(void)
11553{
11554 mdelay(20);
Matthew Wilcox51219352007-10-02 21:55:22 -040011555}
11556
11557static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
11558{
11559 ushort read_back;
11560 int retry;
11561
11562 retry = 0;
11563 while (TRUE) {
11564 AscSetChipEEPData(iop_base, data_reg);
11565 mdelay(1);
11566 read_back = AscGetChipEEPData(iop_base);
11567 if (read_back == data_reg) {
11568 return (1);
11569 }
11570 if (retry++ > ASC_EEP_MAX_RETRY) {
11571 return (0);
11572 }
11573 }
11574}
11575
11576static ushort __devinit
11577AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
11578{
11579 ushort read_wval;
11580
11581 read_wval = AscReadEEPWord(iop_base, addr);
11582 if (read_wval != word_val) {
11583 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
11584 AscWaitEEPRead();
11585 AscWriteEEPDataReg(iop_base, word_val);
11586 AscWaitEEPRead();
11587 AscWriteEEPCmdReg(iop_base,
11588 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
11589 AscWaitEEPWrite();
11590 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11591 AscWaitEEPRead();
11592 return (AscReadEEPWord(iop_base, addr));
11593 }
11594 return (read_wval);
11595}
11596
11597static int __devinit
11598AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11599{
11600 int n_error;
11601 ushort *wbuf;
11602 ushort word;
11603 ushort sum;
11604 int s_addr;
11605 int cfg_beg;
11606 int cfg_end;
11607 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11608
11609 wbuf = (ushort *)cfg_buf;
11610 n_error = 0;
11611 sum = 0;
11612 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11613 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11614 sum += *wbuf;
11615 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11616 n_error++;
11617 }
11618 }
11619 if (bus_type & ASC_IS_VL) {
11620 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11621 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11622 } else {
11623 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11624 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11625 }
11626 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11627 if (s_addr <= uchar_end_in_config) {
11628 /*
11629 * This is a char field. Swap char fields before they are
11630 * swapped again by AscWriteEEPWord().
11631 */
11632 word = cpu_to_le16(*wbuf);
11633 if (word !=
11634 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11635 n_error++;
11636 }
11637 } else {
11638 /* Don't swap word field at the end - cntl field. */
11639 if (*wbuf !=
11640 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11641 n_error++;
11642 }
11643 }
11644 sum += *wbuf; /* Checksum calculated from word values. */
11645 }
11646 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11647 *wbuf = sum;
11648 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11649 n_error++;
11650 }
11651
11652 /* Read EEPROM back again. */
11653 wbuf = (ushort *)cfg_buf;
11654 /*
11655 * Read two config words; Byte-swapping done by AscReadEEPWord().
11656 */
11657 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11658 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11659 n_error++;
11660 }
11661 }
11662 if (bus_type & ASC_IS_VL) {
11663 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11664 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11665 } else {
11666 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11667 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11668 }
11669 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11670 if (s_addr <= uchar_end_in_config) {
11671 /*
11672 * Swap all char fields. Must unswap bytes already swapped
11673 * by AscReadEEPWord().
11674 */
11675 word =
11676 le16_to_cpu(AscReadEEPWord
11677 (iop_base, (uchar)s_addr));
11678 } else {
11679 /* Don't swap word field at the end - cntl field. */
11680 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11681 }
11682 if (*wbuf != word) {
11683 n_error++;
11684 }
11685 }
11686 /* Read checksum; Byte swapping not needed. */
11687 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11688 n_error++;
11689 }
11690 return n_error;
11691}
11692
11693static int __devinit
11694AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11695{
11696 int retry;
11697 int n_error;
11698
11699 retry = 0;
11700 while (TRUE) {
11701 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
11702 bus_type)) == 0) {
11703 break;
11704 }
11705 if (++retry > ASC_EEP_MAX_RETRY) {
11706 break;
11707 }
11708 }
11709 return n_error;
11710}
11711
11712static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
11713{
11714 ASCEEP_CONFIG eep_config_buf;
11715 ASCEEP_CONFIG *eep_config;
11716 PortAddr iop_base;
11717 ushort chksum;
11718 ushort warn_code;
11719 ushort cfg_msw, cfg_lsw;
11720 int i;
11721 int write_eep = 0;
11722
11723 iop_base = asc_dvc->iop_base;
11724 warn_code = 0;
11725 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
11726 AscStopQueueExe(iop_base);
11727 if ((AscStopChip(iop_base) == FALSE) ||
11728 (AscGetChipScsiCtrl(iop_base) != 0)) {
11729 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
11730 AscResetChipAndScsiBus(asc_dvc);
11731 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
11732 }
11733 if (AscIsChipHalted(iop_base) == FALSE) {
11734 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
11735 return (warn_code);
11736 }
11737 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11738 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11739 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
11740 return (warn_code);
11741 }
11742 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
11743 cfg_msw = AscGetChipCfgMsw(iop_base);
11744 cfg_lsw = AscGetChipCfgLsw(iop_base);
11745 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
11746 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11747 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
11748 AscSetChipCfgMsw(iop_base, cfg_msw);
11749 }
11750 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011751 ASC_DBG(1, "chksum 0x%x\n", chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -040011752 if (chksum == 0) {
11753 chksum = 0xaa55;
11754 }
11755 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
11756 warn_code |= ASC_WARN_AUTO_CONFIG;
11757 if (asc_dvc->cfg->chip_version == 3) {
11758 if (eep_config->cfg_lsw != cfg_lsw) {
11759 warn_code |= ASC_WARN_EEPROM_RECOVER;
11760 eep_config->cfg_lsw =
11761 AscGetChipCfgLsw(iop_base);
11762 }
11763 if (eep_config->cfg_msw != cfg_msw) {
11764 warn_code |= ASC_WARN_EEPROM_RECOVER;
11765 eep_config->cfg_msw =
11766 AscGetChipCfgMsw(iop_base);
11767 }
11768 }
11769 }
11770 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11771 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011772 ASC_DBG(1, "eep_config->chksum 0x%x\n", eep_config->chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -040011773 if (chksum != eep_config->chksum) {
11774 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
11775 ASC_CHIP_VER_PCI_ULTRA_3050) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011776 ASC_DBG(1, "chksum error ignored; EEPROM-less board\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011777 eep_config->init_sdtr = 0xFF;
11778 eep_config->disc_enable = 0xFF;
11779 eep_config->start_motor = 0xFF;
11780 eep_config->use_cmd_qng = 0;
11781 eep_config->max_total_qng = 0xF0;
11782 eep_config->max_tag_qng = 0x20;
11783 eep_config->cntl = 0xBFFF;
11784 ASC_EEP_SET_CHIP_ID(eep_config, 7);
11785 eep_config->no_scam = 0;
11786 eep_config->adapter_info[0] = 0;
11787 eep_config->adapter_info[1] = 0;
11788 eep_config->adapter_info[2] = 0;
11789 eep_config->adapter_info[3] = 0;
11790 eep_config->adapter_info[4] = 0;
11791 /* Indicate EEPROM-less board. */
11792 eep_config->adapter_info[5] = 0xBB;
11793 } else {
11794 ASC_PRINT
11795 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
11796 write_eep = 1;
11797 warn_code |= ASC_WARN_EEPROM_CHKSUM;
11798 }
11799 }
11800 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
11801 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
11802 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
11803 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
11804 asc_dvc->start_motor = eep_config->start_motor;
11805 asc_dvc->dvc_cntl = eep_config->cntl;
11806 asc_dvc->no_scam = eep_config->no_scam;
11807 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
11808 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
11809 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
11810 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
11811 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
11812 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
11813 if (!AscTestExternalLram(asc_dvc)) {
11814 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
11815 ASC_IS_PCI_ULTRA)) {
11816 eep_config->max_total_qng =
11817 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
11818 eep_config->max_tag_qng =
11819 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
11820 } else {
11821 eep_config->cfg_msw |= 0x0800;
11822 cfg_msw |= 0x0800;
11823 AscSetChipCfgMsw(iop_base, cfg_msw);
11824 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
11825 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
11826 }
11827 } else {
11828 }
11829 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
11830 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
11831 }
11832 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
11833 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
11834 }
11835 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
11836 eep_config->max_tag_qng = eep_config->max_total_qng;
11837 }
11838 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
11839 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
11840 }
11841 asc_dvc->max_total_qng = eep_config->max_total_qng;
11842 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
11843 eep_config->use_cmd_qng) {
11844 eep_config->disc_enable = eep_config->use_cmd_qng;
11845 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
11846 }
Matthew Wilcox51219352007-10-02 21:55:22 -040011847 ASC_EEP_SET_CHIP_ID(eep_config,
11848 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
11849 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
11850 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
11851 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -040011852 asc_dvc->min_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
Matthew Wilcox51219352007-10-02 21:55:22 -040011853 }
11854
11855 for (i = 0; i <= ASC_MAX_TID; i++) {
11856 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
11857 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
11858 asc_dvc->cfg->sdtr_period_offset[i] =
11859 (uchar)(ASC_DEF_SDTR_OFFSET |
Matthew Wilcoxafbb68c2007-10-02 21:55:36 -040011860 (asc_dvc->min_sdtr_index << 4));
Matthew Wilcox51219352007-10-02 21:55:22 -040011861 }
11862 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
11863 if (write_eep) {
11864 if ((i = AscSetEEPConfig(iop_base, eep_config,
11865 asc_dvc->bus_type)) != 0) {
11866 ASC_PRINT1
11867 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
11868 i);
11869 } else {
11870 ASC_PRINT
11871 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
11872 }
11873 }
11874 return (warn_code);
11875}
11876
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011877static int __devinit AscInitGetConfig(struct Scsi_Host *shost)
Matthew Wilcox51219352007-10-02 21:55:22 -040011878{
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011879 struct asc_board *board = shost_priv(shost);
11880 ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -040011881 unsigned short warn_code = 0;
11882
11883 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
11884 if (asc_dvc->err_code != 0)
11885 return asc_dvc->err_code;
11886
11887 if (AscFindSignature(asc_dvc->iop_base)) {
11888 warn_code |= AscInitAscDvcVar(asc_dvc);
11889 warn_code |= AscInitFromEEP(asc_dvc);
11890 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
11891 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
11892 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
11893 } else {
11894 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11895 }
11896
11897 switch (warn_code) {
11898 case 0: /* No error */
11899 break;
11900 case ASC_WARN_IO_PORT_ROTATE:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011901 shost_printk(KERN_WARNING, shost, "I/O port address "
11902 "modified\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011903 break;
11904 case ASC_WARN_AUTO_CONFIG:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011905 shost_printk(KERN_WARNING, shost, "I/O port increment switch "
11906 "enabled\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011907 break;
11908 case ASC_WARN_EEPROM_CHKSUM:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011909 shost_printk(KERN_WARNING, shost, "EEPROM checksum error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011910 break;
11911 case ASC_WARN_IRQ_MODIFIED:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011912 shost_printk(KERN_WARNING, shost, "IRQ modified\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011913 break;
11914 case ASC_WARN_CMD_QNG_CONFLICT:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011915 shost_printk(KERN_WARNING, shost, "tag queuing enabled w/o "
11916 "disconnects\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011917 break;
11918 default:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011919 shost_printk(KERN_WARNING, shost, "unknown warning: 0x%x\n",
11920 warn_code);
Matthew Wilcox51219352007-10-02 21:55:22 -040011921 break;
11922 }
11923
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011924 if (asc_dvc->err_code != 0)
11925 shost_printk(KERN_ERR, shost, "error 0x%x at init_state "
11926 "0x%x\n", asc_dvc->err_code, asc_dvc->init_state);
Matthew Wilcox51219352007-10-02 21:55:22 -040011927
11928 return asc_dvc->err_code;
11929}
11930
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011931static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
Matthew Wilcox51219352007-10-02 21:55:22 -040011932{
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011933 struct asc_board *board = shost_priv(shost);
11934 ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -040011935 PortAddr iop_base = asc_dvc->iop_base;
11936 unsigned short cfg_msw;
11937 unsigned short warn_code = 0;
11938
11939 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
11940 if (asc_dvc->err_code != 0)
11941 return asc_dvc->err_code;
11942 if (!AscFindSignature(asc_dvc->iop_base)) {
11943 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11944 return asc_dvc->err_code;
11945 }
11946
11947 cfg_msw = AscGetChipCfgMsw(iop_base);
11948 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
11949 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11950 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
11951 AscSetChipCfgMsw(iop_base, cfg_msw);
11952 }
11953 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
11954 asc_dvc->cfg->cmd_qng_enabled) {
11955 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
11956 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
11957 }
11958 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
11959 warn_code |= ASC_WARN_AUTO_CONFIG;
11960 }
Matthew Wilcox51219352007-10-02 21:55:22 -040011961#ifdef CONFIG_PCI
11962 if (asc_dvc->bus_type & ASC_IS_PCI) {
11963 cfg_msw &= 0xFFC0;
11964 AscSetChipCfgMsw(iop_base, cfg_msw);
11965 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
11966 } else {
11967 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
11968 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
11969 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
11970 asc_dvc->bug_fix_cntl |=
11971 ASC_BUG_FIX_ASYN_USE_SYN;
11972 }
11973 }
11974 } else
11975#endif /* CONFIG_PCI */
11976 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
11977 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
11978 == ASC_CHIP_VER_ASYN_BUG) {
11979 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
11980 }
11981 }
11982 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
11983 asc_dvc->cfg->chip_scsi_id) {
11984 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
11985 }
11986#ifdef CONFIG_ISA
11987 if (asc_dvc->bus_type & ASC_IS_ISA) {
11988 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
11989 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
11990 }
11991#endif /* CONFIG_ISA */
11992
11993 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
11994
11995 switch (warn_code) {
11996 case 0: /* No error. */
11997 break;
11998 case ASC_WARN_IO_PORT_ROTATE:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040011999 shost_printk(KERN_WARNING, shost, "I/O port address "
12000 "modified\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040012001 break;
12002 case ASC_WARN_AUTO_CONFIG:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040012003 shost_printk(KERN_WARNING, shost, "I/O port increment switch "
12004 "enabled\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040012005 break;
12006 case ASC_WARN_EEPROM_CHKSUM:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040012007 shost_printk(KERN_WARNING, shost, "EEPROM checksum error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040012008 break;
12009 case ASC_WARN_IRQ_MODIFIED:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040012010 shost_printk(KERN_WARNING, shost, "IRQ modified\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040012011 break;
12012 case ASC_WARN_CMD_QNG_CONFLICT:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040012013 shost_printk(KERN_WARNING, shost, "tag queuing w/o "
12014 "disconnects\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040012015 break;
12016 default:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040012017 shost_printk(KERN_WARNING, shost, "unknown warning: 0x%x\n",
12018 warn_code);
Matthew Wilcox51219352007-10-02 21:55:22 -040012019 break;
12020 }
12021
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040012022 if (asc_dvc->err_code != 0)
12023 shost_printk(KERN_ERR, shost, "error 0x%x at init_state "
12024 "0x%x\n", asc_dvc->err_code, asc_dvc->init_state);
Matthew Wilcox51219352007-10-02 21:55:22 -040012025
12026 return asc_dvc->err_code;
12027}
12028
12029/*
12030 * EEPROM Configuration.
12031 *
12032 * All drivers should use this structure to set the default EEPROM
12033 * configuration. The BIOS now uses this structure when it is built.
12034 * Additional structure information can be found in a_condor.h where
12035 * the structure is defined.
12036 *
12037 * The *_Field_IsChar structs are needed to correct for endianness.
12038 * These values are read from the board 16 bits at a time directly
12039 * into the structs. Because some fields are char, the values will be
12040 * in the wrong order. The *_Field_IsChar tells when to flip the
12041 * bytes. Data read and written to PCI memory is automatically swapped
12042 * on big-endian platforms so char fields read as words are actually being
12043 * unswapped on big-endian platforms.
12044 */
12045static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
12046 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
12047 0x0000, /* cfg_msw */
12048 0xFFFF, /* disc_enable */
12049 0xFFFF, /* wdtr_able */
12050 0xFFFF, /* sdtr_able */
12051 0xFFFF, /* start_motor */
12052 0xFFFF, /* tagqng_able */
12053 0xFFFF, /* bios_scan */
12054 0, /* scam_tolerant */
12055 7, /* adapter_scsi_id */
12056 0, /* bios_boot_delay */
12057 3, /* scsi_reset_delay */
12058 0, /* bios_id_lun */
12059 0, /* termination */
12060 0, /* reserved1 */
12061 0xFFE7, /* bios_ctrl */
12062 0xFFFF, /* ultra_able */
12063 0, /* reserved2 */
12064 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
12065 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12066 0, /* dvc_cntl */
12067 0, /* bug_fix */
12068 0, /* serial_number_word1 */
12069 0, /* serial_number_word2 */
12070 0, /* serial_number_word3 */
12071 0, /* check_sum */
12072 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12073 , /* oem_name[16] */
12074 0, /* dvc_err_code */
12075 0, /* adv_err_code */
12076 0, /* adv_err_addr */
12077 0, /* saved_dvc_err_code */
12078 0, /* saved_adv_err_code */
12079 0, /* saved_adv_err_addr */
12080 0 /* num_of_err */
12081};
12082
12083static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
12084 0, /* cfg_lsw */
12085 0, /* cfg_msw */
12086 0, /* -disc_enable */
12087 0, /* wdtr_able */
12088 0, /* sdtr_able */
12089 0, /* start_motor */
12090 0, /* tagqng_able */
12091 0, /* bios_scan */
12092 0, /* scam_tolerant */
12093 1, /* adapter_scsi_id */
12094 1, /* bios_boot_delay */
12095 1, /* scsi_reset_delay */
12096 1, /* bios_id_lun */
12097 1, /* termination */
12098 1, /* reserved1 */
12099 0, /* bios_ctrl */
12100 0, /* ultra_able */
12101 0, /* reserved2 */
12102 1, /* max_host_qng */
12103 1, /* max_dvc_qng */
12104 0, /* dvc_cntl */
12105 0, /* bug_fix */
12106 0, /* serial_number_word1 */
12107 0, /* serial_number_word2 */
12108 0, /* serial_number_word3 */
12109 0, /* check_sum */
12110 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12111 , /* oem_name[16] */
12112 0, /* dvc_err_code */
12113 0, /* adv_err_code */
12114 0, /* adv_err_addr */
12115 0, /* saved_dvc_err_code */
12116 0, /* saved_adv_err_code */
12117 0, /* saved_adv_err_addr */
12118 0 /* num_of_err */
12119};
12120
12121static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
12122 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12123 0x0000, /* 01 cfg_msw */
12124 0xFFFF, /* 02 disc_enable */
12125 0xFFFF, /* 03 wdtr_able */
12126 0x4444, /* 04 sdtr_speed1 */
12127 0xFFFF, /* 05 start_motor */
12128 0xFFFF, /* 06 tagqng_able */
12129 0xFFFF, /* 07 bios_scan */
12130 0, /* 08 scam_tolerant */
12131 7, /* 09 adapter_scsi_id */
12132 0, /* bios_boot_delay */
12133 3, /* 10 scsi_reset_delay */
12134 0, /* bios_id_lun */
12135 0, /* 11 termination_se */
12136 0, /* termination_lvd */
12137 0xFFE7, /* 12 bios_ctrl */
12138 0x4444, /* 13 sdtr_speed2 */
12139 0x4444, /* 14 sdtr_speed3 */
12140 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12141 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12142 0, /* 16 dvc_cntl */
12143 0x4444, /* 17 sdtr_speed4 */
12144 0, /* 18 serial_number_word1 */
12145 0, /* 19 serial_number_word2 */
12146 0, /* 20 serial_number_word3 */
12147 0, /* 21 check_sum */
12148 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12149 , /* 22-29 oem_name[16] */
12150 0, /* 30 dvc_err_code */
12151 0, /* 31 adv_err_code */
12152 0, /* 32 adv_err_addr */
12153 0, /* 33 saved_dvc_err_code */
12154 0, /* 34 saved_adv_err_code */
12155 0, /* 35 saved_adv_err_addr */
12156 0, /* 36 reserved */
12157 0, /* 37 reserved */
12158 0, /* 38 reserved */
12159 0, /* 39 reserved */
12160 0, /* 40 reserved */
12161 0, /* 41 reserved */
12162 0, /* 42 reserved */
12163 0, /* 43 reserved */
12164 0, /* 44 reserved */
12165 0, /* 45 reserved */
12166 0, /* 46 reserved */
12167 0, /* 47 reserved */
12168 0, /* 48 reserved */
12169 0, /* 49 reserved */
12170 0, /* 50 reserved */
12171 0, /* 51 reserved */
12172 0, /* 52 reserved */
12173 0, /* 53 reserved */
12174 0, /* 54 reserved */
12175 0, /* 55 reserved */
12176 0, /* 56 cisptr_lsw */
12177 0, /* 57 cisprt_msw */
12178 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12179 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
12180 0, /* 60 reserved */
12181 0, /* 61 reserved */
12182 0, /* 62 reserved */
12183 0 /* 63 reserved */
12184};
12185
12186static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
12187 0, /* 00 cfg_lsw */
12188 0, /* 01 cfg_msw */
12189 0, /* 02 disc_enable */
12190 0, /* 03 wdtr_able */
12191 0, /* 04 sdtr_speed1 */
12192 0, /* 05 start_motor */
12193 0, /* 06 tagqng_able */
12194 0, /* 07 bios_scan */
12195 0, /* 08 scam_tolerant */
12196 1, /* 09 adapter_scsi_id */
12197 1, /* bios_boot_delay */
12198 1, /* 10 scsi_reset_delay */
12199 1, /* bios_id_lun */
12200 1, /* 11 termination_se */
12201 1, /* termination_lvd */
12202 0, /* 12 bios_ctrl */
12203 0, /* 13 sdtr_speed2 */
12204 0, /* 14 sdtr_speed3 */
12205 1, /* 15 max_host_qng */
12206 1, /* max_dvc_qng */
12207 0, /* 16 dvc_cntl */
12208 0, /* 17 sdtr_speed4 */
12209 0, /* 18 serial_number_word1 */
12210 0, /* 19 serial_number_word2 */
12211 0, /* 20 serial_number_word3 */
12212 0, /* 21 check_sum */
12213 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12214 , /* 22-29 oem_name[16] */
12215 0, /* 30 dvc_err_code */
12216 0, /* 31 adv_err_code */
12217 0, /* 32 adv_err_addr */
12218 0, /* 33 saved_dvc_err_code */
12219 0, /* 34 saved_adv_err_code */
12220 0, /* 35 saved_adv_err_addr */
12221 0, /* 36 reserved */
12222 0, /* 37 reserved */
12223 0, /* 38 reserved */
12224 0, /* 39 reserved */
12225 0, /* 40 reserved */
12226 0, /* 41 reserved */
12227 0, /* 42 reserved */
12228 0, /* 43 reserved */
12229 0, /* 44 reserved */
12230 0, /* 45 reserved */
12231 0, /* 46 reserved */
12232 0, /* 47 reserved */
12233 0, /* 48 reserved */
12234 0, /* 49 reserved */
12235 0, /* 50 reserved */
12236 0, /* 51 reserved */
12237 0, /* 52 reserved */
12238 0, /* 53 reserved */
12239 0, /* 54 reserved */
12240 0, /* 55 reserved */
12241 0, /* 56 cisptr_lsw */
12242 0, /* 57 cisprt_msw */
12243 0, /* 58 subsysvid */
12244 0, /* 59 subsysid */
12245 0, /* 60 reserved */
12246 0, /* 61 reserved */
12247 0, /* 62 reserved */
12248 0 /* 63 reserved */
12249};
12250
12251static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
12252 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12253 0x0000, /* 01 cfg_msw */
12254 0xFFFF, /* 02 disc_enable */
12255 0xFFFF, /* 03 wdtr_able */
12256 0x5555, /* 04 sdtr_speed1 */
12257 0xFFFF, /* 05 start_motor */
12258 0xFFFF, /* 06 tagqng_able */
12259 0xFFFF, /* 07 bios_scan */
12260 0, /* 08 scam_tolerant */
12261 7, /* 09 adapter_scsi_id */
12262 0, /* bios_boot_delay */
12263 3, /* 10 scsi_reset_delay */
12264 0, /* bios_id_lun */
12265 0, /* 11 termination_se */
12266 0, /* termination_lvd */
12267 0xFFE7, /* 12 bios_ctrl */
12268 0x5555, /* 13 sdtr_speed2 */
12269 0x5555, /* 14 sdtr_speed3 */
12270 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12271 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12272 0, /* 16 dvc_cntl */
12273 0x5555, /* 17 sdtr_speed4 */
12274 0, /* 18 serial_number_word1 */
12275 0, /* 19 serial_number_word2 */
12276 0, /* 20 serial_number_word3 */
12277 0, /* 21 check_sum */
12278 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12279 , /* 22-29 oem_name[16] */
12280 0, /* 30 dvc_err_code */
12281 0, /* 31 adv_err_code */
12282 0, /* 32 adv_err_addr */
12283 0, /* 33 saved_dvc_err_code */
12284 0, /* 34 saved_adv_err_code */
12285 0, /* 35 saved_adv_err_addr */
12286 0, /* 36 reserved */
12287 0, /* 37 reserved */
12288 0, /* 38 reserved */
12289 0, /* 39 reserved */
12290 0, /* 40 reserved */
12291 0, /* 41 reserved */
12292 0, /* 42 reserved */
12293 0, /* 43 reserved */
12294 0, /* 44 reserved */
12295 0, /* 45 reserved */
12296 0, /* 46 reserved */
12297 0, /* 47 reserved */
12298 0, /* 48 reserved */
12299 0, /* 49 reserved */
12300 0, /* 50 reserved */
12301 0, /* 51 reserved */
12302 0, /* 52 reserved */
12303 0, /* 53 reserved */
12304 0, /* 54 reserved */
12305 0, /* 55 reserved */
12306 0, /* 56 cisptr_lsw */
12307 0, /* 57 cisprt_msw */
12308 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12309 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
12310 0, /* 60 reserved */
12311 0, /* 61 reserved */
12312 0, /* 62 reserved */
12313 0 /* 63 reserved */
12314};
12315
12316static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
12317 0, /* 00 cfg_lsw */
12318 0, /* 01 cfg_msw */
12319 0, /* 02 disc_enable */
12320 0, /* 03 wdtr_able */
12321 0, /* 04 sdtr_speed1 */
12322 0, /* 05 start_motor */
12323 0, /* 06 tagqng_able */
12324 0, /* 07 bios_scan */
12325 0, /* 08 scam_tolerant */
12326 1, /* 09 adapter_scsi_id */
12327 1, /* bios_boot_delay */
12328 1, /* 10 scsi_reset_delay */
12329 1, /* bios_id_lun */
12330 1, /* 11 termination_se */
12331 1, /* termination_lvd */
12332 0, /* 12 bios_ctrl */
12333 0, /* 13 sdtr_speed2 */
12334 0, /* 14 sdtr_speed3 */
12335 1, /* 15 max_host_qng */
12336 1, /* max_dvc_qng */
12337 0, /* 16 dvc_cntl */
12338 0, /* 17 sdtr_speed4 */
12339 0, /* 18 serial_number_word1 */
12340 0, /* 19 serial_number_word2 */
12341 0, /* 20 serial_number_word3 */
12342 0, /* 21 check_sum */
12343 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12344 , /* 22-29 oem_name[16] */
12345 0, /* 30 dvc_err_code */
12346 0, /* 31 adv_err_code */
12347 0, /* 32 adv_err_addr */
12348 0, /* 33 saved_dvc_err_code */
12349 0, /* 34 saved_adv_err_code */
12350 0, /* 35 saved_adv_err_addr */
12351 0, /* 36 reserved */
12352 0, /* 37 reserved */
12353 0, /* 38 reserved */
12354 0, /* 39 reserved */
12355 0, /* 40 reserved */
12356 0, /* 41 reserved */
12357 0, /* 42 reserved */
12358 0, /* 43 reserved */
12359 0, /* 44 reserved */
12360 0, /* 45 reserved */
12361 0, /* 46 reserved */
12362 0, /* 47 reserved */
12363 0, /* 48 reserved */
12364 0, /* 49 reserved */
12365 0, /* 50 reserved */
12366 0, /* 51 reserved */
12367 0, /* 52 reserved */
12368 0, /* 53 reserved */
12369 0, /* 54 reserved */
12370 0, /* 55 reserved */
12371 0, /* 56 cisptr_lsw */
12372 0, /* 57 cisprt_msw */
12373 0, /* 58 subsysvid */
12374 0, /* 59 subsysid */
12375 0, /* 60 reserved */
12376 0, /* 61 reserved */
12377 0, /* 62 reserved */
12378 0 /* 63 reserved */
12379};
12380
12381#ifdef CONFIG_PCI
12382/*
12383 * Wait for EEPROM command to complete
12384 */
12385static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
12386{
12387 int eep_delay_ms;
12388
12389 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
12390 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
12391 ASC_EEP_CMD_DONE) {
12392 break;
12393 }
12394 mdelay(1);
12395 }
12396 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
12397 0)
12398 BUG();
12399}
12400
12401/*
12402 * Read the EEPROM from specified location
12403 */
12404static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
12405{
12406 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12407 ASC_EEP_CMD_READ | eep_word_addr);
12408 AdvWaitEEPCmd(iop_base);
12409 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
12410}
12411
12412/*
12413 * Write the EEPROM from 'cfg_buf'.
12414 */
12415void __devinit
12416AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12417{
12418 ushort *wbuf;
12419 ushort addr, chksum;
12420 ushort *charfields;
12421
12422 wbuf = (ushort *)cfg_buf;
12423 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12424 chksum = 0;
12425
12426 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12427 AdvWaitEEPCmd(iop_base);
12428
12429 /*
12430 * Write EEPROM from word 0 to word 20.
12431 */
12432 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12433 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12434 ushort word;
12435
12436 if (*charfields++) {
12437 word = cpu_to_le16(*wbuf);
12438 } else {
12439 word = *wbuf;
12440 }
12441 chksum += *wbuf; /* Checksum is calculated from word values. */
12442 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12443 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12444 ASC_EEP_CMD_WRITE | addr);
12445 AdvWaitEEPCmd(iop_base);
12446 mdelay(ADV_EEP_DELAY_MS);
12447 }
12448
12449 /*
12450 * Write EEPROM checksum at word 21.
12451 */
12452 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12453 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12454 AdvWaitEEPCmd(iop_base);
12455 wbuf++;
12456 charfields++;
12457
12458 /*
12459 * Write EEPROM OEM name at words 22 to 29.
12460 */
12461 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12462 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12463 ushort word;
12464
12465 if (*charfields++) {
12466 word = cpu_to_le16(*wbuf);
12467 } else {
12468 word = *wbuf;
12469 }
12470 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12471 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12472 ASC_EEP_CMD_WRITE | addr);
12473 AdvWaitEEPCmd(iop_base);
12474 }
12475 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12476 AdvWaitEEPCmd(iop_base);
12477}
12478
12479/*
12480 * Write the EEPROM from 'cfg_buf'.
12481 */
12482void __devinit
12483AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12484{
12485 ushort *wbuf;
12486 ushort *charfields;
12487 ushort addr, chksum;
12488
12489 wbuf = (ushort *)cfg_buf;
12490 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12491 chksum = 0;
12492
12493 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12494 AdvWaitEEPCmd(iop_base);
12495
12496 /*
12497 * Write EEPROM from word 0 to word 20.
12498 */
12499 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12500 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12501 ushort word;
12502
12503 if (*charfields++) {
12504 word = cpu_to_le16(*wbuf);
12505 } else {
12506 word = *wbuf;
12507 }
12508 chksum += *wbuf; /* Checksum is calculated from word values. */
12509 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12510 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12511 ASC_EEP_CMD_WRITE | addr);
12512 AdvWaitEEPCmd(iop_base);
12513 mdelay(ADV_EEP_DELAY_MS);
12514 }
12515
12516 /*
12517 * Write EEPROM checksum at word 21.
12518 */
12519 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12520 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12521 AdvWaitEEPCmd(iop_base);
12522 wbuf++;
12523 charfields++;
12524
12525 /*
12526 * Write EEPROM OEM name at words 22 to 29.
12527 */
12528 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12529 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12530 ushort word;
12531
12532 if (*charfields++) {
12533 word = cpu_to_le16(*wbuf);
12534 } else {
12535 word = *wbuf;
12536 }
12537 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12538 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12539 ASC_EEP_CMD_WRITE | addr);
12540 AdvWaitEEPCmd(iop_base);
12541 }
12542 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12543 AdvWaitEEPCmd(iop_base);
12544}
12545
12546/*
12547 * Write the EEPROM from 'cfg_buf'.
12548 */
12549void __devinit
12550AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12551{
12552 ushort *wbuf;
12553 ushort *charfields;
12554 ushort addr, chksum;
12555
12556 wbuf = (ushort *)cfg_buf;
12557 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12558 chksum = 0;
12559
12560 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12561 AdvWaitEEPCmd(iop_base);
12562
12563 /*
12564 * Write EEPROM from word 0 to word 20.
12565 */
12566 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12567 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12568 ushort word;
12569
12570 if (*charfields++) {
12571 word = cpu_to_le16(*wbuf);
12572 } else {
12573 word = *wbuf;
12574 }
12575 chksum += *wbuf; /* Checksum is calculated from word values. */
12576 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12577 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12578 ASC_EEP_CMD_WRITE | addr);
12579 AdvWaitEEPCmd(iop_base);
12580 mdelay(ADV_EEP_DELAY_MS);
12581 }
12582
12583 /*
12584 * Write EEPROM checksum at word 21.
12585 */
12586 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12587 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12588 AdvWaitEEPCmd(iop_base);
12589 wbuf++;
12590 charfields++;
12591
12592 /*
12593 * Write EEPROM OEM name at words 22 to 29.
12594 */
12595 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12596 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12597 ushort word;
12598
12599 if (*charfields++) {
12600 word = cpu_to_le16(*wbuf);
12601 } else {
12602 word = *wbuf;
12603 }
12604 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12605 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12606 ASC_EEP_CMD_WRITE | addr);
12607 AdvWaitEEPCmd(iop_base);
12608 }
12609 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12610 AdvWaitEEPCmd(iop_base);
12611}
12612
12613/*
12614 * Read EEPROM configuration into the specified buffer.
12615 *
12616 * Return a checksum based on the EEPROM configuration read.
12617 */
12618static ushort __devinit
12619AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12620{
12621 ushort wval, chksum;
12622 ushort *wbuf;
12623 int eep_addr;
12624 ushort *charfields;
12625
12626 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12627 wbuf = (ushort *)cfg_buf;
12628 chksum = 0;
12629
12630 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12631 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12632 wval = AdvReadEEPWord(iop_base, eep_addr);
12633 chksum += wval; /* Checksum is calculated from word values. */
12634 if (*charfields++) {
12635 *wbuf = le16_to_cpu(wval);
12636 } else {
12637 *wbuf = wval;
12638 }
12639 }
12640 /* Read checksum word. */
12641 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12642 wbuf++;
12643 charfields++;
12644
12645 /* Read rest of EEPROM not covered by the checksum. */
12646 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12647 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12648 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12649 if (*charfields++) {
12650 *wbuf = le16_to_cpu(*wbuf);
12651 }
12652 }
12653 return chksum;
12654}
12655
12656/*
12657 * Read EEPROM configuration into the specified buffer.
12658 *
12659 * Return a checksum based on the EEPROM configuration read.
12660 */
12661static ushort __devinit
12662AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12663{
12664 ushort wval, chksum;
12665 ushort *wbuf;
12666 int eep_addr;
12667 ushort *charfields;
12668
12669 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12670 wbuf = (ushort *)cfg_buf;
12671 chksum = 0;
12672
12673 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12674 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12675 wval = AdvReadEEPWord(iop_base, eep_addr);
12676 chksum += wval; /* Checksum is calculated from word values. */
12677 if (*charfields++) {
12678 *wbuf = le16_to_cpu(wval);
12679 } else {
12680 *wbuf = wval;
12681 }
12682 }
12683 /* Read checksum word. */
12684 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12685 wbuf++;
12686 charfields++;
12687
12688 /* Read rest of EEPROM not covered by the checksum. */
12689 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12690 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12691 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12692 if (*charfields++) {
12693 *wbuf = le16_to_cpu(*wbuf);
12694 }
12695 }
12696 return chksum;
12697}
12698
12699/*
12700 * Read EEPROM configuration into the specified buffer.
12701 *
12702 * Return a checksum based on the EEPROM configuration read.
12703 */
12704static ushort __devinit
12705AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12706{
12707 ushort wval, chksum;
12708 ushort *wbuf;
12709 int eep_addr;
12710 ushort *charfields;
12711
12712 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12713 wbuf = (ushort *)cfg_buf;
12714 chksum = 0;
12715
12716 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12717 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12718 wval = AdvReadEEPWord(iop_base, eep_addr);
12719 chksum += wval; /* Checksum is calculated from word values. */
12720 if (*charfields++) {
12721 *wbuf = le16_to_cpu(wval);
12722 } else {
12723 *wbuf = wval;
12724 }
12725 }
12726 /* Read checksum word. */
12727 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12728 wbuf++;
12729 charfields++;
12730
12731 /* Read rest of EEPROM not covered by the checksum. */
12732 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12733 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12734 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12735 if (*charfields++) {
12736 *wbuf = le16_to_cpu(*wbuf);
12737 }
12738 }
12739 return chksum;
12740}
12741
12742/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070012743 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12744 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12745 * all of this is done.
12746 *
12747 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12748 *
12749 * For a non-fatal error return a warning code. If there are no warnings
12750 * then 0 is returned.
12751 *
12752 * Note: Chip is stopped on entry.
12753 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012754static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012755{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012756 AdvPortAddr iop_base;
12757 ushort warn_code;
12758 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012759
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012760 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012761
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012762 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012763
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012764 /*
12765 * Read the board's EEPROM configuration.
12766 *
12767 * Set default values if a bad checksum is found.
12768 */
12769 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12770 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012772 /*
12773 * Set EEPROM default values.
12774 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012775 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12776 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012777
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012778 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012779 * Assume the 6 byte board serial number that was read from
12780 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012781 */
12782 eep_config.serial_number_word3 =
12783 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012784
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012785 eep_config.serial_number_word2 =
12786 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012787
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012788 eep_config.serial_number_word1 =
12789 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012790
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012791 AdvSet3550EEPConfig(iop_base, &eep_config);
12792 }
12793 /*
12794 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
12795 * EEPROM configuration that was read.
12796 *
12797 * This is the mapping of EEPROM fields to Adv Library fields.
12798 */
12799 asc_dvc->wdtr_able = eep_config.wdtr_able;
12800 asc_dvc->sdtr_able = eep_config.sdtr_able;
12801 asc_dvc->ultra_able = eep_config.ultra_able;
12802 asc_dvc->tagqng_able = eep_config.tagqng_able;
12803 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
12804 asc_dvc->max_host_qng = eep_config.max_host_qng;
12805 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
12806 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
12807 asc_dvc->start_motor = eep_config.start_motor;
12808 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
12809 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
12810 asc_dvc->no_scam = eep_config.scam_tolerant;
12811 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
12812 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
12813 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012814
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012815 /*
12816 * Set the host maximum queuing (max. 253, min. 16) and the per device
12817 * maximum queuing (max. 63, min. 4).
12818 */
12819 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
12820 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12821 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
12822 /* If the value is zero, assume it is uninitialized. */
12823 if (eep_config.max_host_qng == 0) {
12824 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12825 } else {
12826 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
12827 }
12828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012829
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012830 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
12831 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12832 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
12833 /* If the value is zero, assume it is uninitialized. */
12834 if (eep_config.max_dvc_qng == 0) {
12835 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12836 } else {
12837 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
12838 }
12839 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012841 /*
12842 * If 'max_dvc_qng' is greater than 'max_host_qng', then
12843 * set 'max_dvc_qng' to 'max_host_qng'.
12844 */
12845 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
12846 eep_config.max_dvc_qng = eep_config.max_host_qng;
12847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012848
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012849 /*
12850 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
12851 * values based on possibly adjusted EEPROM values.
12852 */
12853 asc_dvc->max_host_qng = eep_config.max_host_qng;
12854 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012855
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012856 /*
12857 * If the EEPROM 'termination' field is set to automatic (0), then set
12858 * the ADV_DVC_CFG 'termination' field to automatic also.
12859 *
12860 * If the termination is specified with a non-zero 'termination'
12861 * value check that a legal value is set and set the ADV_DVC_CFG
12862 * 'termination' field appropriately.
12863 */
12864 if (eep_config.termination == 0) {
12865 asc_dvc->cfg->termination = 0; /* auto termination */
12866 } else {
12867 /* Enable manual control with low off / high off. */
12868 if (eep_config.termination == 1) {
12869 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012870
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012871 /* Enable manual control with low off / high on. */
12872 } else if (eep_config.termination == 2) {
12873 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012874
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012875 /* Enable manual control with low on / high on. */
12876 } else if (eep_config.termination == 3) {
12877 asc_dvc->cfg->termination =
12878 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
12879 } else {
12880 /*
12881 * The EEPROM 'termination' field contains a bad value. Use
12882 * automatic termination instead.
12883 */
12884 asc_dvc->cfg->termination = 0;
12885 warn_code |= ASC_WARN_EEPROM_TERMINATION;
12886 }
12887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012888
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012889 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012890}
12891
12892/*
12893 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12894 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12895 * all of this is done.
12896 *
12897 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12898 *
12899 * For a non-fatal error return a warning code. If there are no warnings
12900 * then 0 is returned.
12901 *
12902 * Note: Chip is stopped on entry.
12903 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012904static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012905{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012906 AdvPortAddr iop_base;
12907 ushort warn_code;
12908 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012909 uchar tid, termination;
12910 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012911
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012912 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012913
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012914 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012915
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012916 /*
12917 * Read the board's EEPROM configuration.
12918 *
12919 * Set default values if a bad checksum is found.
12920 */
12921 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
12922 eep_config.check_sum) {
12923 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012924
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012925 /*
12926 * Set EEPROM default values.
12927 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012928 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
12929 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012930
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012931 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012932 * Assume the 6 byte board serial number that was read from
12933 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012934 */
12935 eep_config.serial_number_word3 =
12936 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012937
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012938 eep_config.serial_number_word2 =
12939 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012940
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012941 eep_config.serial_number_word1 =
12942 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012943
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012944 AdvSet38C0800EEPConfig(iop_base, &eep_config);
12945 }
12946 /*
12947 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
12948 * EEPROM configuration that was read.
12949 *
12950 * This is the mapping of EEPROM fields to Adv Library fields.
12951 */
12952 asc_dvc->wdtr_able = eep_config.wdtr_able;
12953 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
12954 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
12955 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
12956 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
12957 asc_dvc->tagqng_able = eep_config.tagqng_able;
12958 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
12959 asc_dvc->max_host_qng = eep_config.max_host_qng;
12960 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
12961 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
12962 asc_dvc->start_motor = eep_config.start_motor;
12963 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
12964 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
12965 asc_dvc->no_scam = eep_config.scam_tolerant;
12966 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
12967 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
12968 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012969
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012970 /*
12971 * For every Target ID if any of its 'sdtr_speed[1234]' bits
12972 * are set, then set an 'sdtr_able' bit for it.
12973 */
12974 asc_dvc->sdtr_able = 0;
12975 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12976 if (tid == 0) {
12977 sdtr_speed = asc_dvc->sdtr_speed1;
12978 } else if (tid == 4) {
12979 sdtr_speed = asc_dvc->sdtr_speed2;
12980 } else if (tid == 8) {
12981 sdtr_speed = asc_dvc->sdtr_speed3;
12982 } else if (tid == 12) {
12983 sdtr_speed = asc_dvc->sdtr_speed4;
12984 }
12985 if (sdtr_speed & ADV_MAX_TID) {
12986 asc_dvc->sdtr_able |= (1 << tid);
12987 }
12988 sdtr_speed >>= 4;
12989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012991 /*
12992 * Set the host maximum queuing (max. 253, min. 16) and the per device
12993 * maximum queuing (max. 63, min. 4).
12994 */
12995 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
12996 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12997 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
12998 /* If the value is zero, assume it is uninitialized. */
12999 if (eep_config.max_host_qng == 0) {
13000 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13001 } else {
13002 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13003 }
13004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013005
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013006 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13007 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13008 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13009 /* If the value is zero, assume it is uninitialized. */
13010 if (eep_config.max_dvc_qng == 0) {
13011 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13012 } else {
13013 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13014 }
13015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013016
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013017 /*
13018 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13019 * set 'max_dvc_qng' to 'max_host_qng'.
13020 */
13021 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13022 eep_config.max_dvc_qng = eep_config.max_host_qng;
13023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013024
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013025 /*
13026 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13027 * values based on possibly adjusted EEPROM values.
13028 */
13029 asc_dvc->max_host_qng = eep_config.max_host_qng;
13030 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013031
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013032 /*
13033 * If the EEPROM 'termination' field is set to automatic (0), then set
13034 * the ADV_DVC_CFG 'termination' field to automatic also.
13035 *
13036 * If the termination is specified with a non-zero 'termination'
13037 * value check that a legal value is set and set the ADV_DVC_CFG
13038 * 'termination' field appropriately.
13039 */
13040 if (eep_config.termination_se == 0) {
13041 termination = 0; /* auto termination for SE */
13042 } else {
13043 /* Enable manual control with low off / high off. */
13044 if (eep_config.termination_se == 1) {
13045 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013046
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013047 /* Enable manual control with low off / high on. */
13048 } else if (eep_config.termination_se == 2) {
13049 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013050
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013051 /* Enable manual control with low on / high on. */
13052 } else if (eep_config.termination_se == 3) {
13053 termination = TERM_SE;
13054 } else {
13055 /*
13056 * The EEPROM 'termination_se' field contains a bad value.
13057 * Use automatic termination instead.
13058 */
13059 termination = 0;
13060 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13061 }
13062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013063
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013064 if (eep_config.termination_lvd == 0) {
13065 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13066 } else {
13067 /* Enable manual control with low off / high off. */
13068 if (eep_config.termination_lvd == 1) {
13069 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013070
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013071 /* Enable manual control with low off / high on. */
13072 } else if (eep_config.termination_lvd == 2) {
13073 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013074
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013075 /* Enable manual control with low on / high on. */
13076 } else if (eep_config.termination_lvd == 3) {
13077 asc_dvc->cfg->termination = termination | TERM_LVD;
13078 } else {
13079 /*
13080 * The EEPROM 'termination_lvd' field contains a bad value.
13081 * Use automatic termination instead.
13082 */
13083 asc_dvc->cfg->termination = termination;
13084 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13085 }
13086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013087
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013088 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013089}
13090
13091/*
13092 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13093 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13094 * all of this is done.
13095 *
13096 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13097 *
13098 * For a non-fatal error return a warning code. If there are no warnings
13099 * then 0 is returned.
13100 *
13101 * Note: Chip is stopped on entry.
13102 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013103static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013104{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013105 AdvPortAddr iop_base;
13106 ushort warn_code;
13107 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013108 uchar tid, termination;
13109 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013111 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013112
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013113 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013114
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013115 /*
13116 * Read the board's EEPROM configuration.
13117 *
13118 * Set default values if a bad checksum is found.
13119 */
13120 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13121 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013122 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013123 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013124
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013125 /*
13126 * Set EEPROM default values.
13127 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013128 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13129 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013130
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013131 if (PCI_FUNC(pdev->devfn) != 0) {
13132 u8 ints;
13133 /*
13134 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13135 * and old Mac system booting problem. The Expansion
13136 * ROM must be disabled in Function 1 for these systems
13137 */
13138 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13139 /*
13140 * Clear the INTAB (bit 11) if the GPIO 0 input
13141 * indicates the Function 1 interrupt line is wired
13142 * to INTB.
13143 *
13144 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13145 * 1 - Function 1 interrupt line wired to INT A.
13146 * 0 - Function 1 interrupt line wired to INT B.
13147 *
13148 * Note: Function 0 is always wired to INTA.
13149 * Put all 5 GPIO bits in input mode and then read
13150 * their input values.
13151 */
13152 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13153 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13154 if ((ints & 0x01) == 0)
13155 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013157
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013158 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013159 * Assume the 6 byte board serial number that was read from
13160 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013161 */
13162 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013163 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013164 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013165 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013166 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013167 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013168
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013169 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013171
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013172 /*
13173 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13174 * EEPROM configuration that was read.
13175 *
13176 * This is the mapping of EEPROM fields to Adv Library fields.
13177 */
13178 asc_dvc->wdtr_able = eep_config.wdtr_able;
13179 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13180 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13181 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13182 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13183 asc_dvc->ppr_able = 0;
13184 asc_dvc->tagqng_able = eep_config.tagqng_able;
13185 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13186 asc_dvc->max_host_qng = eep_config.max_host_qng;
13187 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13188 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13189 asc_dvc->start_motor = eep_config.start_motor;
13190 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13191 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13192 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013193
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013194 /*
13195 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13196 * are set, then set an 'sdtr_able' bit for it.
13197 */
13198 asc_dvc->sdtr_able = 0;
13199 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13200 if (tid == 0) {
13201 sdtr_speed = asc_dvc->sdtr_speed1;
13202 } else if (tid == 4) {
13203 sdtr_speed = asc_dvc->sdtr_speed2;
13204 } else if (tid == 8) {
13205 sdtr_speed = asc_dvc->sdtr_speed3;
13206 } else if (tid == 12) {
13207 sdtr_speed = asc_dvc->sdtr_speed4;
13208 }
13209 if (sdtr_speed & ASC_MAX_TID) {
13210 asc_dvc->sdtr_able |= (1 << tid);
13211 }
13212 sdtr_speed >>= 4;
13213 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013214
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013215 /*
13216 * Set the host maximum queuing (max. 253, min. 16) and the per device
13217 * maximum queuing (max. 63, min. 4).
13218 */
13219 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13220 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13221 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13222 /* If the value is zero, assume it is uninitialized. */
13223 if (eep_config.max_host_qng == 0) {
13224 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13225 } else {
13226 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13227 }
13228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013229
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013230 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13231 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13232 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13233 /* If the value is zero, assume it is uninitialized. */
13234 if (eep_config.max_dvc_qng == 0) {
13235 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13236 } else {
13237 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13238 }
13239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013241 /*
13242 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13243 * set 'max_dvc_qng' to 'max_host_qng'.
13244 */
13245 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13246 eep_config.max_dvc_qng = eep_config.max_host_qng;
13247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013248
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013249 /*
13250 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13251 * values based on possibly adjusted EEPROM values.
13252 */
13253 asc_dvc->max_host_qng = eep_config.max_host_qng;
13254 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013255
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013256 /*
13257 * If the EEPROM 'termination' field is set to automatic (0), then set
13258 * the ASC_DVC_CFG 'termination' field to automatic also.
13259 *
13260 * If the termination is specified with a non-zero 'termination'
13261 * value check that a legal value is set and set the ASC_DVC_CFG
13262 * 'termination' field appropriately.
13263 */
13264 if (eep_config.termination_se == 0) {
13265 termination = 0; /* auto termination for SE */
13266 } else {
13267 /* Enable manual control with low off / high off. */
13268 if (eep_config.termination_se == 1) {
13269 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013270
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013271 /* Enable manual control with low off / high on. */
13272 } else if (eep_config.termination_se == 2) {
13273 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013274
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013275 /* Enable manual control with low on / high on. */
13276 } else if (eep_config.termination_se == 3) {
13277 termination = TERM_SE;
13278 } else {
13279 /*
13280 * The EEPROM 'termination_se' field contains a bad value.
13281 * Use automatic termination instead.
13282 */
13283 termination = 0;
13284 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13285 }
13286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013287
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013288 if (eep_config.termination_lvd == 0) {
13289 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13290 } else {
13291 /* Enable manual control with low off / high off. */
13292 if (eep_config.termination_lvd == 1) {
13293 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013294
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013295 /* Enable manual control with low off / high on. */
13296 } else if (eep_config.termination_lvd == 2) {
13297 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013298
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013299 /* Enable manual control with low on / high on. */
13300 } else if (eep_config.termination_lvd == 3) {
13301 asc_dvc->cfg->termination = termination | TERM_LVD;
13302 } else {
13303 /*
13304 * The EEPROM 'termination_lvd' field contains a bad value.
13305 * Use automatic termination instead.
13306 */
13307 asc_dvc->cfg->termination = termination;
13308 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13309 }
13310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013311
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013312 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013313}
13314
13315/*
Matthew Wilcox51219352007-10-02 21:55:22 -040013316 * Initialize the ADV_DVC_VAR structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013317 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013318 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013319 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013320 * For a non-fatal error return a warning code. If there are no warnings
13321 * then 0 is returned.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013322 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013323static int __devinit
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013324AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013325{
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013326 struct asc_board *board = shost_priv(shost);
13327 ADV_DVC_VAR *asc_dvc = &board->dvc_var.adv_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -040013328 unsigned short warn_code = 0;
13329 AdvPortAddr iop_base = asc_dvc->iop_base;
13330 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013331 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013332
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013333 asc_dvc->err_code = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040013334
13335 /*
13336 * Save the state of the PCI Configuration Command Register
13337 * "Parity Error Response Control" Bit. If the bit is clear (0),
13338 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13339 * DMA parity errors.
13340 */
13341 asc_dvc->cfg->control_flag = 0;
13342 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
13343 if ((cmd & PCI_COMMAND_PARITY) == 0)
13344 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
13345
Matthew Wilcox51219352007-10-02 21:55:22 -040013346 asc_dvc->cfg->chip_version =
13347 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
13348
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013349 ASC_DBG(1, "iopb_chip_id_1: 0x%x 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -040013350 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13351 (ushort)ADV_CHIP_ID_BYTE);
13352
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013353 ASC_DBG(1, "iopw_chip_id_0: 0x%x 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -040013354 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13355 (ushort)ADV_CHIP_ID_WORD);
13356
13357 /*
13358 * Reset the chip to start and allow register writes.
13359 */
13360 if (AdvFindSignature(iop_base) == 0) {
13361 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13362 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013363 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013364 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013365 * The caller must set 'chip_type' to a valid setting.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013366 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013367 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13368 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13369 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13370 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13371 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013374 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013375 * Reset Chip.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013376 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013377 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13378 ADV_CTRL_REG_CMD_RESET);
13379 mdelay(100);
13380 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13381 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013382
Matthew Wilcox51219352007-10-02 21:55:22 -040013383 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13384 status = AdvInitFrom38C1600EEP(asc_dvc);
13385 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13386 status = AdvInitFrom38C0800EEP(asc_dvc);
13387 } else {
13388 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013389 }
Matthew Wilcox51219352007-10-02 21:55:22 -040013390 warn_code |= status;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013392
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013393 if (warn_code != 0)
13394 shost_printk(KERN_WARNING, shost, "warning: 0x%x\n", warn_code);
Matthew Wilcox51219352007-10-02 21:55:22 -040013395
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013396 if (asc_dvc->err_code)
13397 shost_printk(KERN_ERR, shost, "error code 0x%x\n",
13398 asc_dvc->err_code);
Matthew Wilcox51219352007-10-02 21:55:22 -040013399
13400 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013401}
Matthew Wilcox51219352007-10-02 21:55:22 -040013402#endif
13403
13404static struct scsi_host_template advansys_template = {
13405 .proc_name = DRV_NAME,
13406#ifdef CONFIG_PROC_FS
13407 .proc_info = advansys_proc_info,
13408#endif
13409 .name = DRV_NAME,
13410 .info = advansys_info,
13411 .queuecommand = advansys_queuecommand,
13412 .eh_bus_reset_handler = advansys_reset,
13413 .bios_param = advansys_biosparam,
13414 .slave_configure = advansys_slave_configure,
13415 /*
13416 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
13417 * must be set. The flag will be cleared in advansys_board_found
13418 * for non-ISA adapters.
13419 */
13420 .unchecked_isa_dma = 1,
13421 /*
13422 * All adapters controlled by this driver are capable of large
13423 * scatter-gather lists. According to the mid-level SCSI documentation
13424 * this obviates any performance gain provided by setting
13425 * 'use_clustering'. But empirically while CPU utilization is increased
13426 * by enabling clustering, I/O throughput increases as well.
13427 */
13428 .use_clustering = ENABLE_CLUSTERING,
13429};
Linus Torvalds1da177e2005-04-16 15:20:36 -070013430
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013431static int __devinit advansys_wide_init_chip(struct Scsi_Host *shost)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013432{
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013433 struct asc_board *board = shost_priv(shost);
13434 struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013435 int req_cnt = 0;
13436 adv_req_t *reqp = NULL;
13437 int sg_cnt = 0;
13438 adv_sgblk_t *sgp;
13439 int warn_code, err_code;
13440
13441 /*
13442 * Allocate buffer carrier structures. The total size
13443 * is about 4 KB, so allocate all at once.
13444 */
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013445 board->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
13446 ASC_DBG(1, "carrp 0x%p\n", board->carrp);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013447
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013448 if (!board->carrp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013449 goto kmalloc_failed;
13450
13451 /*
13452 * Allocate up to 'max_host_qng' request structures for the Wide
13453 * board. The total size is about 16 KB, so allocate all at once.
13454 * If the allocation fails decrement and try again.
13455 */
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013456 for (req_cnt = adv_dvc->max_host_qng; req_cnt > 0; req_cnt--) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013457 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
13458
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013459 ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt,
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013460 (ulong)sizeof(adv_req_t) * req_cnt);
13461
13462 if (reqp)
13463 break;
13464 }
13465
13466 if (!reqp)
13467 goto kmalloc_failed;
13468
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013469 board->orig_reqp = reqp;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013470
13471 /*
13472 * Allocate up to ADV_TOT_SG_BLOCK request structures for
13473 * the Wide board. Each structure is about 136 bytes.
13474 */
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013475 board->adv_sgblkp = NULL;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013476 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
13477 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
13478
13479 if (!sgp)
13480 break;
13481
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013482 sgp->next_sgblkp = board->adv_sgblkp;
13483 board->adv_sgblkp = sgp;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013484
13485 }
13486
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013487 ASC_DBG(1, "sg_cnt %d * %u = %u bytes\n", sg_cnt, sizeof(adv_sgblk_t),
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013488 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
13489
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013490 if (!board->adv_sgblkp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013491 goto kmalloc_failed;
13492
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013493 adv_dvc->carrier_buf = board->carrp;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013494
13495 /*
13496 * Point 'adv_reqp' to the request structures and
13497 * link them together.
13498 */
13499 req_cnt--;
13500 reqp[req_cnt].next_reqp = NULL;
13501 for (; req_cnt > 0; req_cnt--) {
13502 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
13503 }
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013504 board->adv_reqp = &reqp[0];
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013505
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013506 if (adv_dvc->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013507 ASC_DBG(2, "AdvInitAsc3550Driver()\n");
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013508 warn_code = AdvInitAsc3550Driver(adv_dvc);
13509 } else if (adv_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013510 ASC_DBG(2, "AdvInitAsc38C0800Driver()\n");
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013511 warn_code = AdvInitAsc38C0800Driver(adv_dvc);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013512 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013513 ASC_DBG(2, "AdvInitAsc38C1600Driver()\n");
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013514 warn_code = AdvInitAsc38C1600Driver(adv_dvc);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013515 }
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013516 err_code = adv_dvc->err_code;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013517
13518 if (warn_code || err_code) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013519 shost_printk(KERN_WARNING, shost, "error: warn 0x%x, error "
13520 "0x%x\n", warn_code, err_code);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013521 }
13522
13523 goto exit;
13524
13525 kmalloc_failed:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013526 shost_printk(KERN_ERR, shost, "error: kmalloc() failed\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013527 err_code = ADV_ERROR;
13528 exit:
13529 return err_code;
13530}
13531
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013532static void advansys_wide_free_mem(struct asc_board *boardp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013533{
13534 kfree(boardp->carrp);
13535 boardp->carrp = NULL;
13536 kfree(boardp->orig_reqp);
13537 boardp->orig_reqp = boardp->adv_reqp = NULL;
13538 while (boardp->adv_sgblkp) {
13539 adv_sgblk_t *sgp = boardp->adv_sgblkp;
13540 boardp->adv_sgblkp = sgp->next_sgblkp;
13541 kfree(sgp);
13542 }
13543}
13544
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013545static int __devinit advansys_board_found(struct Scsi_Host *shost,
13546 unsigned int iop, int bus_type)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013547{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013548 struct pci_dev *pdev;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013549 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013550 ASC_DVC_VAR *asc_dvc_varp = NULL;
13551 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013552 int share_irq, warn_code, ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013553
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013554 pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013555
13556 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013557 ASC_DBG(1, "narrow board\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013558 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
13559 asc_dvc_varp->bus_type = bus_type;
13560 asc_dvc_varp->drv_ptr = boardp;
13561 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
13562 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
13563 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013564 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013565#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013566 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
13567 adv_dvc_varp->drv_ptr = boardp;
13568 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013569 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013570 ASC_DBG(1, "wide board ASC-3550\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013571 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
13572 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013573 ASC_DBG(1, "wide board ASC-38C0800\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013574 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
13575 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013576 ASC_DBG(1, "wide board ASC-38C1600\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013577 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
13578 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013579
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013580 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
13581 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
13582 boardp->asc_n_io_port);
13583 if (!boardp->ioremap_addr) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013584 shost_printk(KERN_ERR, shost, "ioremap(%x, %d) "
13585 "returned NULL\n",
13586 pci_resource_start(pdev, 1),
13587 boardp->asc_n_io_port);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013588 ret = -ENODEV;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013589 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013590 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013591 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr;
13592 ASC_DBG(1, "iop_base: 0x%p\n", adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013593
13594 /*
13595 * Even though it isn't used to access wide boards, other
13596 * than for the debug line below, save I/O Port address so
13597 * that it can be reported.
13598 */
13599 boardp->ioport = iop;
13600
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013601 ASC_DBG(1, "iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
13602 (ushort)inp(iop + 1), (ushort)inpw(iop));
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013603#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013604 }
13605
13606#ifdef CONFIG_PROC_FS
13607 /*
13608 * Allocate buffer for printing information from
13609 * /proc/scsi/advansys/[0...].
13610 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013611 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
13612 if (!boardp->prtbuf) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013613 shost_printk(KERN_ERR, shost, "kmalloc(%d) returned NULL\n",
13614 ASC_PRTBUF_SIZE);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013615 ret = -ENOMEM;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013616 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013617 }
13618#endif /* CONFIG_PROC_FS */
13619
13620 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013621 /*
13622 * Set the board bus type and PCI IRQ before
13623 * calling AscInitGetConfig().
13624 */
13625 switch (asc_dvc_varp->bus_type) {
13626#ifdef CONFIG_ISA
13627 case ASC_IS_ISA:
13628 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013629 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013630 break;
13631 case ASC_IS_VL:
13632 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013633 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013634 break;
13635 case ASC_IS_EISA:
13636 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013637 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013638 break;
13639#endif /* CONFIG_ISA */
13640#ifdef CONFIG_PCI
13641 case ASC_IS_PCI:
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013642 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013643 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013644 break;
13645#endif /* CONFIG_PCI */
13646 default:
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013647 shost_printk(KERN_ERR, shost, "unknown adapter type: "
13648 "%d\n", asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013649 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013650 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013651 break;
13652 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013653
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013654 /*
13655 * NOTE: AscInitGetConfig() may change the board's
13656 * bus_type value. The bus_type value should no
13657 * longer be used. If the bus_type field must be
13658 * referenced only use the bit-wise AND operator "&".
13659 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013660 ASC_DBG(2, "AscInitGetConfig()\n");
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013661 ret = AscInitGetConfig(shost) ? -ENODEV : 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013662 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013663#ifdef CONFIG_PCI
13664 /*
13665 * For Wide boards set PCI information before calling
13666 * AdvInitGetConfig().
13667 */
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013668 shost->unchecked_isa_dma = FALSE;
13669 share_irq = IRQF_SHARED;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013670 ASC_DBG(2, "AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040013671
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013672 ret = AdvInitGetConfig(pdev, shost) ? -ENODEV : 0;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013673#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013674 }
13675
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013676 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013677 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013678
13679 /*
13680 * Save the EEPROM configuration so that it can be displayed
13681 * from /proc/scsi/advansys/[0...].
13682 */
13683 if (ASC_NARROW_BOARD(boardp)) {
13684
13685 ASCEEP_CONFIG *ep;
13686
13687 /*
13688 * Set the adapter's target id bit in the 'init_tidmask' field.
13689 */
13690 boardp->init_tidmask |=
13691 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
13692
13693 /*
13694 * Save EEPROM settings for the board.
13695 */
13696 ep = &boardp->eep_config.asc_eep;
13697
13698 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
13699 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
13700 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
13701 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
13702 ep->start_motor = asc_dvc_varp->start_motor;
13703 ep->cntl = asc_dvc_varp->dvc_cntl;
13704 ep->no_scam = asc_dvc_varp->no_scam;
13705 ep->max_total_qng = asc_dvc_varp->max_total_qng;
13706 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
13707 /* 'max_tag_qng' is set to the same value for every device. */
13708 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
13709 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
13710 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
13711 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
13712 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
13713 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
13714 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
13715
13716 /*
13717 * Modify board configuration.
13718 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013719 ASC_DBG(2, "AscInitSetConfig()\n");
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013720 ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013721 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013722 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013723 } else {
13724 ADVEEP_3550_CONFIG *ep_3550;
13725 ADVEEP_38C0800_CONFIG *ep_38C0800;
13726 ADVEEP_38C1600_CONFIG *ep_38C1600;
13727
13728 /*
13729 * Save Wide EEP Configuration Information.
13730 */
13731 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
13732 ep_3550 = &boardp->eep_config.adv_3550_eep;
13733
13734 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
13735 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
13736 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13737 ep_3550->termination = adv_dvc_varp->cfg->termination;
13738 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
13739 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
13740 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
13741 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
13742 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
13743 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
13744 ep_3550->start_motor = adv_dvc_varp->start_motor;
13745 ep_3550->scsi_reset_delay =
13746 adv_dvc_varp->scsi_reset_wait;
13747 ep_3550->serial_number_word1 =
13748 adv_dvc_varp->cfg->serial1;
13749 ep_3550->serial_number_word2 =
13750 adv_dvc_varp->cfg->serial2;
13751 ep_3550->serial_number_word3 =
13752 adv_dvc_varp->cfg->serial3;
13753 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
13754 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
13755
13756 ep_38C0800->adapter_scsi_id =
13757 adv_dvc_varp->chip_scsi_id;
13758 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
13759 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13760 ep_38C0800->termination_lvd =
13761 adv_dvc_varp->cfg->termination;
13762 ep_38C0800->disc_enable =
13763 adv_dvc_varp->cfg->disc_enable;
13764 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
13765 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
13766 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
13767 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
13768 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
13769 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
13770 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
13771 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
13772 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
13773 ep_38C0800->scsi_reset_delay =
13774 adv_dvc_varp->scsi_reset_wait;
13775 ep_38C0800->serial_number_word1 =
13776 adv_dvc_varp->cfg->serial1;
13777 ep_38C0800->serial_number_word2 =
13778 adv_dvc_varp->cfg->serial2;
13779 ep_38C0800->serial_number_word3 =
13780 adv_dvc_varp->cfg->serial3;
13781 } else {
13782 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
13783
13784 ep_38C1600->adapter_scsi_id =
13785 adv_dvc_varp->chip_scsi_id;
13786 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
13787 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13788 ep_38C1600->termination_lvd =
13789 adv_dvc_varp->cfg->termination;
13790 ep_38C1600->disc_enable =
13791 adv_dvc_varp->cfg->disc_enable;
13792 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
13793 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
13794 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
13795 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
13796 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
13797 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
13798 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
13799 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
13800 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
13801 ep_38C1600->scsi_reset_delay =
13802 adv_dvc_varp->scsi_reset_wait;
13803 ep_38C1600->serial_number_word1 =
13804 adv_dvc_varp->cfg->serial1;
13805 ep_38C1600->serial_number_word2 =
13806 adv_dvc_varp->cfg->serial2;
13807 ep_38C1600->serial_number_word3 =
13808 adv_dvc_varp->cfg->serial3;
13809 }
13810
13811 /*
13812 * Set the adapter's target id bit in the 'init_tidmask' field.
13813 */
13814 boardp->init_tidmask |=
13815 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013816 }
13817
13818 /*
13819 * Channels are numbered beginning with 0. For AdvanSys one host
13820 * structure supports one channel. Multi-channel boards have a
13821 * separate host structure for each channel.
13822 */
13823 shost->max_channel = 0;
13824 if (ASC_NARROW_BOARD(boardp)) {
13825 shost->max_id = ASC_MAX_TID + 1;
13826 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060013827 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013828
13829 shost->io_port = asc_dvc_varp->iop_base;
13830 boardp->asc_n_io_port = ASC_IOADR_GAP;
13831 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
13832
13833 /* Set maximum number of queues the adapter can handle. */
13834 shost->can_queue = asc_dvc_varp->max_total_qng;
13835 } else {
13836 shost->max_id = ADV_MAX_TID + 1;
13837 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060013838 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013839
13840 /*
13841 * Save the I/O Port address and length even though
13842 * I/O ports are not used to access Wide boards.
13843 * Instead the Wide boards are accessed with
13844 * PCI Memory Mapped I/O.
13845 */
13846 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013847
13848 shost->this_id = adv_dvc_varp->chip_scsi_id;
13849
13850 /* Set maximum number of queues the adapter can handle. */
13851 shost->can_queue = adv_dvc_varp->max_host_qng;
13852 }
13853
13854 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013855 * Following v1.3.89, 'cmd_per_lun' is no longer needed
13856 * and should be set to zero.
13857 *
13858 * But because of a bug introduced in v1.3.89 if the driver is
13859 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
13860 * SCSI function 'allocate_device' will panic. To allow the driver
13861 * to work as a module in these kernels set 'cmd_per_lun' to 1.
13862 *
13863 * Note: This is wrong. cmd_per_lun should be set to the depth
13864 * you want on untagged devices always.
13865 #ifdef MODULE
13866 */
13867 shost->cmd_per_lun = 1;
13868/* #else
13869 shost->cmd_per_lun = 0;
13870#endif */
13871
13872 /*
13873 * Set the maximum number of scatter-gather elements the
13874 * adapter can handle.
13875 */
13876 if (ASC_NARROW_BOARD(boardp)) {
13877 /*
13878 * Allow two commands with 'sg_tablesize' scatter-gather
13879 * elements to be executed simultaneously. This value is
13880 * the theoretical hardware limit. It may be decreased
13881 * below.
13882 */
13883 shost->sg_tablesize =
13884 (((asc_dvc_varp->max_total_qng - 2) / 2) *
13885 ASC_SG_LIST_PER_Q) + 1;
13886 } else {
13887 shost->sg_tablesize = ADV_MAX_SG_LIST;
13888 }
13889
13890 /*
13891 * The value of 'sg_tablesize' can not exceed the SCSI
13892 * mid-level driver definition of SG_ALL. SG_ALL also
13893 * must not be exceeded, because it is used to define the
13894 * size of the scatter-gather table in 'struct asc_sg_head'.
13895 */
13896 if (shost->sg_tablesize > SG_ALL) {
13897 shost->sg_tablesize = SG_ALL;
13898 }
13899
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013900 ASC_DBG(1, "sg_tablesize: %d\n", shost->sg_tablesize);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013901
13902 /* BIOS start address. */
13903 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013904 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
13905 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013906 } else {
13907 /*
13908 * Fill-in BIOS board variables. The Wide BIOS saves
13909 * information in LRAM that is used by the driver.
13910 */
13911 AdvReadWordLram(adv_dvc_varp->iop_base,
13912 BIOS_SIGNATURE, boardp->bios_signature);
13913 AdvReadWordLram(adv_dvc_varp->iop_base,
13914 BIOS_VERSION, boardp->bios_version);
13915 AdvReadWordLram(adv_dvc_varp->iop_base,
13916 BIOS_CODESEG, boardp->bios_codeseg);
13917 AdvReadWordLram(adv_dvc_varp->iop_base,
13918 BIOS_CODELEN, boardp->bios_codelen);
13919
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013920 ASC_DBG(1, "bios_signature 0x%x, bios_version 0x%x\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013921 boardp->bios_signature, boardp->bios_version);
13922
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013923 ASC_DBG(1, "bios_codeseg 0x%x, bios_codelen 0x%x\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013924 boardp->bios_codeseg, boardp->bios_codelen);
13925
13926 /*
13927 * If the BIOS saved a valid signature, then fill in
13928 * the BIOS code segment base address.
13929 */
13930 if (boardp->bios_signature == 0x55AA) {
13931 /*
13932 * Convert x86 realmode code segment to a linear
13933 * address by shifting left 4.
13934 */
13935 shost->base = ((ulong)boardp->bios_codeseg << 4);
13936 } else {
13937 shost->base = 0;
13938 }
13939 }
13940
13941 /*
13942 * Register Board Resources - I/O Port, DMA, IRQ
13943 */
13944
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013945 /* Register DMA Channel for Narrow boards. */
13946 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
13947#ifdef CONFIG_ISA
13948 if (ASC_NARROW_BOARD(boardp)) {
13949 /* Register DMA channel for ISA bus. */
13950 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
13951 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060013952 ret = request_dma(shost->dma_channel, DRV_NAME);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013953 if (ret) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013954 shost_printk(KERN_ERR, shost, "request_dma() "
13955 "%d failed %d\n",
13956 shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060013957 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013958 }
13959 AscEnableIsaDma(shost->dma_channel);
13960 }
13961 }
13962#endif /* CONFIG_ISA */
13963
13964 /* Register IRQ Number. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013965 ASC_DBG(2, "request_irq(%d, %p)\n", boardp->irq, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013966
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013967 ret = request_irq(boardp->irq, advansys_interrupt, share_irq,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060013968 DRV_NAME, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013969
13970 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013971 if (ret == -EBUSY) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013972 shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x "
13973 "already in use\n", boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013974 } else if (ret == -EINVAL) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013975 shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x "
13976 "not valid\n", boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013977 } else {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013978 shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x "
13979 "failed with %d\n", boardp->irq, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013980 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013981 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013982 }
13983
13984 /*
13985 * Initialize board RISC chip and enable interrupts.
13986 */
13987 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013988 ASC_DBG(2, "AscInitAsc1000Driver()\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013989 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013990
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013991 if (warn_code || asc_dvc_varp->err_code) {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040013992 shost_printk(KERN_ERR, shost, "error: init_state 0x%x, "
13993 "warn 0x%x, error 0x%x\n",
13994 asc_dvc_varp->init_state, warn_code,
13995 asc_dvc_varp->err_code);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013996 if (asc_dvc_varp->err_code)
13997 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013998 }
13999 } else {
Matthew Wilcox9d0e96e2007-10-02 21:55:35 -040014000 if (advansys_wide_init_chip(shost))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014001 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014002 }
14003
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014004 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014005 goto err_free_wide_mem;
14006
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014007 ASC_DBG_PRT_SCSI_HOST(2, shost);
14008
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014009 ret = scsi_add_host(shost, boardp->dev);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014010 if (ret)
14011 goto err_free_wide_mem;
14012
14013 scsi_scan_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014014 return 0;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014015
14016 err_free_wide_mem:
14017 advansys_wide_free_mem(boardp);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014018 free_irq(boardp->irq, shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014019 err_free_dma:
14020 if (shost->dma_channel != NO_ISA_DMA)
14021 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014022 err_free_proc:
14023 kfree(boardp->prtbuf);
14024 err_unmap:
14025 if (boardp->ioremap_addr)
14026 iounmap(boardp->ioremap_addr);
14027 err_shost:
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014028 return ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014029}
14030
14031/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014032 * advansys_release()
14033 *
14034 * Release resources allocated for a single AdvanSys adapter.
14035 */
14036static int advansys_release(struct Scsi_Host *shost)
14037{
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014038 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014039 ASC_DBG(1, "begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014040 scsi_remove_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014041 free_irq(boardp->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014042 if (shost->dma_channel != NO_ISA_DMA) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014043 ASC_DBG(1, "free_dma()\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014044 free_dma(shost->dma_channel);
14045 }
Matthew Wilcox9a256fa2007-10-02 21:55:28 -040014046 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014047 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014048 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014049 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014050 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014051 scsi_host_put(shost);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014052 ASC_DBG(1, "end\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014053 return 0;
14054}
14055
Matthew Wilcox95c9f162007-09-09 08:56:39 -060014056#define ASC_IOADR_TABLE_MAX_IX 11
14057
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014058static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
14059 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
14060 0x0210, 0x0230, 0x0250, 0x0330
14061};
14062
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014063/*
14064 * The ISA IRQ number is found in bits 2 and 3 of the CfgLsw. It decodes as:
14065 * 00: 10
14066 * 01: 11
14067 * 10: 12
14068 * 11: 15
14069 */
14070static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
14071{
14072 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14073 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
14074 if (chip_irq == 13)
14075 chip_irq = 15;
14076 return chip_irq;
14077}
14078
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014079static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
14080{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014081 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014082 PortAddr iop_base = _asc_def_iop_base[id];
14083 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014084 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014085
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014086 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014087 ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014088 return -ENODEV;
14089 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014090 ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014091 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014092 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014093 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014094 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014095
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014096 err = -ENOMEM;
14097 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014098 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014099 goto release_region;
14100
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014101 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014102 board->irq = advansys_isa_irq_no(iop_base);
14103 board->dev = dev;
14104
14105 err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
14106 if (err)
14107 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014108
14109 dev_set_drvdata(dev, shost);
14110 return 0;
14111
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014112 free_host:
14113 scsi_host_put(shost);
14114 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014115 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014116 return err;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014117}
14118
14119static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
14120{
Matthew Wilcox71f36112007-07-30 08:04:53 -060014121 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014122 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014123 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014124 return 0;
14125}
14126
14127static struct isa_driver advansys_isa_driver = {
14128 .probe = advansys_isa_probe,
14129 .remove = __devexit_p(advansys_isa_remove),
14130 .driver = {
14131 .owner = THIS_MODULE,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014132 .name = DRV_NAME,
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014133 },
14134};
14135
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014136/*
14137 * The VLB IRQ number is found in bits 2 to 4 of the CfgLsw. It decodes as:
14138 * 000: invalid
14139 * 001: 10
14140 * 010: 11
14141 * 011: 12
14142 * 100: invalid
14143 * 101: 14
14144 * 110: 15
14145 * 111: invalid
14146 */
14147static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
14148{
14149 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14150 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
14151 if ((chip_irq < 10) || (chip_irq == 13) || (chip_irq > 15))
14152 return 0;
14153 return chip_irq;
14154}
14155
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014156static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
14157{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014158 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014159 PortAddr iop_base = _asc_def_iop_base[id];
14160 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014161 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014162
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014163 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014164 ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014165 return -ENODEV;
14166 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014167 ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014168 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014169 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014170 /*
14171 * I don't think this condition can actually happen, but the old
14172 * driver did it, and the chances of finding a VLB setup in 2007
14173 * to do testing with is slight to none.
14174 */
14175 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014176 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014177
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014178 err = -ENOMEM;
14179 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014180 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014181 goto release_region;
14182
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014183 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014184 board->irq = advansys_vlb_irq_no(iop_base);
14185 board->dev = dev;
14186
14187 err = advansys_board_found(shost, iop_base, ASC_IS_VL);
14188 if (err)
14189 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014190
14191 dev_set_drvdata(dev, shost);
14192 return 0;
14193
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014194 free_host:
14195 scsi_host_put(shost);
14196 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014197 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014198 return -ENODEV;
14199}
14200
14201static struct isa_driver advansys_vlb_driver = {
14202 .probe = advansys_vlb_probe,
14203 .remove = __devexit_p(advansys_isa_remove),
14204 .driver = {
14205 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060014206 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014207 },
14208};
14209
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014210static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
14211 { "ABP7401" },
14212 { "ABP7501" },
14213 { "" }
14214};
14215
14216MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
14217
14218/*
14219 * EISA is a little more tricky than PCI; each EISA device may have two
14220 * channels, and this driver is written to make each channel its own Scsi_Host
14221 */
14222struct eisa_scsi_data {
14223 struct Scsi_Host *host[2];
14224};
14225
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014226/*
14227 * The EISA IRQ number is found in bits 8 to 10 of the CfgLsw. It decodes as:
14228 * 000: 10
14229 * 001: 11
14230 * 010: 12
14231 * 011: invalid
14232 * 100: 14
14233 * 101: 15
14234 * 110: invalid
14235 * 111: invalid
14236 */
14237static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
14238{
14239 unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
14240 unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
14241 if ((chip_irq == 13) || (chip_irq > 15))
14242 return 0;
14243 return chip_irq;
14244}
14245
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014246static int __devinit advansys_eisa_probe(struct device *dev)
14247{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014248 int i, ioport, irq = 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014249 int err;
14250 struct eisa_device *edev = to_eisa_device(dev);
14251 struct eisa_scsi_data *data;
14252
14253 err = -ENOMEM;
14254 data = kzalloc(sizeof(*data), GFP_KERNEL);
14255 if (!data)
14256 goto fail;
14257 ioport = edev->base_addr + 0xc30;
14258
14259 err = -ENODEV;
14260 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014261 struct asc_board *board;
14262 struct Scsi_Host *shost;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014263 if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014264 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
14265 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014266 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014267 }
14268 if (!AscFindSignature(ioport)) {
14269 release_region(ioport, ASC_IOADR_GAP);
14270 continue;
14271 }
14272
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014273 /*
14274 * I don't know why we need to do this for EISA chips, but
14275 * not for any others. It looks to be equivalent to
14276 * AscGetChipCfgMsw, but I may have overlooked something,
14277 * so I'm not converting it until I get an EISA board to
14278 * test with.
14279 */
14280 inw(ioport + 4);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014281
14282 if (!irq)
14283 irq = advansys_eisa_irq_no(edev);
14284
14285 err = -ENOMEM;
14286 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
14287 if (!shost)
14288 goto release_region;
14289
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014290 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014291 board->irq = irq;
14292 board->dev = dev;
14293
14294 err = advansys_board_found(shost, ioport, ASC_IS_EISA);
14295 if (!err) {
14296 data->host[i] = shost;
14297 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014298 }
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014299
14300 scsi_host_put(shost);
14301 release_region:
14302 release_region(ioport, ASC_IOADR_GAP);
14303 break;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014304 }
14305
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014306 if (err)
14307 goto free_data;
14308 dev_set_drvdata(dev, data);
14309 return 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014310
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014311 free_data:
14312 kfree(data->host[0]);
14313 kfree(data->host[1]);
14314 kfree(data);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014315 fail:
14316 return err;
14317}
14318
14319static __devexit int advansys_eisa_remove(struct device *dev)
14320{
14321 int i;
14322 struct eisa_scsi_data *data = dev_get_drvdata(dev);
14323
14324 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014325 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014326 struct Scsi_Host *shost = data->host[i];
14327 if (!shost)
14328 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014329 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014330 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014331 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014332 }
14333
14334 kfree(data);
14335 return 0;
14336}
14337
14338static struct eisa_driver advansys_eisa_driver = {
14339 .id_table = advansys_eisa_table,
14340 .driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014341 .name = DRV_NAME,
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014342 .probe = advansys_eisa_probe,
14343 .remove = __devexit_p(advansys_eisa_remove),
14344 }
14345};
14346
Dave Jones2672ea82006-08-02 17:11:49 -040014347/* PCI Devices supported by this driver */
14348static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014349 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
14350 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14351 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
14352 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14353 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
14354 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14355 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
14356 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14357 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
14358 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14359 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
14360 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14361 {}
Dave Jones2672ea82006-08-02 17:11:49 -040014362};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014363
Dave Jones2672ea82006-08-02 17:11:49 -040014364MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014365
Matthew Wilcox9649af32007-07-26 21:51:47 -060014366static void __devinit advansys_set_latency(struct pci_dev *pdev)
14367{
14368 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
14369 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
14370 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
14371 } else {
14372 u8 latency;
14373 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
14374 if (latency < 0x20)
14375 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
14376 }
14377}
14378
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014379static int __devinit
14380advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14381{
14382 int err, ioport;
14383 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014384 struct asc_board *board;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014385
14386 err = pci_enable_device(pdev);
14387 if (err)
14388 goto fail;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014389 err = pci_request_regions(pdev, DRV_NAME);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014390 if (err)
14391 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060014392 pci_set_master(pdev);
14393 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014394
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014395 err = -ENODEV;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014396 if (pci_resource_len(pdev, 0) == 0)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014397 goto release_region;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014398
14399 ioport = pci_resource_start(pdev, 0);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014400
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014401 err = -ENOMEM;
14402 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014403 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014404 goto release_region;
14405
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014406 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014407 board->irq = pdev->irq;
14408 board->dev = &pdev->dev;
14409
14410 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14411 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14412 pdev->device == PCI_DEVICE_ID_38C1600_REV1) {
14413 board->flags |= ASC_IS_WIDE_BOARD;
14414 }
14415
14416 err = advansys_board_found(shost, ioport, ASC_IS_PCI);
14417 if (err)
14418 goto free_host;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014419
14420 pci_set_drvdata(pdev, shost);
14421 return 0;
14422
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014423 free_host:
14424 scsi_host_put(shost);
14425 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014426 pci_release_regions(pdev);
14427 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014428 pci_disable_device(pdev);
14429 fail:
14430 return err;
14431}
14432
14433static void __devexit advansys_pci_remove(struct pci_dev *pdev)
14434{
14435 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014436 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014437 pci_disable_device(pdev);
14438}
14439
14440static struct pci_driver advansys_pci_driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014441 .name = DRV_NAME,
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014442 .id_table = advansys_pci_tbl,
14443 .probe = advansys_pci_probe,
14444 .remove = __devexit_p(advansys_pci_remove),
14445};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014446
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014447static int __init advansys_init(void)
14448{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014449 int error;
14450
14451 error = isa_register_driver(&advansys_isa_driver,
14452 ASC_IOADR_TABLE_MAX_IX);
14453 if (error)
14454 goto fail;
14455
14456 error = isa_register_driver(&advansys_vlb_driver,
14457 ASC_IOADR_TABLE_MAX_IX);
14458 if (error)
14459 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014460
14461 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014462 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014463 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014464
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014465 error = pci_register_driver(&advansys_pci_driver);
14466 if (error)
14467 goto unregister_eisa;
14468
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014469 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014470
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014471 unregister_eisa:
14472 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014473 unregister_vlb:
14474 isa_unregister_driver(&advansys_vlb_driver);
14475 unregister_isa:
14476 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014477 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014478 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014479}
14480
14481static void __exit advansys_exit(void)
14482{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014483 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014484 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014485 isa_unregister_driver(&advansys_vlb_driver);
14486 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014487}
14488
14489module_init(advansys_init);
14490module_exit(advansys_exit);
14491
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014492MODULE_LICENSE("GPL");