blob: 6bd8e835ea0f769d65b2f6673d66c3f7c5be7317 [file] [log] [blame]
Matthew Wilcox01fbfe02007-09-09 08:56:40 -06001#define DRV_NAME "advansys"
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04002#define ASC_VERSION "3.4" /* AdvanSys Driver Version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003
4/*
5 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
6 *
7 * Copyright (c) 1995-2000 Advanced System Products, Inc.
8 * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04009 * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * All Rights Reserved.
11 *
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
20 * changed its name to ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040021 * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/string.h>
26#include <linux/kernel.h>
27#include <linux/types.h>
28#include <linux/ioport.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <linux/slab.h>
32#include <linux/mm.h>
33#include <linux/proc_fs.h>
34#include <linux/init.h>
35#include <linux/blkdev.h>
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060036#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060037#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040038#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/spinlock.h>
40#include <linux/dma-mapping.h>
41
42#include <asm/io.h>
43#include <asm/system.h>
44#include <asm/dma.h>
45
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040046#include <scsi/scsi_cmnd.h>
47#include <scsi/scsi_device.h>
48#include <scsi/scsi_tcq.h>
49#include <scsi/scsi.h>
50#include <scsi/scsi_host.h>
51
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060052/* FIXME:
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 *
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060054 * 1. Although all of the necessary command mapping places have the
55 * appropriate dma_map.. APIs, the driver still processes its internal
56 * queue using bus_to_virt() and virt_to_bus() which are illegal under
57 * the API. The entire queue processing structure will need to be
58 * altered to fix this.
59 * 2. Need to add memory mapping workaround. Test the memory mapping.
60 * If it doesn't work revert to I/O port access. Can a test be done
61 * safely?
62 * 3. Handle an interrupt not working. Keep an interrupt counter in
63 * the interrupt handler. In the timeout function if the interrupt
64 * has not occurred then print a message and run in polled mode.
65 * 4. Need to add support for target mode commands, cf. CAM XPT.
66 * 5. check DMA mapping functions for failure
Matthew Wilcox349d2c42007-09-09 08:56:34 -060067 * 6. Use scsi_transport_spi
68 * 7. advansys_info is not safe against multiple simultaneous callers
69 * 8. Kill boardp->id
70 * 9. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 */
72#warning this driver is still not properly converted to the DMA API
73
Linus Torvalds1da177e2005-04-16 15:20:36 -070074/* Enable driver /proc statistics. */
75#define ADVANSYS_STATS
76
77/* Enable driver tracing. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040078#undef ADVANSYS_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Linus Torvalds1da177e2005-04-16 15:20:36 -070080/*
81 * Portable Data Types
82 *
83 * Any instance where a 32-bit long or pointer type is assumed
84 * for precision or HW defined structures, the following define
85 * types must be used. In Linux the char, short, and int types
86 * are all consistent at 8, 16, and 32 bits respectively. Pointers
87 * and long types are 64 bits on Alpha and UltraSPARC.
88 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040089#define ASC_PADDR __u32 /* Physical/Bus address data type. */
90#define ASC_VADDR __u32 /* Virtual address data type. */
91#define ASC_DCNT __u32 /* Unsigned Data count type. */
92#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94/*
95 * These macros are used to convert a virtual address to a
96 * 32-bit value. This currently can be used on Linux Alpha
97 * which uses 64-bit virtual address but a 32-bit bus address.
98 * This is likely to break in the future, but doing this now
99 * will give us time to change the HW and FW to handle 64-bit
100 * addresses.
101 */
102#define ASC_VADDR_TO_U32 virt_to_bus
103#define ASC_U32_TO_VADDR bus_to_virt
104
105typedef unsigned char uchar;
106
107#ifndef TRUE
108#define TRUE (1)
109#endif
110#ifndef FALSE
111#define FALSE (0)
112#endif
113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#define ERR (-1)
115#define UW_ERR (uint)(0xFFFF)
116#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
Dave Jones2672ea82006-08-02 17:11:49 -0400118#define PCI_VENDOR_ID_ASP 0x10cd
119#define PCI_DEVICE_ID_ASP_1200A 0x1100
120#define PCI_DEVICE_ID_ASP_ABP940 0x1200
121#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
122#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
123#define PCI_DEVICE_ID_38C0800_REV1 0x2500
124#define PCI_DEVICE_ID_38C1600_REV1 0x2700
125
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126/*
127 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
128 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
129 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
130 * SRB structure.
131 */
132#define CC_VERY_LONG_SG_LIST 0
133#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
134
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400135#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136#define inp(port) inb(port)
137#define outp(port, byte) outb((byte), (port))
138
139#define inpw(port) inw(port)
140#define outpw(port, word) outw((word), (port))
141
142#define ASC_MAX_SG_QUEUE 7
143#define ASC_MAX_SG_LIST 255
144
145#define ASC_CS_TYPE unsigned short
146
147#define ASC_IS_ISA (0x0001)
148#define ASC_IS_ISAPNP (0x0081)
149#define ASC_IS_EISA (0x0002)
150#define ASC_IS_PCI (0x0004)
151#define ASC_IS_PCI_ULTRA (0x0104)
152#define ASC_IS_PCMCIA (0x0008)
153#define ASC_IS_MCA (0x0020)
154#define ASC_IS_VL (0x0040)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#define ASC_IS_WIDESCSI_16 (0x0100)
156#define ASC_IS_WIDESCSI_32 (0x0200)
157#define ASC_IS_BIG_ENDIAN (0x8000)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159#define ASC_CHIP_MIN_VER_VL (0x01)
160#define ASC_CHIP_MAX_VER_VL (0x07)
161#define ASC_CHIP_MIN_VER_PCI (0x09)
162#define ASC_CHIP_MAX_VER_PCI (0x0F)
163#define ASC_CHIP_VER_PCI_BIT (0x08)
164#define ASC_CHIP_MIN_VER_ISA (0x11)
165#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
166#define ASC_CHIP_MAX_VER_ISA (0x27)
167#define ASC_CHIP_VER_ISA_BIT (0x30)
168#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
169#define ASC_CHIP_VER_ASYN_BUG (0x21)
170#define ASC_CHIP_VER_PCI 0x08
171#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
172#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
173#define ASC_CHIP_MIN_VER_EISA (0x41)
174#define ASC_CHIP_MAX_VER_EISA (0x47)
175#define ASC_CHIP_VER_EISA_BIT (0x40)
176#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
181#define ASC_SCSI_ID_BITS 3
182#define ASC_SCSI_TIX_TYPE uchar
183#define ASC_ALL_DEVICE_BIT_SET 0xFF
184#define ASC_SCSI_BIT_ID_TYPE uchar
185#define ASC_MAX_TID 7
186#define ASC_MAX_LUN 7
187#define ASC_SCSI_WIDTH_BIT_SET 0xFF
188#define ASC_MAX_SENSE_LEN 32
189#define ASC_MIN_SENSE_LEN 14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190#define ASC_SCSI_RESET_HOLD_TIME_US 60
191
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192/*
Matthew Wilcoxf05ec592007-09-09 08:56:36 -0600193 * Narrow boards only support 12-byte commands, while wide boards
194 * extend to 16-byte commands.
195 */
196#define ASC_MAX_CDB_LEN 12
197#define ADV_MAX_CDB_LEN 16
198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202#define ASC_SG_LIST_PER_Q 7
203#define QS_FREE 0x00
204#define QS_READY 0x01
205#define QS_DISC1 0x02
206#define QS_DISC2 0x04
207#define QS_BUSY 0x08
208#define QS_ABORTED 0x40
209#define QS_DONE 0x80
210#define QC_NO_CALLBACK 0x01
211#define QC_SG_SWAP_QUEUE 0x02
212#define QC_SG_HEAD 0x04
213#define QC_DATA_IN 0x08
214#define QC_DATA_OUT 0x10
215#define QC_URGENT 0x20
216#define QC_MSG_OUT 0x40
217#define QC_REQ_SENSE 0x80
218#define QCSG_SG_XFER_LIST 0x02
219#define QCSG_SG_XFER_MORE 0x04
220#define QCSG_SG_XFER_END 0x08
221#define QD_IN_PROGRESS 0x00
222#define QD_NO_ERROR 0x01
223#define QD_ABORTED_BY_HOST 0x02
224#define QD_WITH_ERROR 0x04
225#define QD_INVALID_REQUEST 0x80
226#define QD_INVALID_HOST_NUM 0x81
227#define QD_INVALID_DEVICE 0x82
228#define QD_ERR_INTERNAL 0xFF
229#define QHSTA_NO_ERROR 0x00
230#define QHSTA_M_SEL_TIMEOUT 0x11
231#define QHSTA_M_DATA_OVER_RUN 0x12
232#define QHSTA_M_DATA_UNDER_RUN 0x12
233#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
234#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
235#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
236#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
237#define QHSTA_D_HOST_ABORT_FAILED 0x23
238#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
239#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
240#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
241#define QHSTA_M_WTM_TIMEOUT 0x41
242#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
243#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
244#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
245#define QHSTA_M_TARGET_STATUS_BUSY 0x45
246#define QHSTA_M_BAD_TAG_CODE 0x46
247#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
248#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
249#define QHSTA_D_LRAM_CMP_ERROR 0x81
250#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
251#define ASC_FLAG_SCSIQ_REQ 0x01
252#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
253#define ASC_FLAG_BIOS_ASYNC_IO 0x04
254#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
255#define ASC_FLAG_WIN16 0x10
256#define ASC_FLAG_WIN32 0x20
257#define ASC_FLAG_ISA_OVER_16MB 0x40
258#define ASC_FLAG_DOS_VM_CALLBACK 0x80
259#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
260#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
261#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
262#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
263#define ASC_SCSIQ_CPY_BEG 4
264#define ASC_SCSIQ_SGHD_CPY_BEG 2
265#define ASC_SCSIQ_B_FWD 0
266#define ASC_SCSIQ_B_BWD 1
267#define ASC_SCSIQ_B_STATUS 2
268#define ASC_SCSIQ_B_QNO 3
269#define ASC_SCSIQ_B_CNTL 4
270#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
271#define ASC_SCSIQ_D_DATA_ADDR 8
272#define ASC_SCSIQ_D_DATA_CNT 12
273#define ASC_SCSIQ_B_SENSE_LEN 20
274#define ASC_SCSIQ_DONE_INFO_BEG 22
275#define ASC_SCSIQ_D_SRBPTR 22
276#define ASC_SCSIQ_B_TARGET_IX 26
277#define ASC_SCSIQ_B_CDB_LEN 28
278#define ASC_SCSIQ_B_TAG_CODE 29
279#define ASC_SCSIQ_W_VM_ID 30
280#define ASC_SCSIQ_DONE_STATUS 32
281#define ASC_SCSIQ_HOST_STATUS 33
282#define ASC_SCSIQ_SCSI_STATUS 34
283#define ASC_SCSIQ_CDB_BEG 36
284#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
285#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
286#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
287#define ASC_SCSIQ_B_SG_WK_QP 49
288#define ASC_SCSIQ_B_SG_WK_IX 50
289#define ASC_SCSIQ_W_ALT_DC1 52
290#define ASC_SCSIQ_B_LIST_CNT 6
291#define ASC_SCSIQ_B_CUR_LIST_CNT 7
292#define ASC_SGQ_B_SG_CNTL 4
293#define ASC_SGQ_B_SG_HEAD_QP 5
294#define ASC_SGQ_B_SG_LIST_CNT 6
295#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
296#define ASC_SGQ_LIST_BEG 8
297#define ASC_DEF_SCSI1_QNG 4
298#define ASC_MAX_SCSI1_QNG 4
299#define ASC_DEF_SCSI2_QNG 16
300#define ASC_MAX_SCSI2_QNG 32
301#define ASC_TAG_CODE_MASK 0x23
302#define ASC_STOP_REQ_RISC_STOP 0x01
303#define ASC_STOP_ACK_RISC_STOP 0x03
304#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
305#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
306#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
307#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
308#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
309#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
310#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
311#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
312#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
313#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
314
315typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400316 uchar status;
317 uchar q_no;
318 uchar cntl;
319 uchar sg_queue_cnt;
320 uchar target_id;
321 uchar target_lun;
322 ASC_PADDR data_addr;
323 ASC_DCNT data_cnt;
324 ASC_PADDR sense_addr;
325 uchar sense_len;
326 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327} ASC_SCSIQ_1;
328
329typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400330 ASC_VADDR srb_ptr;
331 uchar target_ix;
332 uchar flag;
333 uchar cdb_len;
334 uchar tag_code;
335 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336} ASC_SCSIQ_2;
337
338typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400339 uchar done_stat;
340 uchar host_stat;
341 uchar scsi_stat;
342 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343} ASC_SCSIQ_3;
344
345typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400346 uchar cdb[ASC_MAX_CDB_LEN];
347 uchar y_first_sg_list_qp;
348 uchar y_working_sg_qp;
349 uchar y_working_sg_ix;
350 uchar y_res;
351 ushort x_req_count;
352 ushort x_reconnect_rtn;
353 ASC_PADDR x_saved_data_addr;
354 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355} ASC_SCSIQ_4;
356
357typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400358 ASC_SCSIQ_2 d2;
359 ASC_SCSIQ_3 d3;
360 uchar q_status;
361 uchar q_no;
362 uchar cntl;
363 uchar sense_len;
364 uchar extra_bytes;
365 uchar res;
366 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367} ASC_QDONE_INFO;
368
369typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400370 ASC_PADDR addr;
371 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372} ASC_SG_LIST;
373
374typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400375 ushort entry_cnt;
376 ushort queue_cnt;
377 ushort entry_to_copy;
378 ushort res;
Matthew Wilcox05848b62007-10-02 21:55:25 -0400379 ASC_SG_LIST sg_list[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380} ASC_SG_HEAD;
381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400383 ASC_SCSIQ_1 q1;
384 ASC_SCSIQ_2 q2;
385 uchar *cdbptr;
386 ASC_SG_HEAD *sg_head;
387 ushort remain_sg_entry_cnt;
388 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389} ASC_SCSI_Q;
390
391typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400392 ASC_SCSIQ_1 r1;
393 ASC_SCSIQ_2 r2;
394 uchar *cdbptr;
395 ASC_SG_HEAD *sg_head;
396 uchar *sense_ptr;
397 ASC_SCSIQ_3 r3;
398 uchar cdb[ASC_MAX_CDB_LEN];
399 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400} ASC_SCSI_REQ_Q;
401
402typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400403 ASC_SCSIQ_1 r1;
404 ASC_SCSIQ_2 r2;
405 uchar *cdbptr;
406 ASC_SG_HEAD *sg_head;
407 uchar *sense_ptr;
408 ASC_SCSIQ_3 r3;
409 uchar cdb[ASC_MAX_CDB_LEN];
410 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411} ASC_SCSI_BIOS_REQ_Q;
412
413typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400414 uchar fwd;
415 uchar bwd;
416 ASC_SCSIQ_1 i1;
417 ASC_SCSIQ_2 i2;
418 ASC_SCSIQ_3 i3;
419 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420} ASC_RISC_Q;
421
422typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400423 uchar seq_no;
424 uchar q_no;
425 uchar cntl;
426 uchar sg_head_qp;
427 uchar sg_list_cnt;
428 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429} ASC_SG_LIST_Q;
430
431typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400432 uchar fwd;
433 uchar bwd;
434 ASC_SG_LIST_Q sg;
435 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436} ASC_RISC_SG_LIST_Q;
437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438#define ASCQ_ERR_Q_STATUS 0x0D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439#define ASCQ_ERR_CUR_QNG 0x17
440#define ASCQ_ERR_SG_Q_LINKS 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
442#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
443#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
445/*
446 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
447 */
448#define ASC_WARN_NO_ERROR 0x0000
449#define ASC_WARN_IO_PORT_ROTATE 0x0001
450#define ASC_WARN_EEPROM_CHKSUM 0x0002
451#define ASC_WARN_IRQ_MODIFIED 0x0004
452#define ASC_WARN_AUTO_CONFIG 0x0008
453#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
454#define ASC_WARN_EEPROM_RECOVER 0x0020
455#define ASC_WARN_CFG_MSW_RECOVER 0x0040
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457/*
Matthew Wilcox720349a2007-10-02 21:55:30 -0400458 * Error code values are set in {ASC/ADV}_DVC_VAR 'err_code'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 */
Matthew Wilcox720349a2007-10-02 21:55:30 -0400460#define ASC_IERR_NO_CARRIER 0x0001 /* No more carrier memory */
461#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
462#define ASC_IERR_SET_PC_ADDR 0x0004
463#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
464#define ASC_IERR_ILLEGAL_CONNECTION 0x0010 /* Illegal cable connection */
465#define ASC_IERR_SINGLE_END_DEVICE 0x0020 /* SE device on DIFF bus */
466#define ASC_IERR_REVERSED_CABLE 0x0040 /* Narrow flat cable reversed */
467#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
468#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD device on LVD port */
469#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
470#define ASC_IERR_NO_BUS_TYPE 0x0400
471#define ASC_IERR_BIST_PRE_TEST 0x0800 /* BIST pre-test error */
472#define ASC_IERR_BIST_RAM_TEST 0x1000 /* BIST RAM test error */
473#define ASC_IERR_BAD_CHIPTYPE 0x2000 /* Invalid chip_type setting */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
476#define ASC_MIN_TAG_Q_PER_DVC (0x04)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600477#define ASC_MIN_FREE_Q (0x02)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
479#define ASC_MAX_TOTAL_QNG 240
480#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
481#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
482#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
483#define ASC_MAX_INRAM_TAG_QNG 16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485#define ASC_MAX_SYN_XFER_NO 16
486#define ASC_SYN_MAX_OFFSET 0x0F
487#define ASC_DEF_SDTR_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
489#define SYN_XFER_NS_0 25
490#define SYN_XFER_NS_1 30
491#define SYN_XFER_NS_2 35
492#define SYN_XFER_NS_3 40
493#define SYN_XFER_NS_4 50
494#define SYN_XFER_NS_5 60
495#define SYN_XFER_NS_6 70
496#define SYN_XFER_NS_7 85
497#define SYN_ULTRA_XFER_NS_0 12
498#define SYN_ULTRA_XFER_NS_1 19
499#define SYN_ULTRA_XFER_NS_2 25
500#define SYN_ULTRA_XFER_NS_3 32
501#define SYN_ULTRA_XFER_NS_4 38
502#define SYN_ULTRA_XFER_NS_5 44
503#define SYN_ULTRA_XFER_NS_6 50
504#define SYN_ULTRA_XFER_NS_7 57
505#define SYN_ULTRA_XFER_NS_8 63
506#define SYN_ULTRA_XFER_NS_9 69
507#define SYN_ULTRA_XFER_NS_10 75
508#define SYN_ULTRA_XFER_NS_11 82
509#define SYN_ULTRA_XFER_NS_12 88
510#define SYN_ULTRA_XFER_NS_13 94
511#define SYN_ULTRA_XFER_NS_14 100
512#define SYN_ULTRA_XFER_NS_15 107
513
514typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400515 uchar msg_type;
516 uchar msg_len;
517 uchar msg_req;
518 union {
519 struct {
520 uchar sdtr_xfer_period;
521 uchar sdtr_req_ack_offset;
522 } sdtr;
523 struct {
524 uchar wdtr_width;
525 } wdtr;
526 struct {
527 uchar mdp_b3;
528 uchar mdp_b2;
529 uchar mdp_b1;
530 uchar mdp_b0;
531 } mdp;
532 } u_ext_msg;
533 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534} EXT_MSG;
535
536#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
537#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
538#define wdtr_width u_ext_msg.wdtr.wdtr_width
539#define mdp_b3 u_ext_msg.mdp_b3
540#define mdp_b2 u_ext_msg.mdp_b2
541#define mdp_b1 u_ext_msg.mdp_b1
542#define mdp_b0 u_ext_msg.mdp_b0
543
544typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400545 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
546 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
547 ASC_SCSI_BIT_ID_TYPE disc_enable;
548 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
549 uchar chip_scsi_id;
550 uchar isa_dma_speed;
551 uchar isa_dma_channel;
552 uchar chip_version;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400553 ushort mcode_date;
554 ushort mcode_version;
555 uchar max_tag_qng[ASC_MAX_TID + 1];
556 uchar *overrun_buf;
557 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400558 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559} ASC_DVC_CFG;
560
561#define ASC_DEF_DVC_CNTL 0xFFFF
562#define ASC_DEF_CHIP_SCSI_ID 7
563#define ASC_DEF_ISA_DMA_SPEED 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
565#define ASC_INIT_STATE_END_GET_CFG 0x0002
566#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
567#define ASC_INIT_STATE_END_SET_CFG 0x0008
568#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
569#define ASC_INIT_STATE_END_LOAD_MC 0x0020
570#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
571#define ASC_INIT_STATE_END_INQUIRY 0x0080
572#define ASC_INIT_RESET_SCSI_DONE 0x0100
573#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
575#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
576#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
577#define ASC_MIN_TAGGED_CMD 7
578#define ASC_MAX_SCSI_RESET_WAIT 30
579
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400580struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400583 PortAddr iop_base;
584 ushort err_code;
585 ushort dvc_cntl;
586 ushort bug_fix_cntl;
587 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400588 ASC_SCSI_BIT_ID_TYPE init_sdtr;
589 ASC_SCSI_BIT_ID_TYPE sdtr_done;
590 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
591 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
592 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
593 ASC_SCSI_BIT_ID_TYPE start_motor;
594 uchar scsi_reset_wait;
595 uchar chip_no;
596 char is_in_int;
597 uchar max_total_qng;
598 uchar cur_total_qng;
599 uchar in_critical_cnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400600 uchar last_q_shortage;
601 ushort init_state;
602 uchar cur_dvc_qng[ASC_MAX_TID + 1];
603 uchar max_dvc_qng[ASC_MAX_TID + 1];
604 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
605 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
606 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
607 ASC_DVC_CFG *cfg;
608 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
609 char redo_scam;
610 ushort res2;
611 uchar dos_int13_table[ASC_MAX_TID + 1];
612 ASC_DCNT max_dma_count;
613 ASC_SCSI_BIT_ID_TYPE no_scam;
614 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
615 uchar max_sdtr_index;
616 uchar host_init_sdtr_index;
617 struct asc_board *drv_ptr;
618 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619} ASC_DVC_VAR;
620
621typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400622 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623} ASC_DVC_INQ_INFO;
624
625typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400626 ASC_DCNT lba;
627 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628} ASC_CAP_INFO;
629
630typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400631 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632} ASC_CAP_INFO_ARRAY;
633
634#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
635#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
636#define ASC_CNTL_INITIATOR (ushort)0x0001
637#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
638#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
639#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
640#define ASC_CNTL_NO_SCAM (ushort)0x0010
641#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
642#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
643#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
644#define ASC_CNTL_RESET_SCSI (ushort)0x0200
645#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
646#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
647#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
648#define ASC_CNTL_BURST_MODE (ushort)0x2000
649#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
650#define ASC_EEP_DVC_CFG_BEG_VL 2
651#define ASC_EEP_MAX_DVC_ADDR_VL 15
652#define ASC_EEP_DVC_CFG_BEG 32
653#define ASC_EEP_MAX_DVC_ADDR 45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654#define ASC_EEP_MAX_RETRY 20
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656/*
657 * These macros keep the chip SCSI id and ISA DMA speed
658 * bitfields in board order. C bitfields aren't portable
659 * between big and little-endian platforms so they are
660 * not used.
661 */
662
663#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
664#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
665#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
666 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
667#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
668 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
669
670typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400671 ushort cfg_lsw;
672 ushort cfg_msw;
673 uchar init_sdtr;
674 uchar disc_enable;
675 uchar use_cmd_qng;
676 uchar start_motor;
677 uchar max_total_qng;
678 uchar max_tag_qng;
679 uchar bios_scan;
680 uchar power_up_wait;
681 uchar no_scam;
682 uchar id_speed; /* low order 4 bits is chip scsi id */
683 /* high order 4 bits is isa dma speed */
684 uchar dos_int13_table[ASC_MAX_TID + 1];
685 uchar adapter_info[6];
686 ushort cntl;
687 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688} ASCEEP_CONFIG;
689
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690#define ASC_EEP_CMD_READ 0x80
691#define ASC_EEP_CMD_WRITE 0x40
692#define ASC_EEP_CMD_WRITE_ABLE 0x30
693#define ASC_EEP_CMD_WRITE_DISABLE 0x00
694#define ASC_OVERRUN_BSIZE 0x00000048UL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695#define ASCV_MSGOUT_BEG 0x0000
696#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
697#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
698#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
699#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
700#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
701#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
702#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
703#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
704#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
705#define ASCV_BREAK_ADDR (ushort)0x0028
706#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
707#define ASCV_BREAK_CONTROL (ushort)0x002C
708#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
709
710#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
711#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
712#define ASCV_MCODE_SIZE_W (ushort)0x0034
713#define ASCV_STOP_CODE_B (ushort)0x0036
714#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
715#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
716#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
717#define ASCV_HALTCODE_W (ushort)0x0040
718#define ASCV_CHKSUM_W (ushort)0x0042
719#define ASCV_MC_DATE_W (ushort)0x0044
720#define ASCV_MC_VER_W (ushort)0x0046
721#define ASCV_NEXTRDY_B (ushort)0x0048
722#define ASCV_DONENEXT_B (ushort)0x0049
723#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
724#define ASCV_SCSIBUSY_B (ushort)0x004B
725#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
726#define ASCV_CURCDB_B (ushort)0x004D
727#define ASCV_RCLUN_B (ushort)0x004E
728#define ASCV_BUSY_QHEAD_B (ushort)0x004F
729#define ASCV_DISC1_QHEAD_B (ushort)0x0050
730#define ASCV_DISC_ENABLE_B (ushort)0x0052
731#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
732#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
733#define ASCV_MCODE_CNTL_B (ushort)0x0056
734#define ASCV_NULL_TARGET_B (ushort)0x0057
735#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
736#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
737#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
738#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
739#define ASCV_HOST_FLAG_B (ushort)0x005D
740#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
741#define ASCV_VER_SERIAL_B (ushort)0x0065
742#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
743#define ASCV_WTM_FLAG_B (ushort)0x0068
744#define ASCV_RISC_FLAG_B (ushort)0x006A
745#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
746#define ASC_HOST_FLAG_IN_ISR 0x01
747#define ASC_HOST_FLAG_ACK_INT 0x02
748#define ASC_RISC_FLAG_GEN_INT 0x01
749#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
750#define IOP_CTRL (0x0F)
751#define IOP_STATUS (0x0E)
752#define IOP_INT_ACK IOP_STATUS
753#define IOP_REG_IFC (0x0D)
754#define IOP_SYN_OFFSET (0x0B)
755#define IOP_EXTRA_CONTROL (0x0D)
756#define IOP_REG_PC (0x0C)
757#define IOP_RAM_ADDR (0x0A)
758#define IOP_RAM_DATA (0x08)
759#define IOP_EEP_DATA (0x06)
760#define IOP_EEP_CMD (0x07)
761#define IOP_VERSION (0x03)
762#define IOP_CONFIG_HIGH (0x04)
763#define IOP_CONFIG_LOW (0x02)
764#define IOP_SIG_BYTE (0x01)
765#define IOP_SIG_WORD (0x00)
766#define IOP_REG_DC1 (0x0E)
767#define IOP_REG_DC0 (0x0C)
768#define IOP_REG_SB (0x0B)
769#define IOP_REG_DA1 (0x0A)
770#define IOP_REG_DA0 (0x08)
771#define IOP_REG_SC (0x09)
772#define IOP_DMA_SPEED (0x07)
773#define IOP_REG_FLAG (0x07)
774#define IOP_FIFO_H (0x06)
775#define IOP_FIFO_L (0x04)
776#define IOP_REG_ID (0x05)
777#define IOP_REG_QP (0x03)
778#define IOP_REG_IH (0x02)
779#define IOP_REG_IX (0x01)
780#define IOP_REG_AX (0x00)
781#define IFC_REG_LOCK (0x00)
782#define IFC_REG_UNLOCK (0x09)
783#define IFC_WR_EN_FILTER (0x10)
784#define IFC_RD_NO_EEPROM (0x10)
785#define IFC_SLEW_RATE (0x20)
786#define IFC_ACT_NEG (0x40)
787#define IFC_INP_FILTER (0x80)
788#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
789#define SC_SEL (uchar)(0x80)
790#define SC_BSY (uchar)(0x40)
791#define SC_ACK (uchar)(0x20)
792#define SC_REQ (uchar)(0x10)
793#define SC_ATN (uchar)(0x08)
794#define SC_IO (uchar)(0x04)
795#define SC_CD (uchar)(0x02)
796#define SC_MSG (uchar)(0x01)
797#define SEC_SCSI_CTL (uchar)(0x80)
798#define SEC_ACTIVE_NEGATE (uchar)(0x40)
799#define SEC_SLEW_RATE (uchar)(0x20)
800#define SEC_ENABLE_FILTER (uchar)(0x10)
801#define ASC_HALT_EXTMSG_IN (ushort)0x8000
802#define ASC_HALT_CHK_CONDITION (ushort)0x8100
803#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
804#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
805#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
806#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
807#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
808#define ASC_MAX_QNO 0xF8
809#define ASC_DATA_SEC_BEG (ushort)0x0080
810#define ASC_DATA_SEC_END (ushort)0x0080
811#define ASC_CODE_SEC_BEG (ushort)0x0080
812#define ASC_CODE_SEC_END (ushort)0x0080
813#define ASC_QADR_BEG (0x4000)
814#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
815#define ASC_QADR_END (ushort)0x7FFF
816#define ASC_QLAST_ADR (ushort)0x7FC0
817#define ASC_QBLK_SIZE 0x40
818#define ASC_BIOS_DATA_QBEG 0xF8
819#define ASC_MIN_ACTIVE_QNO 0x01
820#define ASC_QLINK_END 0xFF
821#define ASC_EEPROM_WORDS 0x10
822#define ASC_MAX_MGS_LEN 0x10
823#define ASC_BIOS_ADDR_DEF 0xDC00
824#define ASC_BIOS_SIZE 0x3800
825#define ASC_BIOS_RAM_OFF 0x3800
826#define ASC_BIOS_RAM_SIZE 0x800
827#define ASC_BIOS_MIN_ADDR 0xC000
828#define ASC_BIOS_MAX_ADDR 0xEC00
829#define ASC_BIOS_BANK_SIZE 0x0400
830#define ASC_MCODE_START_ADDR 0x0080
831#define ASC_CFG0_HOST_INT_ON 0x0020
832#define ASC_CFG0_BIOS_ON 0x0040
833#define ASC_CFG0_VERA_BURST_ON 0x0080
834#define ASC_CFG0_SCSI_PARITY_ON 0x0800
835#define ASC_CFG1_SCSI_TARGET_ON 0x0080
836#define ASC_CFG1_LRAM_8BITS_ON 0x0800
837#define ASC_CFG_MSW_CLR_MASK 0x3080
838#define CSW_TEST1 (ASC_CS_TYPE)0x8000
839#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
840#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
841#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
842#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
843#define CSW_TEST2 (ASC_CS_TYPE)0x0400
844#define CSW_TEST3 (ASC_CS_TYPE)0x0200
845#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
846#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
847#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
848#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
849#define CSW_HALTED (ASC_CS_TYPE)0x0010
850#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
851#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
852#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
853#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
854#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
855#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
856#define CIW_TEST1 (ASC_CS_TYPE)0x0200
857#define CIW_TEST2 (ASC_CS_TYPE)0x0400
858#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
859#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
860#define CC_CHIP_RESET (uchar)0x80
861#define CC_SCSI_RESET (uchar)0x40
862#define CC_HALT (uchar)0x20
863#define CC_SINGLE_STEP (uchar)0x10
864#define CC_DMA_ABLE (uchar)0x08
865#define CC_TEST (uchar)0x04
866#define CC_BANK_ONE (uchar)0x02
867#define CC_DIAG (uchar)0x01
868#define ASC_1000_ID0W 0x04C1
869#define ASC_1000_ID0W_FIX 0x00C1
870#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871#define ASC_EISA_REV_IOP_MASK (0x0C83)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872#define ASC_EISA_CFG_IOP_MASK (0x0C86)
873#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874#define INS_HALTINT (ushort)0x6281
875#define INS_HALT (ushort)0x6280
876#define INS_SINT (ushort)0x6200
877#define INS_RFLAG_WTM (ushort)0x7380
878#define ASC_MC_SAVE_CODE_WSIZE 0x500
879#define ASC_MC_SAVE_DATA_WSIZE 0x40
880
881typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400882 ushort data[ASC_MC_SAVE_DATA_WSIZE];
883 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884} ASC_MC_SAVED;
885
886#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
887#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
888#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
889#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
890#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
891#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
892#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
893#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
894#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
895#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
Matthew Wilcox51219352007-10-02 21:55:22 -0400896#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data))
897#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id))
898#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data)
899#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
901#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
902#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
903#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
904#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
905#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
906#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
907#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
908#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
909#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
910#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
911#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
912#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
913#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
914#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
915#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
916#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
917#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
918#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
919#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
920#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
921#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
922#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
923#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
924#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
925#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
926#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
927#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
928#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
929#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
930#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
931#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
932#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
933#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
934#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
935#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
936#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
937#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
938#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
939#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
940#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
941#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
942#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
943#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
944#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
945#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
946#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
947#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
948#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
949#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
950#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
951#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
952#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
953#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955/*
956 * Portable Data Types
957 *
958 * Any instance where a 32-bit long or pointer type is assumed
959 * for precision or HW defined structures, the following define
960 * types must be used. In Linux the char, short, and int types
961 * are all consistent at 8, 16, and 32 bits respectively. Pointers
962 * and long types are 64 bits on Alpha and UltraSPARC.
963 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400964#define ADV_PADDR __u32 /* Physical address data type. */
965#define ADV_VADDR __u32 /* Virtual address data type. */
966#define ADV_DCNT __u32 /* Unsigned Data count type. */
967#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
969/*
970 * These macros are used to convert a virtual address to a
971 * 32-bit value. This currently can be used on Linux Alpha
972 * which uses 64-bit virtual address but a 32-bit bus address.
973 * This is likely to break in the future, but doing this now
974 * will give us time to change the HW and FW to handle 64-bit
975 * addresses.
976 */
977#define ADV_VADDR_TO_U32 virt_to_bus
978#define ADV_U32_TO_VADDR bus_to_virt
979
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400980#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
982/*
983 * Define Adv Library required memory access macros.
984 */
985#define ADV_MEM_READB(addr) readb(addr)
986#define ADV_MEM_READW(addr) readw(addr)
987#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
988#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
989#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
990
991#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
992
993/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 * Define total number of simultaneous maximum element scatter-gather
995 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
996 * maximum number of outstanding commands per wide host adapter. Each
997 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
998 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
999 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1000 * structures or 255 scatter-gather elements.
1001 *
1002 */
1003#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1004
1005/*
1006 * Define Adv Library required maximum number of scatter-gather
1007 * elements per request.
1008 */
1009#define ADV_MAX_SG_LIST 255
1010
1011/* Number of SG blocks needed. */
1012#define ADV_NUM_SG_BLOCK \
1013 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1014
1015/* Total contiguous memory needed for SG blocks. */
1016#define ADV_SG_TOTAL_MEM_SIZE \
1017 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1018
1019#define ADV_PAGE_SIZE PAGE_SIZE
1020
1021#define ADV_NUM_PAGE_CROSSING \
1022 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1025#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001026#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1028
1029#define ADV_EEP_DELAY_MS 100
1030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001031#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1032#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033/*
1034 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1035 * For later ICs Bit 13 controls whether the CIS (Card Information
1036 * Service Section) is loaded from EEPROM.
1037 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001038#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1039#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040/*
1041 * ASC38C1600 Bit 11
1042 *
1043 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1044 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1045 * Function 0 will specify INT B.
1046 *
1047 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1048 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1049 * Function 1 will specify INT A.
1050 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001051#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001053typedef struct adveep_3550_config {
1054 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001056 ushort cfg_lsw; /* 00 power up initialization */
1057 /* bit 13 set - Term Polarity Control */
1058 /* bit 14 set - BIOS Enable */
1059 /* bit 15 set - Big Endian Mode */
1060 ushort cfg_msw; /* 01 unused */
1061 ushort disc_enable; /* 02 disconnect enable */
1062 ushort wdtr_able; /* 03 Wide DTR able */
1063 ushort sdtr_able; /* 04 Synchronous DTR able */
1064 ushort start_motor; /* 05 send start up motor */
1065 ushort tagqng_able; /* 06 tag queuing able */
1066 ushort bios_scan; /* 07 BIOS device control */
1067 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001069 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1070 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001072 uchar scsi_reset_delay; /* 10 reset delay */
1073 uchar bios_id_lun; /* first boot device scsi id & lun */
1074 /* high nibble is lun */
1075 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001077 uchar termination; /* 11 0 - automatic */
1078 /* 1 - low off / high off */
1079 /* 2 - low off / high on */
1080 /* 3 - low on / high on */
1081 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001083 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001085 ushort bios_ctrl; /* 12 BIOS control bits */
1086 /* bit 0 BIOS don't act as initiator. */
1087 /* bit 1 BIOS > 1 GB support */
1088 /* bit 2 BIOS > 2 Disk Support */
1089 /* bit 3 BIOS don't support removables */
1090 /* bit 4 BIOS support bootable CD */
1091 /* bit 5 BIOS scan enabled */
1092 /* bit 6 BIOS support multiple LUNs */
1093 /* bit 7 BIOS display of message */
1094 /* bit 8 SCAM disabled */
1095 /* bit 9 Reset SCSI bus during init. */
1096 /* bit 10 */
1097 /* bit 11 No verbose initialization. */
1098 /* bit 12 SCSI parity enabled */
1099 /* bit 13 */
1100 /* bit 14 */
1101 /* bit 15 */
1102 ushort ultra_able; /* 13 ULTRA speed able */
1103 ushort reserved2; /* 14 reserved */
1104 uchar max_host_qng; /* 15 maximum host queuing */
1105 uchar max_dvc_qng; /* maximum per device queuing */
1106 ushort dvc_cntl; /* 16 control bit for driver */
1107 ushort bug_fix; /* 17 control bit for bug fix */
1108 ushort serial_number_word1; /* 18 Board serial number word 1 */
1109 ushort serial_number_word2; /* 19 Board serial number word 2 */
1110 ushort serial_number_word3; /* 20 Board serial number word 3 */
1111 ushort check_sum; /* 21 EEP check sum */
1112 uchar oem_name[16]; /* 22 OEM name */
1113 ushort dvc_err_code; /* 30 last device driver error code */
1114 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1115 ushort adv_err_addr; /* 32 last uc error address */
1116 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1117 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1118 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1119 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120} ADVEEP_3550_CONFIG;
1121
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001122typedef struct adveep_38C0800_config {
1123 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001125 ushort cfg_lsw; /* 00 power up initialization */
1126 /* bit 13 set - Load CIS */
1127 /* bit 14 set - BIOS Enable */
1128 /* bit 15 set - Big Endian Mode */
1129 ushort cfg_msw; /* 01 unused */
1130 ushort disc_enable; /* 02 disconnect enable */
1131 ushort wdtr_able; /* 03 Wide DTR able */
1132 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1133 ushort start_motor; /* 05 send start up motor */
1134 ushort tagqng_able; /* 06 tag queuing able */
1135 ushort bios_scan; /* 07 BIOS device control */
1136 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001138 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1139 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001141 uchar scsi_reset_delay; /* 10 reset delay */
1142 uchar bios_id_lun; /* first boot device scsi id & lun */
1143 /* high nibble is lun */
1144 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001146 uchar termination_se; /* 11 0 - automatic */
1147 /* 1 - low off / high off */
1148 /* 2 - low off / high on */
1149 /* 3 - low on / high on */
1150 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001152 uchar termination_lvd; /* 11 0 - automatic */
1153 /* 1 - low off / high off */
1154 /* 2 - low off / high on */
1155 /* 3 - low on / high on */
1156 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001158 ushort bios_ctrl; /* 12 BIOS control bits */
1159 /* bit 0 BIOS don't act as initiator. */
1160 /* bit 1 BIOS > 1 GB support */
1161 /* bit 2 BIOS > 2 Disk Support */
1162 /* bit 3 BIOS don't support removables */
1163 /* bit 4 BIOS support bootable CD */
1164 /* bit 5 BIOS scan enabled */
1165 /* bit 6 BIOS support multiple LUNs */
1166 /* bit 7 BIOS display of message */
1167 /* bit 8 SCAM disabled */
1168 /* bit 9 Reset SCSI bus during init. */
1169 /* bit 10 */
1170 /* bit 11 No verbose initialization. */
1171 /* bit 12 SCSI parity enabled */
1172 /* bit 13 */
1173 /* bit 14 */
1174 /* bit 15 */
1175 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1176 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1177 uchar max_host_qng; /* 15 maximum host queueing */
1178 uchar max_dvc_qng; /* maximum per device queuing */
1179 ushort dvc_cntl; /* 16 control bit for driver */
1180 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1181 ushort serial_number_word1; /* 18 Board serial number word 1 */
1182 ushort serial_number_word2; /* 19 Board serial number word 2 */
1183 ushort serial_number_word3; /* 20 Board serial number word 3 */
1184 ushort check_sum; /* 21 EEP check sum */
1185 uchar oem_name[16]; /* 22 OEM name */
1186 ushort dvc_err_code; /* 30 last device driver error code */
1187 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1188 ushort adv_err_addr; /* 32 last uc error address */
1189 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1190 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1191 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1192 ushort reserved36; /* 36 reserved */
1193 ushort reserved37; /* 37 reserved */
1194 ushort reserved38; /* 38 reserved */
1195 ushort reserved39; /* 39 reserved */
1196 ushort reserved40; /* 40 reserved */
1197 ushort reserved41; /* 41 reserved */
1198 ushort reserved42; /* 42 reserved */
1199 ushort reserved43; /* 43 reserved */
1200 ushort reserved44; /* 44 reserved */
1201 ushort reserved45; /* 45 reserved */
1202 ushort reserved46; /* 46 reserved */
1203 ushort reserved47; /* 47 reserved */
1204 ushort reserved48; /* 48 reserved */
1205 ushort reserved49; /* 49 reserved */
1206 ushort reserved50; /* 50 reserved */
1207 ushort reserved51; /* 51 reserved */
1208 ushort reserved52; /* 52 reserved */
1209 ushort reserved53; /* 53 reserved */
1210 ushort reserved54; /* 54 reserved */
1211 ushort reserved55; /* 55 reserved */
1212 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1213 ushort cisprt_msw; /* 57 CIS PTR MSW */
1214 ushort subsysvid; /* 58 SubSystem Vendor ID */
1215 ushort subsysid; /* 59 SubSystem ID */
1216 ushort reserved60; /* 60 reserved */
1217 ushort reserved61; /* 61 reserved */
1218 ushort reserved62; /* 62 reserved */
1219 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220} ADVEEP_38C0800_CONFIG;
1221
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001222typedef struct adveep_38C1600_config {
1223 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001225 ushort cfg_lsw; /* 00 power up initialization */
1226 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1227 /* clear - Func. 0 INTA, Func. 1 INTB */
1228 /* bit 13 set - Load CIS */
1229 /* bit 14 set - BIOS Enable */
1230 /* bit 15 set - Big Endian Mode */
1231 ushort cfg_msw; /* 01 unused */
1232 ushort disc_enable; /* 02 disconnect enable */
1233 ushort wdtr_able; /* 03 Wide DTR able */
1234 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1235 ushort start_motor; /* 05 send start up motor */
1236 ushort tagqng_able; /* 06 tag queuing able */
1237 ushort bios_scan; /* 07 BIOS device control */
1238 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001240 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1241 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001243 uchar scsi_reset_delay; /* 10 reset delay */
1244 uchar bios_id_lun; /* first boot device scsi id & lun */
1245 /* high nibble is lun */
1246 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001248 uchar termination_se; /* 11 0 - automatic */
1249 /* 1 - low off / high off */
1250 /* 2 - low off / high on */
1251 /* 3 - low on / high on */
1252 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001254 uchar termination_lvd; /* 11 0 - automatic */
1255 /* 1 - low off / high off */
1256 /* 2 - low off / high on */
1257 /* 3 - low on / high on */
1258 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001260 ushort bios_ctrl; /* 12 BIOS control bits */
1261 /* bit 0 BIOS don't act as initiator. */
1262 /* bit 1 BIOS > 1 GB support */
1263 /* bit 2 BIOS > 2 Disk Support */
1264 /* bit 3 BIOS don't support removables */
1265 /* bit 4 BIOS support bootable CD */
1266 /* bit 5 BIOS scan enabled */
1267 /* bit 6 BIOS support multiple LUNs */
1268 /* bit 7 BIOS display of message */
1269 /* bit 8 SCAM disabled */
1270 /* bit 9 Reset SCSI bus during init. */
1271 /* bit 10 Basic Integrity Checking disabled */
1272 /* bit 11 No verbose initialization. */
1273 /* bit 12 SCSI parity enabled */
1274 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1275 /* bit 14 */
1276 /* bit 15 */
1277 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1278 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1279 uchar max_host_qng; /* 15 maximum host queueing */
1280 uchar max_dvc_qng; /* maximum per device queuing */
1281 ushort dvc_cntl; /* 16 control bit for driver */
1282 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1283 ushort serial_number_word1; /* 18 Board serial number word 1 */
1284 ushort serial_number_word2; /* 19 Board serial number word 2 */
1285 ushort serial_number_word3; /* 20 Board serial number word 3 */
1286 ushort check_sum; /* 21 EEP check sum */
1287 uchar oem_name[16]; /* 22 OEM name */
1288 ushort dvc_err_code; /* 30 last device driver error code */
1289 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1290 ushort adv_err_addr; /* 32 last uc error address */
1291 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1292 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1293 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1294 ushort reserved36; /* 36 reserved */
1295 ushort reserved37; /* 37 reserved */
1296 ushort reserved38; /* 38 reserved */
1297 ushort reserved39; /* 39 reserved */
1298 ushort reserved40; /* 40 reserved */
1299 ushort reserved41; /* 41 reserved */
1300 ushort reserved42; /* 42 reserved */
1301 ushort reserved43; /* 43 reserved */
1302 ushort reserved44; /* 44 reserved */
1303 ushort reserved45; /* 45 reserved */
1304 ushort reserved46; /* 46 reserved */
1305 ushort reserved47; /* 47 reserved */
1306 ushort reserved48; /* 48 reserved */
1307 ushort reserved49; /* 49 reserved */
1308 ushort reserved50; /* 50 reserved */
1309 ushort reserved51; /* 51 reserved */
1310 ushort reserved52; /* 52 reserved */
1311 ushort reserved53; /* 53 reserved */
1312 ushort reserved54; /* 54 reserved */
1313 ushort reserved55; /* 55 reserved */
1314 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1315 ushort cisprt_msw; /* 57 CIS PTR MSW */
1316 ushort subsysvid; /* 58 SubSystem Vendor ID */
1317 ushort subsysid; /* 59 SubSystem ID */
1318 ushort reserved60; /* 60 reserved */
1319 ushort reserved61; /* 61 reserved */
1320 ushort reserved62; /* 62 reserved */
1321 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322} ADVEEP_38C1600_CONFIG;
1323
1324/*
1325 * EEPROM Commands
1326 */
1327#define ASC_EEP_CMD_DONE 0x0200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329/* bios_ctrl */
1330#define BIOS_CTRL_BIOS 0x0001
1331#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1332#define BIOS_CTRL_GT_2_DISK 0x0004
1333#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1334#define BIOS_CTRL_BOOTABLE_CD 0x0010
1335#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1336#define BIOS_CTRL_DISPLAY_MSG 0x0080
1337#define BIOS_CTRL_NO_SCAM 0x0100
1338#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1339#define BIOS_CTRL_INIT_VERBOSE 0x0800
1340#define BIOS_CTRL_SCSI_PARITY 0x1000
1341#define BIOS_CTRL_AIPP_DIS 0x2000
1342
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001343#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001345#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
1347/*
1348 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1349 * a special 16K Adv Library and Microcode version. After the issue is
1350 * resolved, should restore 32K support.
1351 *
1352 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1353 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001354#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
1356/*
1357 * Byte I/O register address from base of 'iop_base'.
1358 */
1359#define IOPB_INTR_STATUS_REG 0x00
1360#define IOPB_CHIP_ID_1 0x01
1361#define IOPB_INTR_ENABLES 0x02
1362#define IOPB_CHIP_TYPE_REV 0x03
1363#define IOPB_RES_ADDR_4 0x04
1364#define IOPB_RES_ADDR_5 0x05
1365#define IOPB_RAM_DATA 0x06
1366#define IOPB_RES_ADDR_7 0x07
1367#define IOPB_FLAG_REG 0x08
1368#define IOPB_RES_ADDR_9 0x09
1369#define IOPB_RISC_CSR 0x0A
1370#define IOPB_RES_ADDR_B 0x0B
1371#define IOPB_RES_ADDR_C 0x0C
1372#define IOPB_RES_ADDR_D 0x0D
1373#define IOPB_SOFT_OVER_WR 0x0E
1374#define IOPB_RES_ADDR_F 0x0F
1375#define IOPB_MEM_CFG 0x10
1376#define IOPB_RES_ADDR_11 0x11
1377#define IOPB_GPIO_DATA 0x12
1378#define IOPB_RES_ADDR_13 0x13
1379#define IOPB_FLASH_PAGE 0x14
1380#define IOPB_RES_ADDR_15 0x15
1381#define IOPB_GPIO_CNTL 0x16
1382#define IOPB_RES_ADDR_17 0x17
1383#define IOPB_FLASH_DATA 0x18
1384#define IOPB_RES_ADDR_19 0x19
1385#define IOPB_RES_ADDR_1A 0x1A
1386#define IOPB_RES_ADDR_1B 0x1B
1387#define IOPB_RES_ADDR_1C 0x1C
1388#define IOPB_RES_ADDR_1D 0x1D
1389#define IOPB_RES_ADDR_1E 0x1E
1390#define IOPB_RES_ADDR_1F 0x1F
1391#define IOPB_DMA_CFG0 0x20
1392#define IOPB_DMA_CFG1 0x21
1393#define IOPB_TICKLE 0x22
1394#define IOPB_DMA_REG_WR 0x23
1395#define IOPB_SDMA_STATUS 0x24
1396#define IOPB_SCSI_BYTE_CNT 0x25
1397#define IOPB_HOST_BYTE_CNT 0x26
1398#define IOPB_BYTE_LEFT_TO_XFER 0x27
1399#define IOPB_BYTE_TO_XFER_0 0x28
1400#define IOPB_BYTE_TO_XFER_1 0x29
1401#define IOPB_BYTE_TO_XFER_2 0x2A
1402#define IOPB_BYTE_TO_XFER_3 0x2B
1403#define IOPB_ACC_GRP 0x2C
1404#define IOPB_RES_ADDR_2D 0x2D
1405#define IOPB_DEV_ID 0x2E
1406#define IOPB_RES_ADDR_2F 0x2F
1407#define IOPB_SCSI_DATA 0x30
1408#define IOPB_RES_ADDR_31 0x31
1409#define IOPB_RES_ADDR_32 0x32
1410#define IOPB_SCSI_DATA_HSHK 0x33
1411#define IOPB_SCSI_CTRL 0x34
1412#define IOPB_RES_ADDR_35 0x35
1413#define IOPB_RES_ADDR_36 0x36
1414#define IOPB_RES_ADDR_37 0x37
1415#define IOPB_RAM_BIST 0x38
1416#define IOPB_PLL_TEST 0x39
1417#define IOPB_PCI_INT_CFG 0x3A
1418#define IOPB_RES_ADDR_3B 0x3B
1419#define IOPB_RFIFO_CNT 0x3C
1420#define IOPB_RES_ADDR_3D 0x3D
1421#define IOPB_RES_ADDR_3E 0x3E
1422#define IOPB_RES_ADDR_3F 0x3F
1423
1424/*
1425 * Word I/O register address from base of 'iop_base'.
1426 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001427#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1428#define IOPW_CTRL_REG 0x02 /* CC */
1429#define IOPW_RAM_ADDR 0x04 /* LA */
1430#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001432#define IOPW_RISC_CSR 0x0A /* CSR */
1433#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1434#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001436#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001438#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001440#define IOPW_EE_CMD 0x1A /* EC */
1441#define IOPW_EE_DATA 0x1C /* ED */
1442#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001444#define IOPW_Q_BASE 0x22 /* QB */
1445#define IOPW_QP 0x24 /* QP */
1446#define IOPW_IX 0x26 /* IX */
1447#define IOPW_SP 0x28 /* SP */
1448#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449#define IOPW_RES_ADDR_2C 0x2C
1450#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001451#define IOPW_SCSI_DATA 0x30 /* SD */
1452#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1453#define IOPW_SCSI_CTRL 0x34 /* SC */
1454#define IOPW_HSHK_CFG 0x36 /* HCFG */
1455#define IOPW_SXFR_STATUS 0x36 /* SXS */
1456#define IOPW_SXFR_CNTL 0x38 /* SXL */
1457#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001459#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461/*
1462 * Doubleword I/O register address from base of 'iop_base'.
1463 */
1464#define IOPDW_RES_ADDR_0 0x00
1465#define IOPDW_RAM_DATA 0x04
1466#define IOPDW_RES_ADDR_8 0x08
1467#define IOPDW_RES_ADDR_C 0x0C
1468#define IOPDW_RES_ADDR_10 0x10
1469#define IOPDW_COMMA 0x14
1470#define IOPDW_COMMB 0x18
1471#define IOPDW_RES_ADDR_1C 0x1C
1472#define IOPDW_SDMA_ADDR0 0x20
1473#define IOPDW_SDMA_ADDR1 0x24
1474#define IOPDW_SDMA_COUNT 0x28
1475#define IOPDW_SDMA_ERROR 0x2C
1476#define IOPDW_RDMA_ADDR0 0x30
1477#define IOPDW_RDMA_ADDR1 0x34
1478#define IOPDW_RDMA_COUNT 0x38
1479#define IOPDW_RDMA_ERROR 0x3C
1480
1481#define ADV_CHIP_ID_BYTE 0x25
1482#define ADV_CHIP_ID_WORD 0x04C1
1483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484#define ADV_INTR_ENABLE_HOST_INTR 0x01
1485#define ADV_INTR_ENABLE_SEL_INTR 0x02
1486#define ADV_INTR_ENABLE_DPR_INTR 0x04
1487#define ADV_INTR_ENABLE_RTA_INTR 0x08
1488#define ADV_INTR_ENABLE_RMA_INTR 0x10
1489#define ADV_INTR_ENABLE_RST_INTR 0x20
1490#define ADV_INTR_ENABLE_DPE_INTR 0x40
1491#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1492
1493#define ADV_INTR_STATUS_INTRA 0x01
1494#define ADV_INTR_STATUS_INTRB 0x02
1495#define ADV_INTR_STATUS_INTRC 0x04
1496
1497#define ADV_RISC_CSR_STOP (0x0000)
1498#define ADV_RISC_TEST_COND (0x2000)
1499#define ADV_RISC_CSR_RUN (0x4000)
1500#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1501
1502#define ADV_CTRL_REG_HOST_INTR 0x0100
1503#define ADV_CTRL_REG_SEL_INTR 0x0200
1504#define ADV_CTRL_REG_DPR_INTR 0x0400
1505#define ADV_CTRL_REG_RTA_INTR 0x0800
1506#define ADV_CTRL_REG_RMA_INTR 0x1000
1507#define ADV_CTRL_REG_RES_BIT14 0x2000
1508#define ADV_CTRL_REG_DPE_INTR 0x4000
1509#define ADV_CTRL_REG_POWER_DONE 0x8000
1510#define ADV_CTRL_REG_ANY_INTR 0xFF00
1511
1512#define ADV_CTRL_REG_CMD_RESET 0x00C6
1513#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1514#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1515#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1516#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1517
1518#define ADV_TICKLE_NOP 0x00
1519#define ADV_TICKLE_A 0x01
1520#define ADV_TICKLE_B 0x02
1521#define ADV_TICKLE_C 0x03
1522
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523#define AdvIsIntPending(port) \
1524 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1525
1526/*
1527 * SCSI_CFG0 Register bit definitions
1528 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001529#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1530#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1531#define EVEN_PARITY 0x1000 /* Select Even Parity */
1532#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1533#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1534#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1535#define SCAM_EN 0x0080 /* Enable SCAM selection */
1536#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1537#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1538#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1539#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
1541/*
1542 * SCSI_CFG1 Register bit definitions
1543 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001544#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1545#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1546#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1547#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1548#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1549#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1550#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1551#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1552#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1553#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1554#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1555#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1556#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1557#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1558#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
1560/*
1561 * Addendum for ASC-38C0800 Chip
1562 *
1563 * The ASC-38C1600 Chip uses the same definitions except that the
1564 * bus mode override bits [12:10] have been moved to byte register
1565 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1566 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1567 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1568 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1569 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1570 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001571#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1572#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1573#define HVD 0x1000 /* HVD Device Detect */
1574#define LVD 0x0800 /* LVD Device Detect */
1575#define SE 0x0400 /* SE Device Detect */
1576#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1577#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1578#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1579#define TERM_SE 0x0030 /* SE Termination Bits */
1580#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1581#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1582#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1583#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1584#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1585#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1586#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1587#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589#define CABLE_ILLEGAL_A 0x7
1590 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1591
1592#define CABLE_ILLEGAL_B 0xB
1593 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1594
1595/*
1596 * MEM_CFG Register bit definitions
1597 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001598#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1599#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1600#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1601#define RAM_SZ_2KB 0x00 /* 2 KB */
1602#define RAM_SZ_4KB 0x04 /* 4 KB */
1603#define RAM_SZ_8KB 0x08 /* 8 KB */
1604#define RAM_SZ_16KB 0x0C /* 16 KB */
1605#define RAM_SZ_32KB 0x10 /* 32 KB */
1606#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
1608/*
1609 * DMA_CFG0 Register bit definitions
1610 *
1611 * This register is only accessible to the host.
1612 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001613#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1614#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1615#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1616#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1617#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1618#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1619#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1620#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1621#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1622#define START_CTL 0x0C /* DMA start conditions */
1623#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1624#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1625#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1626#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1627#define READ_CMD 0x03 /* Memory Read Method */
1628#define READ_CMD_MR 0x00 /* Memory Read */
1629#define READ_CMD_MRL 0x02 /* Memory Read Long */
1630#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
1632/*
1633 * ASC-38C0800 RAM BIST Register bit definitions
1634 */
1635#define RAM_TEST_MODE 0x80
1636#define PRE_TEST_MODE 0x40
1637#define NORMAL_MODE 0x00
1638#define RAM_TEST_DONE 0x10
1639#define RAM_TEST_STATUS 0x0F
1640#define RAM_TEST_HOST_ERROR 0x08
1641#define RAM_TEST_INTRAM_ERROR 0x04
1642#define RAM_TEST_RISC_ERROR 0x02
1643#define RAM_TEST_SCSI_ERROR 0x01
1644#define RAM_TEST_SUCCESS 0x00
1645#define PRE_TEST_VALUE 0x05
1646#define NORMAL_VALUE 0x00
1647
1648/*
1649 * ASC38C1600 Definitions
1650 *
1651 * IOPB_PCI_INT_CFG Bit Field Definitions
1652 */
1653
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001654#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
1656/*
1657 * Bit 1 can be set to change the interrupt for the Function to operate in
1658 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1659 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1660 * mode, otherwise the operating mode is undefined.
1661 */
1662#define TOTEMPOLE 0x02
1663
1664/*
1665 * Bit 0 can be used to change the Int Pin for the Function. The value is
1666 * 0 by default for both Functions with Function 0 using INT A and Function
1667 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1668 * INT A is used.
1669 *
1670 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1671 * value specified in the PCI Configuration Space.
1672 */
1673#define INTAB 0x01
1674
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675/*
1676 * Adv Library Status Definitions
1677 */
1678#define ADV_TRUE 1
1679#define ADV_FALSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680#define ADV_SUCCESS 1
1681#define ADV_BUSY 0
1682#define ADV_ERROR (-1)
1683
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684/*
1685 * ADV_DVC_VAR 'warn_code' values
1686 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001687#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1688#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1689#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001690#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001692#define ADV_MAX_TID 15 /* max. target identifier */
1693#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
1695/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 * Fixed locations of microcode operating variables.
1697 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001698#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1699#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1700#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1701#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1702#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1703#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1704#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1705#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1706#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1707#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1708#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1709#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1710#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711#define ASC_MC_CHIP_TYPE 0x009A
1712#define ASC_MC_INTRB_CODE 0x009B
1713#define ASC_MC_WDTR_ABLE 0x009C
1714#define ASC_MC_SDTR_ABLE 0x009E
1715#define ASC_MC_TAGQNG_ABLE 0x00A0
1716#define ASC_MC_DISC_ENABLE 0x00A2
1717#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1718#define ASC_MC_IDLE_CMD 0x00A6
1719#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1720#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1721#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1722#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1723#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1724#define ASC_MC_SDTR_DONE 0x00B6
1725#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1726#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1727#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001728#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001730#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731#define ASC_MC_ICQ 0x0160
1732#define ASC_MC_IRQ 0x0164
1733#define ASC_MC_PPR_ABLE 0x017A
1734
1735/*
1736 * BIOS LRAM variable absolute offsets.
1737 */
1738#define BIOS_CODESEG 0x54
1739#define BIOS_CODELEN 0x56
1740#define BIOS_SIGNATURE 0x58
1741#define BIOS_VERSION 0x5A
1742
1743/*
1744 * Microcode Control Flags
1745 *
1746 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1747 * and handled by the microcode.
1748 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001749#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1750#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
1752/*
1753 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1754 */
1755#define HSHK_CFG_WIDE_XFR 0x8000
1756#define HSHK_CFG_RATE 0x0F00
1757#define HSHK_CFG_OFFSET 0x001F
1758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001759#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1760#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1761#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1762#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001764#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
1765#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
1766#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
1767#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
1768#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001770#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
1771#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
1772#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
1773#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
1774#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775/*
1776 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
1777 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
1778 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001779#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
1780#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
1782/*
1783 * All fields here are accessed by the board microcode and need to be
1784 * little-endian.
1785 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001786typedef struct adv_carr_t {
1787 ADV_VADDR carr_va; /* Carrier Virtual Address */
1788 ADV_PADDR carr_pa; /* Carrier Physical Address */
1789 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
1790 /*
1791 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
1792 *
1793 * next_vpa [3:1] Reserved Bits
1794 * next_vpa [0] Done Flag set in Response Queue.
1795 */
1796 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797} ADV_CARR_T;
1798
1799/*
1800 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
1801 */
1802#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
1803
1804#define ASC_RQ_DONE 0x00000001
1805#define ASC_RQ_GOOD 0x00000002
1806#define ASC_CQ_STOPPER 0x00000000
1807
1808#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
1809
1810#define ADV_CARRIER_NUM_PAGE_CROSSING \
1811 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
1812 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1813
1814#define ADV_CARRIER_BUFSIZE \
1815 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
1816
1817/*
1818 * ASC_SCSI_REQ_Q 'a_flag' definitions
1819 *
1820 * The Adv Library should limit use to the lower nibble (4 bits) of
1821 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
1822 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001823#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
1824#define ADV_SCSIQ_DONE 0x02 /* request done */
1825#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001827#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
1828#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
1829#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
1831/*
1832 * Adapter temporary configuration structure
1833 *
1834 * This structure can be discarded after initialization. Don't add
1835 * fields here needed after initialization.
1836 *
1837 * Field naming convention:
1838 *
1839 * *_enable indicates the field enables or disables a feature. The
1840 * value of the field is never reset.
1841 */
1842typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001843 ushort disc_enable; /* enable disconnection */
1844 uchar chip_version; /* chip version */
1845 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001846 ushort control_flag; /* Microcode Control Flag */
1847 ushort mcode_date; /* Microcode date */
1848 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001849 ushort serial1; /* EEPROM serial number word 1 */
1850 ushort serial2; /* EEPROM serial number word 2 */
1851 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852} ADV_DVC_CFG;
1853
1854struct adv_dvc_var;
1855struct adv_scsi_req_q;
1856
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857/*
1858 * Adapter operation variable structure.
1859 *
1860 * One structure is required per host adapter.
1861 *
1862 * Field naming convention:
1863 *
1864 * *_able indicates both whether a feature should be enabled or disabled
1865 * and whether a device isi capable of the feature. At initialization
1866 * this field may be set, but later if a device is found to be incapable
1867 * of the feature, the field is cleared.
1868 */
1869typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001870 AdvPortAddr iop_base; /* I/O port address */
1871 ushort err_code; /* fatal error code */
1872 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001873 ushort wdtr_able; /* try WDTR for a device */
1874 ushort sdtr_able; /* try SDTR for a device */
1875 ushort ultra_able; /* try SDTR Ultra speed for a device */
1876 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
1877 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
1878 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
1879 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
1880 ushort tagqng_able; /* try tagged queuing with a device */
1881 ushort ppr_able; /* PPR message capable per TID bitmask. */
1882 uchar max_dvc_qng; /* maximum number of tagged commands per device */
1883 ushort start_motor; /* start motor command allowed */
1884 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
1885 uchar chip_no; /* should be assigned by caller */
1886 uchar max_host_qng; /* maximum number of Q'ed command allowed */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001887 ushort no_scam; /* scam_tolerant of EEPROM */
1888 struct asc_board *drv_ptr; /* driver pointer to private structure */
1889 uchar chip_scsi_id; /* chip SCSI target ID */
1890 uchar chip_type;
1891 uchar bist_err_code;
1892 ADV_CARR_T *carrier_buf;
1893 ADV_CARR_T *carr_freelist; /* Carrier free list. */
1894 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
1895 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
1896 ushort carr_pending_cnt; /* Count of pending carriers. */
1897 /*
1898 * Note: The following fields will not be used after initialization. The
1899 * driver may discard the buffer after initialization is done.
1900 */
1901 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902} ADV_DVC_VAR;
1903
1904#define NO_OF_SG_PER_BLOCK 15
1905
1906typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001907 uchar reserved1;
1908 uchar reserved2;
1909 uchar reserved3;
1910 uchar sg_cnt; /* Valid entries in block. */
1911 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
1912 struct {
1913 ADV_PADDR sg_addr; /* SG element address. */
1914 ADV_DCNT sg_count; /* SG element count. */
1915 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916} ADV_SG_BLOCK;
1917
1918/*
1919 * ADV_SCSI_REQ_Q - microcode request structure
1920 *
1921 * All fields in this structure up to byte 60 are used by the microcode.
1922 * The microcode makes assumptions about the size and ordering of fields
1923 * in this structure. Do not change the structure definition here without
1924 * coordinating the change with the microcode.
1925 *
1926 * All fields accessed by microcode must be maintained in little_endian
1927 * order.
1928 */
1929typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001930 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
1931 uchar target_cmd;
1932 uchar target_id; /* Device target identifier. */
1933 uchar target_lun; /* Device target logical unit number. */
1934 ADV_PADDR data_addr; /* Data buffer physical address. */
1935 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
1936 ADV_PADDR sense_addr;
1937 ADV_PADDR carr_pa;
1938 uchar mflag;
1939 uchar sense_len;
1940 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
1941 uchar scsi_cntl;
1942 uchar done_status; /* Completion status. */
1943 uchar scsi_status; /* SCSI status byte. */
1944 uchar host_status; /* Ucode host status. */
1945 uchar sg_working_ix;
1946 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
1947 ADV_PADDR sg_real_addr; /* SG list physical address. */
1948 ADV_PADDR scsiq_rptr;
1949 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
1950 ADV_VADDR scsiq_ptr;
1951 ADV_VADDR carr_va;
1952 /*
1953 * End of microcode structure - 60 bytes. The rest of the structure
1954 * is used by the Adv Library and ignored by the microcode.
1955 */
1956 ADV_VADDR srb_ptr;
1957 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
1958 char *vdata_addr; /* Data buffer virtual address. */
1959 uchar a_flag;
1960 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961} ADV_SCSI_REQ_Q;
1962
1963/*
1964 * Microcode idle loop commands
1965 */
1966#define IDLE_CMD_COMPLETED 0
1967#define IDLE_CMD_STOP_CHIP 0x0001
1968#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
1969#define IDLE_CMD_SEND_INT 0x0004
1970#define IDLE_CMD_ABORT 0x0008
1971#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001972#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
1973#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974#define IDLE_CMD_SCSIREQ 0x0080
1975
1976#define IDLE_CMD_STATUS_SUCCESS 0x0001
1977#define IDLE_CMD_STATUS_FAILURE 0x0002
1978
1979/*
1980 * AdvSendIdleCmd() flag definitions.
1981 */
1982#define ADV_NOWAIT 0x01
1983
1984/*
1985 * Wait loop time out values.
1986 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001987#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
1988#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001989#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001991#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
1992#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
1993#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
1994#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001996#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998/* Read byte from a register. */
1999#define AdvReadByteRegister(iop_base, reg_off) \
2000 (ADV_MEM_READB((iop_base) + (reg_off)))
2001
2002/* Write byte to a register. */
2003#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2004 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2005
2006/* Read word (2 bytes) from a register. */
2007#define AdvReadWordRegister(iop_base, reg_off) \
2008 (ADV_MEM_READW((iop_base) + (reg_off)))
2009
2010/* Write word (2 bytes) to a register. */
2011#define AdvWriteWordRegister(iop_base, reg_off, word) \
2012 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2013
2014/* Write dword (4 bytes) to a register. */
2015#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2016 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2017
2018/* Read byte from LRAM. */
2019#define AdvReadByteLram(iop_base, addr, byte) \
2020do { \
2021 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2022 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2023} while (0)
2024
2025/* Write byte to LRAM. */
2026#define AdvWriteByteLram(iop_base, addr, byte) \
2027 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2028 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2029
2030/* Read word (2 bytes) from LRAM. */
2031#define AdvReadWordLram(iop_base, addr, word) \
2032do { \
2033 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2034 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2035} while (0)
2036
2037/* Write word (2 bytes) to LRAM. */
2038#define AdvWriteWordLram(iop_base, addr, word) \
2039 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2040 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2041
2042/* Write little-endian double word (4 bytes) to LRAM */
2043/* Because of unspecified C language ordering don't use auto-increment. */
2044#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2045 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2046 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2047 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2048 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2049 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2050 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2051
2052/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2053#define AdvReadWordAutoIncLram(iop_base) \
2054 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2055
2056/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2057#define AdvWriteWordAutoIncLram(iop_base, word) \
2058 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2059
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060/*
2061 * Define macro to check for Condor signature.
2062 *
2063 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2064 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2065 */
2066#define AdvFindSignature(iop_base) \
2067 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2068 ADV_CHIP_ID_BYTE) && \
2069 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2070 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2071
2072/*
2073 * Define macro to Return the version number of the chip at 'iop_base'.
2074 *
2075 * The second parameter 'bus_type' is currently unused.
2076 */
2077#define AdvGetChipVersion(iop_base, bus_type) \
2078 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2079
2080/*
2081 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2082 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2083 *
2084 * If the request has not yet been sent to the device it will simply be
2085 * aborted from RISC memory. If the request is disconnected it will be
2086 * aborted on reselection by sending an Abort Message to the target ID.
2087 *
2088 * Return value:
2089 * ADV_TRUE(1) - Queue was successfully aborted.
2090 * ADV_FALSE(0) - Queue was not found on the active queue list.
2091 */
2092#define AdvAbortQueue(asc_dvc, scsiq) \
2093 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2094 (ADV_DCNT) (scsiq))
2095
2096/*
2097 * Send a Bus Device Reset Message to the specified target ID.
2098 *
2099 * All outstanding commands will be purged if sending the
2100 * Bus Device Reset Message is successful.
2101 *
2102 * Return Value:
2103 * ADV_TRUE(1) - All requests on the target are purged.
2104 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2105 * are not purged.
2106 */
2107#define AdvResetDevice(asc_dvc, target_id) \
2108 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2109 (ADV_DCNT) (target_id))
2110
2111/*
2112 * SCSI Wide Type definition.
2113 */
2114#define ADV_SCSI_BIT_ID_TYPE ushort
2115
2116/*
2117 * AdvInitScsiTarget() 'cntl_flag' options.
2118 */
2119#define ADV_SCAN_LUN 0x01
2120#define ADV_CAPINFO_NOLUN 0x02
2121
2122/*
2123 * Convert target id to target id bit mask.
2124 */
2125#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2126
2127/*
2128 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2129 */
2130
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002131#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132#define QD_NO_ERROR 0x01
2133#define QD_ABORTED_BY_HOST 0x02
2134#define QD_WITH_ERROR 0x04
2135
2136#define QHSTA_NO_ERROR 0x00
2137#define QHSTA_M_SEL_TIMEOUT 0x11
2138#define QHSTA_M_DATA_OVER_RUN 0x12
2139#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2140#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002141#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2142#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2143#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2144#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2145#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2146#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2147#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002149#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2150#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2151#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2152#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2153#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2154#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2155#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2156#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157#define QHSTA_M_WTM_TIMEOUT 0x41
2158#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2159#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2160#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002161#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2162#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2163#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164
2165/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 * DvcGetPhyAddr() flag arguments
2167 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002168#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2169#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2170#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2171#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2172#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2173#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174
2175/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2176#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2177#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2178#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2179
2180/*
2181 * Total contiguous memory needed for driver SG blocks.
2182 *
2183 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2184 * number of scatter-gather elements the driver supports in a
2185 * single request.
2186 */
2187
2188#define ADV_SG_LIST_MAX_BYTE_SIZE \
2189 (sizeof(ADV_SG_BLOCK) * \
2190 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2191
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002192/* struct asc_board flags */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002193#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194
2195#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002197#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002199#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
2201#ifdef CONFIG_PROC_FS
2202/* /proc/scsi/advansys/[0...] related definitions */
2203#define ASC_PRTBUF_SIZE 2048
2204#define ASC_PRTLINE_SIZE 160
2205
2206#define ASC_PRT_NEXT() \
2207 if (cp) { \
2208 totlen += len; \
2209 leftlen -= len; \
2210 if (leftlen == 0) { \
2211 return totlen; \
2212 } \
2213 cp += len; \
2214 }
2215#endif /* CONFIG_PROC_FS */
2216
2217/* Asc Library return codes */
2218#define ASC_TRUE 1
2219#define ASC_FALSE 0
2220#define ASC_NOERROR 1
2221#define ASC_BUSY 0
2222#define ASC_ERROR (-1)
2223
2224/* struct scsi_cmnd function return codes */
2225#define STATUS_BYTE(byte) (byte)
2226#define MSG_BYTE(byte) ((byte) << 8)
2227#define HOST_BYTE(byte) ((byte) << 16)
2228#define DRIVER_BYTE(byte) ((byte) << 24)
2229
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002230#define ASC_STATS(shost, counter) ASC_STATS_ADD(shost, counter, 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002232#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002234#define ASC_STATS_ADD(shost, counter, count) \
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002235 (((struct asc_board *) shost_priv(shost))->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236#endif /* ADVANSYS_STATS */
2237
2238#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2239
2240/* If the result wraps when calculating tenths, return 0. */
2241#define ASC_TENTHS(num, den) \
2242 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2243 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2244
2245/*
2246 * Display a message to the console.
2247 */
2248#define ASC_PRINT(s) \
2249 { \
2250 printk("advansys: "); \
2251 printk(s); \
2252 }
2253
2254#define ASC_PRINT1(s, a1) \
2255 { \
2256 printk("advansys: "); \
2257 printk((s), (a1)); \
2258 }
2259
2260#define ASC_PRINT2(s, a1, a2) \
2261 { \
2262 printk("advansys: "); \
2263 printk((s), (a1), (a2)); \
2264 }
2265
2266#define ASC_PRINT3(s, a1, a2, a3) \
2267 { \
2268 printk("advansys: "); \
2269 printk((s), (a1), (a2), (a3)); \
2270 }
2271
2272#define ASC_PRINT4(s, a1, a2, a3, a4) \
2273 { \
2274 printk("advansys: "); \
2275 printk((s), (a1), (a2), (a3), (a4)); \
2276 }
2277
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278#ifndef ADVANSYS_DEBUG
2279
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002280#define ASC_DBG(lvl, s...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2283#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2284#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2285#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2286#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2287#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2288#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2289#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2290
2291#else /* ADVANSYS_DEBUG */
2292
2293/*
2294 * Debugging Message Levels:
2295 * 0: Errors Only
2296 * 1: High-Level Tracing
2297 * 2-N: Verbose Tracing
2298 */
2299
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002300#define ASC_DBG(lvl, format, arg...) { \
2301 if (asc_dbglvl >= (lvl)) \
2302 printk(KERN_DEBUG "%s: %s: " format, DRV_NAME, \
2303 __FUNCTION__ , ## arg); \
2304}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
2306#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2307 { \
2308 if (asc_dbglvl >= (lvl)) { \
2309 asc_prt_scsi_host(s); \
2310 } \
2311 }
2312
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2314 { \
2315 if (asc_dbglvl >= (lvl)) { \
2316 asc_prt_asc_scsi_q(scsiqp); \
2317 } \
2318 }
2319
2320#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2321 { \
2322 if (asc_dbglvl >= (lvl)) { \
2323 asc_prt_asc_qdone_info(qdone); \
2324 } \
2325 }
2326
2327#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2328 { \
2329 if (asc_dbglvl >= (lvl)) { \
2330 asc_prt_adv_scsi_req_q(scsiqp); \
2331 } \
2332 }
2333
2334#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2335 { \
2336 if (asc_dbglvl >= (lvl)) { \
2337 asc_prt_hex((name), (start), (length)); \
2338 } \
2339 }
2340
2341#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2342 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2343
2344#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2345 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2346
2347#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2348 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2349#endif /* ADVANSYS_DEBUG */
2350
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351#ifdef ADVANSYS_STATS
2352
2353/* Per board statistics structure */
2354struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002355 /* Driver Entrypoint Statistics */
2356 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2357 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2358 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2359 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2360 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2361 ADV_DCNT done; /* # calls to request's scsi_done function */
2362 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2363 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2364 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2365 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2366 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2367 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2368 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2369 ADV_DCNT exe_unknown; /* # unknown returns. */
2370 /* Data Transfer Statistics */
2371 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2372 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2373 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2374 ADV_DCNT sg_elem; /* # scatter-gather elements */
2375 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376};
2377#endif /* ADVANSYS_STATS */
2378
2379/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 * Adv Library Request Structures
2381 *
2382 * The following two structures are used to process Wide Board requests.
2383 *
2384 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2385 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2386 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2387 * Mid-Level SCSI request structure.
2388 *
2389 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2390 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2391 * up to 255 scatter-gather elements may be used per request or
2392 * ADV_SCSI_REQ_Q.
2393 *
2394 * Both structures must be 32 byte aligned.
2395 */
2396typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002397 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2398 uchar align[32]; /* Sgblock structure padding. */
2399 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400} adv_sgblk_t;
2401
2402typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002403 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2404 uchar align[32]; /* Request structure padding. */
2405 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2406 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2407 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408} adv_req_t;
2409
2410/*
2411 * Structure allocated for each board.
2412 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002413 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 * of the 'Scsi_Host' structure starting at the 'hostdata'
2415 * field. It is guaranteed to be allocated from DMA-able memory.
2416 */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002417struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002418 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002419 int id; /* Board Id */
2420 uint flags; /* Board flags */
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002421 unsigned int irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002422 union {
2423 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2424 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2425 } dvc_var;
2426 union {
2427 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2428 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2429 } dvc_cfg;
2430 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002431 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002432 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2433 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2434 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2435 union {
2436 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2437 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2438 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2439 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2440 } eep_config;
2441 ulong last_reset; /* Saved last reset time */
2442 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002443 /* /proc/scsi/advansys/[0...] */
2444 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002446 struct asc_stats asc_stats; /* Board statistics */
2447#endif /* ADVANSYS_STATS */
2448 /*
2449 * The following fields are used only for Narrow Boards.
2450 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002451 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2452 /*
2453 * The following fields are used only for Wide Boards.
2454 */
2455 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2456 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002457 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002458 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2459 adv_req_t *adv_reqp; /* Request structures. */
2460 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2461 ushort bios_signature; /* BIOS Signature. */
2462 ushort bios_version; /* BIOS Version. */
2463 ushort bios_codeseg; /* BIOS Code Segment. */
2464 ushort bios_codelen; /* BIOS Code Segment Length. */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002465};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002467#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2468 dvc_var.adv_dvc_var)
2469#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2470
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002472static int asc_board_count;
2473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002475static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002478static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002481 * asc_prt_asc_dvc_var()
2482 */
2483static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
2484{
2485 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
2486
2487 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
2488 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
2489
2490 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
2491 (unsigned)h->init_sdtr);
2492
2493 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
2494 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
2495 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
2496 (unsigned)h->chip_no);
2497
2498 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
2499 "%u,\n", (unsigned)h->queue_full_or_busy,
2500 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
2501
2502 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
2503 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
2504 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
2505 (unsigned)h->in_critical_cnt);
2506
2507 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
2508 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
2509 (unsigned)h->init_state, (unsigned)h->no_scam,
2510 (unsigned)h->pci_fix_asyn_xfer);
2511
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002512 printk(" cfg 0x%lx\n", (ulong)h->cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002513}
2514
2515/*
2516 * asc_prt_asc_dvc_cfg()
2517 */
2518static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
2519{
2520 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
2521
2522 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
2523 h->can_tagged_qng, h->cmd_qng_enabled);
2524 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
2525 h->disc_enable, h->sdtr_enable);
2526
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04002527 printk(" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, "
2528 "chip_version %d,\n", h->chip_scsi_id, h->isa_dma_speed,
2529 h->isa_dma_channel, h->chip_version);
Matthew Wilcox51219352007-10-02 21:55:22 -04002530
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002531 printk(" mcode_date 0x%x, mcode_version %d, overrun_buf 0x%p\n",
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04002532 h->mcode_date, h->mcode_version, h->overrun_buf);
Matthew Wilcox51219352007-10-02 21:55:22 -04002533}
2534
2535/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002536 * asc_prt_adv_dvc_var()
2537 *
2538 * Display an ADV_DVC_VAR structure.
2539 */
2540static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
2541{
2542 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
2543
2544 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
2545 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
2546
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002547 printk(" sdtr_able 0x%x, wdtr_able 0x%x\n",
2548 (unsigned)h->sdtr_able, (unsigned)h->wdtr_able);
Matthew Wilcox51219352007-10-02 21:55:22 -04002549
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002550 printk(" start_motor 0x%x, scsi_reset_wait 0x%x\n",
2551 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Matthew Wilcox51219352007-10-02 21:55:22 -04002552
2553 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
2554 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
2555 (ulong)h->carr_freelist);
2556
2557 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
2558 (ulong)h->icq_sp, (ulong)h->irq_sp);
2559
2560 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
2561 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
2562
2563 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
2564 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
2565}
2566
2567/*
2568 * asc_prt_adv_dvc_cfg()
2569 *
2570 * Display an ADV_DVC_CFG structure.
2571 */
2572static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
2573{
2574 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
2575
2576 printk(" disc_enable 0x%x, termination 0x%x\n",
2577 h->disc_enable, h->termination);
2578
2579 printk(" chip_version 0x%x, mcode_date 0x%x\n",
2580 h->chip_version, h->mcode_date);
2581
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002582 printk(" mcode_version 0x%x, control_flag 0x%x\n",
2583 h->mcode_version, h->control_flag);
Matthew Wilcox51219352007-10-02 21:55:22 -04002584}
2585
2586/*
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002587 * asc_prt_scsi_host()
Matthew Wilcox51219352007-10-02 21:55:22 -04002588 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002589static void asc_prt_scsi_host(struct Scsi_Host *s)
Matthew Wilcox51219352007-10-02 21:55:22 -04002590{
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002591 struct asc_board *boardp = shost_priv(s);
Matthew Wilcox51219352007-10-02 21:55:22 -04002592
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002593 printk("Scsi_Host at addr 0x%p, device %s\n", s, boardp->dev->bus_id);
2594 printk(" host_busy %u, host_no %d, last_reset %d,\n",
2595 s->host_busy, s->host_no, (unsigned)s->last_reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04002596
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002597 printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
2598 (ulong)s->base, (ulong)s->io_port, boardp->irq);
Matthew Wilcox51219352007-10-02 21:55:22 -04002599
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002600 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
2601 s->dma_channel, s->this_id, s->can_queue);
Matthew Wilcox51219352007-10-02 21:55:22 -04002602
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002603 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
2604 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Matthew Wilcox51219352007-10-02 21:55:22 -04002605
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002606 if (ASC_NARROW_BOARD(boardp)) {
2607 asc_prt_asc_dvc_var(&boardp->dvc_var.asc_dvc_var);
2608 asc_prt_asc_dvc_cfg(&boardp->dvc_cfg.asc_dvc_cfg);
2609 } else {
2610 asc_prt_adv_dvc_var(&boardp->dvc_var.adv_dvc_var);
2611 asc_prt_adv_dvc_cfg(&boardp->dvc_cfg.adv_dvc_cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002612 }
2613}
2614
2615/*
2616 * asc_prt_hex()
2617 *
2618 * Print hexadecimal output in 4 byte groupings 32 bytes
2619 * or 8 double-words per line.
2620 */
2621static void asc_prt_hex(char *f, uchar *s, int l)
2622{
2623 int i;
2624 int j;
2625 int k;
2626 int m;
2627
2628 printk("%s: (%d bytes)\n", f, l);
2629
2630 for (i = 0; i < l; i += 32) {
2631
2632 /* Display a maximum of 8 double-words per line. */
2633 if ((k = (l - i) / 4) >= 8) {
2634 k = 8;
2635 m = 0;
2636 } else {
2637 m = (l - i) % 4;
2638 }
2639
2640 for (j = 0; j < k; j++) {
2641 printk(" %2.2X%2.2X%2.2X%2.2X",
2642 (unsigned)s[i + (j * 4)],
2643 (unsigned)s[i + (j * 4) + 1],
2644 (unsigned)s[i + (j * 4) + 2],
2645 (unsigned)s[i + (j * 4) + 3]);
2646 }
2647
2648 switch (m) {
2649 case 0:
2650 default:
2651 break;
2652 case 1:
2653 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
2654 break;
2655 case 2:
2656 printk(" %2.2X%2.2X",
2657 (unsigned)s[i + (j * 4)],
2658 (unsigned)s[i + (j * 4) + 1]);
2659 break;
2660 case 3:
2661 printk(" %2.2X%2.2X%2.2X",
2662 (unsigned)s[i + (j * 4) + 1],
2663 (unsigned)s[i + (j * 4) + 2],
2664 (unsigned)s[i + (j * 4) + 3]);
2665 break;
2666 }
2667
2668 printk("\n");
2669 }
2670}
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002671
2672/*
2673 * asc_prt_asc_scsi_q()
2674 */
2675static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
2676{
2677 ASC_SG_HEAD *sgp;
2678 int i;
2679
2680 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
2681
2682 printk
2683 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
2684 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
2685 q->q2.tag_code);
2686
2687 printk
2688 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2689 (ulong)le32_to_cpu(q->q1.data_addr),
2690 (ulong)le32_to_cpu(q->q1.data_cnt),
2691 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
2692
2693 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
2694 (ulong)q->cdbptr, q->q2.cdb_len,
2695 (ulong)q->sg_head, q->q1.sg_queue_cnt);
2696
2697 if (q->sg_head) {
2698 sgp = q->sg_head;
2699 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
2700 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
2701 sgp->queue_cnt);
2702 for (i = 0; i < sgp->entry_cnt; i++) {
2703 printk(" [%u]: addr 0x%lx, bytes %lu\n",
2704 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
2705 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
2706 }
2707
2708 }
2709}
2710
2711/*
2712 * asc_prt_asc_qdone_info()
2713 */
2714static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
2715{
2716 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
2717 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
2718 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
2719 q->d2.tag_code);
2720 printk
2721 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
2722 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
2723}
2724
2725/*
2726 * asc_prt_adv_sgblock()
2727 *
2728 * Display an ADV_SG_BLOCK structure.
2729 */
2730static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
2731{
2732 int i;
2733
2734 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
2735 (ulong)b, sgblockno);
2736 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
2737 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
2738 BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
2739 if (b->sg_ptr != 0)
2740 BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
2741 for (i = 0; i < b->sg_cnt; i++) {
2742 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
2743 i, (ulong)b->sg_list[i].sg_addr,
2744 (ulong)b->sg_list[i].sg_count);
2745 }
2746}
2747
2748/*
2749 * asc_prt_adv_scsi_req_q()
2750 *
2751 * Display an ADV_SCSI_REQ_Q structure.
2752 */
2753static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
2754{
2755 int sg_blk_cnt;
2756 struct asc_sg_block *sg_ptr;
2757
2758 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
2759
2760 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
2761 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
2762
2763 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
2764 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
2765
2766 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2767 (ulong)le32_to_cpu(q->data_cnt),
2768 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
2769
2770 printk
2771 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
2772 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
2773
2774 printk(" sg_working_ix 0x%x, target_cmd %u\n",
2775 q->sg_working_ix, q->target_cmd);
2776
2777 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
2778 (ulong)le32_to_cpu(q->scsiq_rptr),
2779 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
2780
2781 /* Display the request's ADV_SG_BLOCK structures. */
2782 if (q->sg_list_ptr != NULL) {
2783 sg_blk_cnt = 0;
2784 while (1) {
2785 /*
2786 * 'sg_ptr' is a physical address. Convert it to a virtual
2787 * address by indexing 'sg_blk_cnt' into the virtual address
2788 * array 'sg_list_ptr'.
2789 *
2790 * XXX - Assumes all SG physical blocks are virtually contiguous.
2791 */
2792 sg_ptr =
2793 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
2794 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
2795 if (sg_ptr->sg_ptr == 0) {
2796 break;
2797 }
2798 sg_blk_cnt++;
2799 }
2800 }
2801}
Matthew Wilcox51219352007-10-02 21:55:22 -04002802#endif /* ADVANSYS_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
2804/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 * advansys_info()
2806 *
2807 * Return suitable for printing on the console with the argument
2808 * adapter's configuration information.
2809 *
2810 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
2811 * otherwise the static 'info' array will be overrun.
2812 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002813static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002815 static char info[ASC_INFO_SIZE];
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002816 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002817 ASC_DVC_VAR *asc_dvc_varp;
2818 ADV_DVC_VAR *adv_dvc_varp;
2819 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002820 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002822 if (ASC_NARROW_BOARD(boardp)) {
2823 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002824 ASC_DBG(1, "begin\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002825 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
2826 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
2827 ASC_IS_ISAPNP) {
2828 busname = "ISA PnP";
2829 } else {
2830 busname = "ISA";
2831 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002832 sprintf(info,
2833 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
2834 ASC_VERSION, busname,
2835 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002836 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002837 boardp->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002838 } else {
2839 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
2840 busname = "VL";
2841 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
2842 busname = "EISA";
2843 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
2844 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
2845 == ASC_IS_PCI_ULTRA) {
2846 busname = "PCI Ultra";
2847 } else {
2848 busname = "PCI";
2849 }
2850 } else {
2851 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002852 ASC_PRINT2("advansys_info: board %d: unknown "
2853 "bus type %d\n", boardp->id,
2854 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002855 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002856 sprintf(info,
2857 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002858 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002859 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002860 boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002861 }
2862 } else {
2863 /*
2864 * Wide Adapter Information
2865 *
2866 * Memory-mapped I/O is used instead of I/O space to access
2867 * the adapter, but display the I/O Port range. The Memory
2868 * I/O address is displayed through the driver /proc file.
2869 */
2870 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
2871 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002872 widename = "Ultra-Wide";
2873 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002874 widename = "Ultra2-Wide";
2875 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002876 widename = "Ultra3-Wide";
2877 }
2878 sprintf(info,
2879 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
2880 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002881 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002882 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002883 BUG_ON(strlen(info) >= ASC_INFO_SIZE);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002884 ASC_DBG(1, "end\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002885 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886}
2887
Matthew Wilcox51219352007-10-02 21:55:22 -04002888#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002890 * asc_prt_line()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 *
Matthew Wilcox51219352007-10-02 21:55:22 -04002892 * If 'cp' is NULL print to the console, otherwise print to a buffer.
2893 *
2894 * Return 0 if printing to the console, otherwise return the number of
2895 * bytes written to the buffer.
2896 *
2897 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
2898 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 */
Matthew Wilcox51219352007-10-02 21:55:22 -04002900static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901{
Matthew Wilcox51219352007-10-02 21:55:22 -04002902 va_list args;
2903 int ret;
2904 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905
Matthew Wilcox51219352007-10-02 21:55:22 -04002906 va_start(args, fmt);
2907 ret = vsprintf(s, fmt, args);
2908 BUG_ON(ret >= ASC_PRTLINE_SIZE);
2909 if (buf == NULL) {
2910 (void)printk(s);
2911 ret = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002912 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04002913 ret = min(buflen, ret);
2914 memcpy(buf, s, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002915 }
Matthew Wilcox51219352007-10-02 21:55:22 -04002916 va_end(args);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002917 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918}
2919
2920/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 * asc_prt_board_devices()
2922 *
2923 * Print driver information for devices attached to the board.
2924 *
2925 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
2926 * cf. asc_prt_line().
2927 *
2928 * Return the number of characters copied into 'cp'. No more than
2929 * 'cplen' characters will be copied to 'cp'.
2930 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002931static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002933 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002934 int leftlen;
2935 int totlen;
2936 int len;
2937 int chip_scsi_id;
2938 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002940 leftlen = cplen;
2941 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002943 len = asc_prt_line(cp, leftlen,
2944 "\nDevice Information for AdvanSys SCSI Host %d:\n",
2945 shost->host_no);
2946 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002948 if (ASC_NARROW_BOARD(boardp)) {
2949 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
2950 } else {
2951 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
2952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002954 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
2955 ASC_PRT_NEXT();
2956 for (i = 0; i <= ADV_MAX_TID; i++) {
2957 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
2958 len = asc_prt_line(cp, leftlen, " %X,", i);
2959 ASC_PRT_NEXT();
2960 }
2961 }
2962 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
2963 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002965 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966}
2967
2968/*
2969 * Display Wide Board BIOS Information.
2970 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002971static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002973 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002974 int leftlen;
2975 int totlen;
2976 int len;
2977 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002979 leftlen = cplen;
2980 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002982 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
2983 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002985 /*
2986 * If the BIOS saved a valid signature, then fill in
2987 * the BIOS code segment base address.
2988 */
2989 if (boardp->bios_signature != 0x55AA) {
2990 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
2991 ASC_PRT_NEXT();
2992 len = asc_prt_line(cp, leftlen,
2993 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
2994 ASC_PRT_NEXT();
2995 len = asc_prt_line(cp, leftlen,
2996 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
2997 ASC_PRT_NEXT();
2998 } else {
2999 major = (boardp->bios_version >> 12) & 0xF;
3000 minor = (boardp->bios_version >> 8) & 0xF;
3001 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003003 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
3004 major, minor,
3005 letter >= 26 ? '?' : letter + 'A');
3006 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003008 /*
3009 * Current available ROM BIOS release is 3.1I for UW
3010 * and 3.2I for U2W. This code doesn't differentiate
3011 * UW and U2W boards.
3012 */
3013 if (major < 3 || (major <= 3 && minor < 1) ||
3014 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
3015 len = asc_prt_line(cp, leftlen,
3016 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
3017 ASC_PRT_NEXT();
3018 len = asc_prt_line(cp, leftlen,
3019 "ftp://ftp.connectcom.net/pub\n");
3020 ASC_PRT_NEXT();
3021 }
3022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003024 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025}
3026
3027/*
3028 * Add serial number to information bar if signature AAh
3029 * is found in at bit 15-9 (7 bits) of word 1.
3030 *
3031 * Serial Number consists fo 12 alpha-numeric digits.
3032 *
3033 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
3034 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
3035 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
3036 * 5 - Product revision (A-J) Word0: " "
3037 *
3038 * Signature Word1: 15-9 (7 bits)
3039 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
3040 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
3041 *
3042 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
3043 *
3044 * Note 1: Only production cards will have a serial number.
3045 *
3046 * Note 2: Signature is most significant 7 bits (0xFE).
3047 *
3048 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
3049 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003050static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003052 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003054 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
3055 return ASC_FALSE;
3056 } else {
3057 /*
3058 * First word - 6 digits.
3059 */
3060 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003062 /* Product type - 1st digit. */
3063 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
3064 /* Product type is P=Prototype */
3065 *cp += 0x8;
3066 }
3067 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003069 /* Manufacturing location - 2nd digit. */
3070 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003072 /* Product ID - 3rd, 4th digits. */
3073 num = w & 0x3FF;
3074 *cp++ = '0' + (num / 100);
3075 num %= 100;
3076 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003078 /* Product revision - 5th digit. */
3079 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003081 /*
3082 * Second word
3083 */
3084 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003086 /*
3087 * Year - 6th digit.
3088 *
3089 * If bit 15 of third word is set, then the
3090 * last digit of the year is greater than 7.
3091 */
3092 if (serialnum[2] & 0x8000) {
3093 *cp++ = '8' + ((w & 0x1C0) >> 6);
3094 } else {
3095 *cp++ = '0' + ((w & 0x1C0) >> 6);
3096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003098 /* Week of year - 7th, 8th digits. */
3099 num = w & 0x003F;
3100 *cp++ = '0' + num / 10;
3101 num %= 10;
3102 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003104 /*
3105 * Third word
3106 */
3107 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003109 /* Serial number - 9th digit. */
3110 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003112 /* 10th, 11th, 12th digits. */
3113 num = w % 1000;
3114 *cp++ = '0' + num / 100;
3115 num %= 100;
3116 *cp++ = '0' + num / 10;
3117 num %= 10;
3118 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003120 *cp = '\0'; /* Null Terminate the string. */
3121 return ASC_TRUE;
3122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123}
3124
3125/*
3126 * asc_prt_asc_board_eeprom()
3127 *
3128 * Print board EEPROM configuration.
3129 *
3130 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3131 * cf. asc_prt_line().
3132 *
3133 * Return the number of characters copied into 'cp'. No more than
3134 * 'cplen' characters will be copied to 'cp'.
3135 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003136static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003138 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003139 ASC_DVC_VAR *asc_dvc_varp;
3140 int leftlen;
3141 int totlen;
3142 int len;
3143 ASCEEP_CONFIG *ep;
3144 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003146 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003148 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003150 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3151 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003153 leftlen = cplen;
3154 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003156 len = asc_prt_line(cp, leftlen,
3157 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3158 shost->host_no);
3159 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003161 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
3162 == ASC_TRUE) {
3163 len =
3164 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3165 serialstr);
3166 ASC_PRT_NEXT();
3167 } else {
3168 if (ep->adapter_info[5] == 0xBB) {
3169 len = asc_prt_line(cp, leftlen,
3170 " Default Settings Used for EEPROM-less Adapter.\n");
3171 ASC_PRT_NEXT();
3172 } else {
3173 len = asc_prt_line(cp, leftlen,
3174 " Serial Number Signature Not Present.\n");
3175 ASC_PRT_NEXT();
3176 }
3177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003179 len = asc_prt_line(cp, leftlen,
3180 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3181 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
3182 ep->max_tag_qng);
3183 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003185 len = asc_prt_line(cp, leftlen,
3186 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
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, " Target ID: ");
3190 ASC_PRT_NEXT();
3191 for (i = 0; i <= ASC_MAX_TID; i++) {
3192 len = asc_prt_line(cp, leftlen, " %d", i);
3193 ASC_PRT_NEXT();
3194 }
3195 len = asc_prt_line(cp, leftlen, "\n");
3196 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003198 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3199 ASC_PRT_NEXT();
3200 for (i = 0; i <= ASC_MAX_TID; i++) {
3201 len = asc_prt_line(cp, leftlen, " %c",
3202 (ep->
3203 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3204 'N');
3205 ASC_PRT_NEXT();
3206 }
3207 len = asc_prt_line(cp, leftlen, "\n");
3208 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003210 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3211 ASC_PRT_NEXT();
3212 for (i = 0; i <= ASC_MAX_TID; i++) {
3213 len = asc_prt_line(cp, leftlen, " %c",
3214 (ep->
3215 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3216 'N');
3217 ASC_PRT_NEXT();
3218 }
3219 len = asc_prt_line(cp, leftlen, "\n");
3220 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003222 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3223 ASC_PRT_NEXT();
3224 for (i = 0; i <= ASC_MAX_TID; i++) {
3225 len = asc_prt_line(cp, leftlen, " %c",
3226 (ep->
3227 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3228 'N');
3229 ASC_PRT_NEXT();
3230 }
3231 len = asc_prt_line(cp, leftlen, "\n");
3232 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003234 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3235 ASC_PRT_NEXT();
3236 for (i = 0; i <= ASC_MAX_TID; i++) {
3237 len = asc_prt_line(cp, leftlen, " %c",
3238 (ep->
3239 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3240 'N');
3241 ASC_PRT_NEXT();
3242 }
3243 len = asc_prt_line(cp, leftlen, "\n");
3244 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
3246#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003247 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3248 len = asc_prt_line(cp, leftlen,
3249 " Host ISA DMA speed: %d MB/S\n",
3250 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
3251 ASC_PRT_NEXT();
3252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253#endif /* CONFIG_ISA */
3254
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003255 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256}
3257
3258/*
3259 * asc_prt_adv_board_eeprom()
3260 *
3261 * Print board EEPROM configuration.
3262 *
3263 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3264 * cf. asc_prt_line().
3265 *
3266 * Return the number of characters copied into 'cp'. No more than
3267 * 'cplen' characters will be copied to 'cp'.
3268 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003269static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003271 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003272 ADV_DVC_VAR *adv_dvc_varp;
3273 int leftlen;
3274 int totlen;
3275 int len;
3276 int i;
3277 char *termstr;
3278 uchar serialstr[13];
3279 ADVEEP_3550_CONFIG *ep_3550 = NULL;
3280 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
3281 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
3282 ushort word;
3283 ushort *wordp;
3284 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003286 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3287 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3288 ep_3550 = &boardp->eep_config.adv_3550_eep;
3289 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3290 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
3291 } else {
3292 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
3293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003295 leftlen = cplen;
3296 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003298 len = asc_prt_line(cp, leftlen,
3299 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3300 shost->host_no);
3301 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003303 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3304 wordp = &ep_3550->serial_number_word1;
3305 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3306 wordp = &ep_38C0800->serial_number_word1;
3307 } else {
3308 wordp = &ep_38C1600->serial_number_word1;
3309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003311 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
3312 len =
3313 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3314 serialstr);
3315 ASC_PRT_NEXT();
3316 } else {
3317 len = asc_prt_line(cp, leftlen,
3318 " Serial Number Signature Not Present.\n");
3319 ASC_PRT_NEXT();
3320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003322 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3323 len = asc_prt_line(cp, leftlen,
3324 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3325 ep_3550->adapter_scsi_id,
3326 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
3327 ASC_PRT_NEXT();
3328 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3329 len = asc_prt_line(cp, leftlen,
3330 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3331 ep_38C0800->adapter_scsi_id,
3332 ep_38C0800->max_host_qng,
3333 ep_38C0800->max_dvc_qng);
3334 ASC_PRT_NEXT();
3335 } else {
3336 len = asc_prt_line(cp, leftlen,
3337 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3338 ep_38C1600->adapter_scsi_id,
3339 ep_38C1600->max_host_qng,
3340 ep_38C1600->max_dvc_qng);
3341 ASC_PRT_NEXT();
3342 }
3343 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3344 word = ep_3550->termination;
3345 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3346 word = ep_38C0800->termination_lvd;
3347 } else {
3348 word = ep_38C1600->termination_lvd;
3349 }
3350 switch (word) {
3351 case 1:
3352 termstr = "Low Off/High Off";
3353 break;
3354 case 2:
3355 termstr = "Low Off/High On";
3356 break;
3357 case 3:
3358 termstr = "Low On/High On";
3359 break;
3360 default:
3361 case 0:
3362 termstr = "Automatic";
3363 break;
3364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003366 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3367 len = asc_prt_line(cp, leftlen,
3368 " termination: %u (%s), bios_ctrl: 0x%x\n",
3369 ep_3550->termination, termstr,
3370 ep_3550->bios_ctrl);
3371 ASC_PRT_NEXT();
3372 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3373 len = asc_prt_line(cp, leftlen,
3374 " termination: %u (%s), bios_ctrl: 0x%x\n",
3375 ep_38C0800->termination_lvd, termstr,
3376 ep_38C0800->bios_ctrl);
3377 ASC_PRT_NEXT();
3378 } else {
3379 len = asc_prt_line(cp, leftlen,
3380 " termination: %u (%s), bios_ctrl: 0x%x\n",
3381 ep_38C1600->termination_lvd, termstr,
3382 ep_38C1600->bios_ctrl);
3383 ASC_PRT_NEXT();
3384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003386 len = asc_prt_line(cp, leftlen, " Target ID: ");
3387 ASC_PRT_NEXT();
3388 for (i = 0; i <= ADV_MAX_TID; i++) {
3389 len = asc_prt_line(cp, leftlen, " %X", i);
3390 ASC_PRT_NEXT();
3391 }
3392 len = asc_prt_line(cp, leftlen, "\n");
3393 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003395 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3396 word = ep_3550->disc_enable;
3397 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3398 word = ep_38C0800->disc_enable;
3399 } else {
3400 word = ep_38C1600->disc_enable;
3401 }
3402 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3403 ASC_PRT_NEXT();
3404 for (i = 0; i <= ADV_MAX_TID; i++) {
3405 len = asc_prt_line(cp, leftlen, " %c",
3406 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3407 ASC_PRT_NEXT();
3408 }
3409 len = asc_prt_line(cp, leftlen, "\n");
3410 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003412 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3413 word = ep_3550->tagqng_able;
3414 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3415 word = ep_38C0800->tagqng_able;
3416 } else {
3417 word = ep_38C1600->tagqng_able;
3418 }
3419 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3420 ASC_PRT_NEXT();
3421 for (i = 0; i <= ADV_MAX_TID; i++) {
3422 len = asc_prt_line(cp, leftlen, " %c",
3423 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3424 ASC_PRT_NEXT();
3425 }
3426 len = asc_prt_line(cp, leftlen, "\n");
3427 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003429 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3430 word = ep_3550->start_motor;
3431 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3432 word = ep_38C0800->start_motor;
3433 } else {
3434 word = ep_38C1600->start_motor;
3435 }
3436 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3437 ASC_PRT_NEXT();
3438 for (i = 0; i <= ADV_MAX_TID; i++) {
3439 len = asc_prt_line(cp, leftlen, " %c",
3440 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3441 ASC_PRT_NEXT();
3442 }
3443 len = asc_prt_line(cp, leftlen, "\n");
3444 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003446 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3447 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3448 ASC_PRT_NEXT();
3449 for (i = 0; i <= ADV_MAX_TID; i++) {
3450 len = asc_prt_line(cp, leftlen, " %c",
3451 (ep_3550->
3452 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
3453 'Y' : 'N');
3454 ASC_PRT_NEXT();
3455 }
3456 len = asc_prt_line(cp, leftlen, "\n");
3457 ASC_PRT_NEXT();
3458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003460 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3461 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
3462 ASC_PRT_NEXT();
3463 for (i = 0; i <= ADV_MAX_TID; i++) {
3464 len = asc_prt_line(cp, leftlen, " %c",
3465 (ep_3550->
3466 ultra_able & ADV_TID_TO_TIDMASK(i))
3467 ? 'Y' : 'N');
3468 ASC_PRT_NEXT();
3469 }
3470 len = asc_prt_line(cp, leftlen, "\n");
3471 ASC_PRT_NEXT();
3472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003474 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3475 word = ep_3550->wdtr_able;
3476 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3477 word = ep_38C0800->wdtr_able;
3478 } else {
3479 word = ep_38C1600->wdtr_able;
3480 }
3481 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
3482 ASC_PRT_NEXT();
3483 for (i = 0; i <= ADV_MAX_TID; i++) {
3484 len = asc_prt_line(cp, leftlen, " %c",
3485 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3486 ASC_PRT_NEXT();
3487 }
3488 len = asc_prt_line(cp, leftlen, "\n");
3489 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003491 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
3492 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
3493 len = asc_prt_line(cp, leftlen,
3494 " Synchronous Transfer Speed (Mhz):\n ");
3495 ASC_PRT_NEXT();
3496 for (i = 0; i <= ADV_MAX_TID; i++) {
3497 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003499 if (i == 0) {
3500 sdtr_speed = adv_dvc_varp->sdtr_speed1;
3501 } else if (i == 4) {
3502 sdtr_speed = adv_dvc_varp->sdtr_speed2;
3503 } else if (i == 8) {
3504 sdtr_speed = adv_dvc_varp->sdtr_speed3;
3505 } else if (i == 12) {
3506 sdtr_speed = adv_dvc_varp->sdtr_speed4;
3507 }
3508 switch (sdtr_speed & ADV_MAX_TID) {
3509 case 0:
3510 speed_str = "Off";
3511 break;
3512 case 1:
3513 speed_str = " 5";
3514 break;
3515 case 2:
3516 speed_str = " 10";
3517 break;
3518 case 3:
3519 speed_str = " 20";
3520 break;
3521 case 4:
3522 speed_str = " 40";
3523 break;
3524 case 5:
3525 speed_str = " 80";
3526 break;
3527 default:
3528 speed_str = "Unk";
3529 break;
3530 }
3531 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
3532 ASC_PRT_NEXT();
3533 if (i == 7) {
3534 len = asc_prt_line(cp, leftlen, "\n ");
3535 ASC_PRT_NEXT();
3536 }
3537 sdtr_speed >>= 4;
3538 }
3539 len = asc_prt_line(cp, leftlen, "\n");
3540 ASC_PRT_NEXT();
3541 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003543 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544}
3545
3546/*
3547 * asc_prt_driver_conf()
3548 *
3549 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3550 * cf. asc_prt_line().
3551 *
3552 * Return the number of characters copied into 'cp'. No more than
3553 * 'cplen' characters will be copied to 'cp'.
3554 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003555static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003557 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003558 int leftlen;
3559 int totlen;
3560 int len;
3561 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003563 leftlen = cplen;
3564 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003566 len = asc_prt_line(cp, leftlen,
3567 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
3568 shost->host_no);
3569 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003571 len = asc_prt_line(cp, leftlen,
3572 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
3573 shost->host_busy, shost->last_reset, shost->max_id,
3574 shost->max_lun, shost->max_channel);
3575 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003577 len = asc_prt_line(cp, leftlen,
3578 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
3579 shost->unique_id, shost->can_queue, shost->this_id,
3580 shost->sg_tablesize, shost->cmd_per_lun);
3581 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003583 len = asc_prt_line(cp, leftlen,
3584 " unchecked_isa_dma %d, use_clustering %d\n",
3585 shost->unchecked_isa_dma, shost->use_clustering);
3586 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003588 len = asc_prt_line(cp, leftlen,
3589 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
3590 boardp->flags, boardp->last_reset, jiffies,
3591 boardp->asc_n_io_port);
3592 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003594 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003595 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003597 if (ASC_NARROW_BOARD(boardp)) {
3598 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3599 } else {
3600 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003603 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604}
3605
3606/*
3607 * asc_prt_asc_board_info()
3608 *
3609 * Print dynamic board configuration information.
3610 *
3611 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3612 * cf. asc_prt_line().
3613 *
3614 * Return the number of characters copied into 'cp'. No more than
3615 * 'cplen' characters will be copied to 'cp'.
3616 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003617static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003619 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003620 int chip_scsi_id;
3621 int leftlen;
3622 int totlen;
3623 int len;
3624 ASC_DVC_VAR *v;
3625 ASC_DVC_CFG *c;
3626 int i;
3627 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003629 v = &boardp->dvc_var.asc_dvc_var;
3630 c = &boardp->dvc_cfg.asc_dvc_cfg;
3631 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003633 leftlen = cplen;
3634 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003636 len = asc_prt_line(cp, leftlen,
3637 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3638 shost->host_no);
3639 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04003641 len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
3642 "mcode_version 0x%x, err_code %u\n",
3643 c->chip_version, c->mcode_date, c->mcode_version,
3644 v->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003645 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003647 /* Current number of commands waiting for the host. */
3648 len = asc_prt_line(cp, leftlen,
3649 " Total Command Pending: %d\n", v->cur_total_qng);
3650 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003652 len = asc_prt_line(cp, leftlen, " Command Queuing:");
3653 ASC_PRT_NEXT();
3654 for (i = 0; i <= ASC_MAX_TID; i++) {
3655 if ((chip_scsi_id == i) ||
3656 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3657 continue;
3658 }
3659 len = asc_prt_line(cp, leftlen, " %X:%c",
3660 i,
3661 (v->
3662 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
3663 'Y' : 'N');
3664 ASC_PRT_NEXT();
3665 }
3666 len = asc_prt_line(cp, leftlen, "\n");
3667 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003669 /* Current number of commands waiting for a device. */
3670 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
3671 ASC_PRT_NEXT();
3672 for (i = 0; i <= ASC_MAX_TID; i++) {
3673 if ((chip_scsi_id == i) ||
3674 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3675 continue;
3676 }
3677 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
3678 ASC_PRT_NEXT();
3679 }
3680 len = asc_prt_line(cp, leftlen, "\n");
3681 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003683 /* Current limit on number of commands that can be sent to a device. */
3684 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
3685 ASC_PRT_NEXT();
3686 for (i = 0; i <= ASC_MAX_TID; i++) {
3687 if ((chip_scsi_id == i) ||
3688 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3689 continue;
3690 }
3691 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
3692 ASC_PRT_NEXT();
3693 }
3694 len = asc_prt_line(cp, leftlen, "\n");
3695 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003697 /* Indicate whether the device has returned queue full status. */
3698 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
3699 ASC_PRT_NEXT();
3700 for (i = 0; i <= ASC_MAX_TID; i++) {
3701 if ((chip_scsi_id == i) ||
3702 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3703 continue;
3704 }
3705 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
3706 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
3707 i, boardp->queue_full_cnt[i]);
3708 } else {
3709 len = asc_prt_line(cp, leftlen, " %X:N", i);
3710 }
3711 ASC_PRT_NEXT();
3712 }
3713 len = asc_prt_line(cp, leftlen, "\n");
3714 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003716 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3717 ASC_PRT_NEXT();
3718 for (i = 0; i <= ASC_MAX_TID; i++) {
3719 if ((chip_scsi_id == i) ||
3720 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3721 continue;
3722 }
3723 len = asc_prt_line(cp, leftlen, " %X:%c",
3724 i,
3725 (v->
3726 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3727 'N');
3728 ASC_PRT_NEXT();
3729 }
3730 len = asc_prt_line(cp, leftlen, "\n");
3731 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003733 for (i = 0; i <= ASC_MAX_TID; i++) {
3734 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003736 if ((chip_scsi_id == i) ||
3737 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3738 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
3739 continue;
3740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003742 len = asc_prt_line(cp, leftlen, " %X:", i);
3743 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003745 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
3746 len = asc_prt_line(cp, leftlen, " Asynchronous");
3747 ASC_PRT_NEXT();
3748 } else {
3749 syn_period_ix =
3750 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
3751 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003753 len = asc_prt_line(cp, leftlen,
3754 " Transfer Period Factor: %d (%d.%d Mhz),",
3755 v->sdtr_period_tbl[syn_period_ix],
3756 250 /
3757 v->sdtr_period_tbl[syn_period_ix],
3758 ASC_TENTHS(250,
3759 v->
3760 sdtr_period_tbl
3761 [syn_period_ix]));
3762 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003764 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
3765 boardp->
3766 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
3767 ASC_PRT_NEXT();
3768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003770 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3771 len = asc_prt_line(cp, leftlen, "*\n");
3772 renegotiate = 1;
3773 } else {
3774 len = asc_prt_line(cp, leftlen, "\n");
3775 }
3776 ASC_PRT_NEXT();
3777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003779 if (renegotiate) {
3780 len = asc_prt_line(cp, leftlen,
3781 " * = Re-negotiation pending before next command.\n");
3782 ASC_PRT_NEXT();
3783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003785 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786}
3787
3788/*
3789 * asc_prt_adv_board_info()
3790 *
3791 * Print dynamic board configuration information.
3792 *
3793 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3794 * cf. asc_prt_line().
3795 *
3796 * Return the number of characters copied into 'cp'. No more than
3797 * 'cplen' characters will be copied to 'cp'.
3798 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003799static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003801 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003802 int leftlen;
3803 int totlen;
3804 int len;
3805 int i;
3806 ADV_DVC_VAR *v;
3807 ADV_DVC_CFG *c;
3808 AdvPortAddr iop_base;
3809 ushort chip_scsi_id;
3810 ushort lramword;
3811 uchar lrambyte;
3812 ushort tagqng_able;
3813 ushort sdtr_able, wdtr_able;
3814 ushort wdtr_done, sdtr_done;
3815 ushort period = 0;
3816 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003818 v = &boardp->dvc_var.adv_dvc_var;
3819 c = &boardp->dvc_cfg.adv_dvc_cfg;
3820 iop_base = v->iop_base;
3821 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003823 leftlen = cplen;
3824 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003826 len = asc_prt_line(cp, leftlen,
3827 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3828 shost->host_no);
3829 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003831 len = asc_prt_line(cp, leftlen,
3832 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
3833 v->iop_base,
3834 AdvReadWordRegister(iop_base,
3835 IOPW_SCSI_CFG1) & CABLE_DETECT,
3836 v->err_code);
3837 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04003839 len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
3840 "mcode_version 0x%x\n", c->chip_version,
3841 c->mcode_date, c->mcode_version);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003842 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003844 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
3845 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
3846 ASC_PRT_NEXT();
3847 for (i = 0; i <= ADV_MAX_TID; i++) {
3848 if ((chip_scsi_id == i) ||
3849 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3850 continue;
3851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003853 len = asc_prt_line(cp, leftlen, " %X:%c",
3854 i,
3855 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3856 'N');
3857 ASC_PRT_NEXT();
3858 }
3859 len = asc_prt_line(cp, leftlen, "\n");
3860 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003862 len = asc_prt_line(cp, leftlen, " Queue Limit:");
3863 ASC_PRT_NEXT();
3864 for (i = 0; i <= ADV_MAX_TID; i++) {
3865 if ((chip_scsi_id == i) ||
3866 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3867 continue;
3868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003870 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
3871 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003873 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3874 ASC_PRT_NEXT();
3875 }
3876 len = asc_prt_line(cp, leftlen, "\n");
3877 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003879 len = asc_prt_line(cp, leftlen, " Command Pending:");
3880 ASC_PRT_NEXT();
3881 for (i = 0; i <= ADV_MAX_TID; i++) {
3882 if ((chip_scsi_id == i) ||
3883 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3884 continue;
3885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003887 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
3888 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003890 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3891 ASC_PRT_NEXT();
3892 }
3893 len = asc_prt_line(cp, leftlen, "\n");
3894 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003896 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
3897 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
3898 ASC_PRT_NEXT();
3899 for (i = 0; i <= ADV_MAX_TID; i++) {
3900 if ((chip_scsi_id == i) ||
3901 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3902 continue;
3903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003905 len = asc_prt_line(cp, leftlen, " %X:%c",
3906 i,
3907 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3908 'N');
3909 ASC_PRT_NEXT();
3910 }
3911 len = asc_prt_line(cp, leftlen, "\n");
3912 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003914 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
3915 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
3916 ASC_PRT_NEXT();
3917 for (i = 0; i <= ADV_MAX_TID; i++) {
3918 if ((chip_scsi_id == i) ||
3919 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3920 continue;
3921 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003923 AdvReadWordLram(iop_base,
3924 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
3925 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003927 len = asc_prt_line(cp, leftlen, " %X:%d",
3928 i, (lramword & 0x8000) ? 16 : 8);
3929 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003931 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
3932 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3933 len = asc_prt_line(cp, leftlen, "*");
3934 ASC_PRT_NEXT();
3935 renegotiate = 1;
3936 }
3937 }
3938 len = asc_prt_line(cp, leftlen, "\n");
3939 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003941 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
3942 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
3943 ASC_PRT_NEXT();
3944 for (i = 0; i <= ADV_MAX_TID; i++) {
3945 if ((chip_scsi_id == i) ||
3946 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3947 continue;
3948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003950 len = asc_prt_line(cp, leftlen, " %X:%c",
3951 i,
3952 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3953 'N');
3954 ASC_PRT_NEXT();
3955 }
3956 len = asc_prt_line(cp, leftlen, "\n");
3957 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003959 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
3960 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003962 AdvReadWordLram(iop_base,
3963 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
3964 lramword);
3965 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003967 if ((chip_scsi_id == i) ||
3968 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3969 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
3970 continue;
3971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003973 len = asc_prt_line(cp, leftlen, " %X:", i);
3974 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003976 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
3977 len = asc_prt_line(cp, leftlen, " Asynchronous");
3978 ASC_PRT_NEXT();
3979 } else {
3980 len =
3981 asc_prt_line(cp, leftlen,
3982 " Transfer Period Factor: ");
3983 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003985 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
3986 len =
3987 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
3988 ASC_PRT_NEXT();
3989 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
3990 len =
3991 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
3992 ASC_PRT_NEXT();
3993 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003995 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003997 if (period == 0) { /* Should never happen. */
3998 len =
3999 asc_prt_line(cp, leftlen,
4000 "%d (? Mhz), ");
4001 ASC_PRT_NEXT();
4002 } else {
4003 len = asc_prt_line(cp, leftlen,
4004 "%d (%d.%d Mhz),",
4005 period, 250 / period,
4006 ASC_TENTHS(250,
4007 period));
4008 ASC_PRT_NEXT();
4009 }
4010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004012 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
4013 lramword & 0x1F);
4014 ASC_PRT_NEXT();
4015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004017 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
4018 len = asc_prt_line(cp, leftlen, "*\n");
4019 renegotiate = 1;
4020 } else {
4021 len = asc_prt_line(cp, leftlen, "\n");
4022 }
4023 ASC_PRT_NEXT();
4024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004026 if (renegotiate) {
4027 len = asc_prt_line(cp, leftlen,
4028 " * = Re-negotiation pending before next command.\n");
4029 ASC_PRT_NEXT();
4030 }
4031
4032 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033}
4034
4035/*
4036 * asc_proc_copy()
4037 *
4038 * Copy proc information to a read buffer taking into account the current
4039 * read offset in the file and the remaining space in the read buffer.
4040 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004041static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004043 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004045 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004047 ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004048 (unsigned)offset, (unsigned)advoffset, cplen);
4049 if (offset <= advoffset) {
4050 /* Read offset below current offset, copy everything. */
4051 cnt = min(cplen, leftlen);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004052 ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004053 (ulong)curbuf, (ulong)cp, cnt);
4054 memcpy(curbuf, cp, cnt);
4055 } else if (offset < advoffset + cplen) {
4056 /* Read offset within current range, partial copy. */
4057 cnt = (advoffset + cplen) - offset;
4058 cp = (cp + cplen) - cnt;
4059 cnt = min(cnt, leftlen);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004060 ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004061 (ulong)curbuf, (ulong)cp, cnt);
4062 memcpy(curbuf, cp, cnt);
4063 }
4064 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065}
4066
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067#ifdef ADVANSYS_STATS
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068/*
4069 * asc_prt_board_stats()
4070 *
4071 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4072 * cf. asc_prt_line().
4073 *
4074 * Return the number of characters copied into 'cp'. No more than
4075 * 'cplen' characters will be copied to 'cp'.
4076 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004077static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004079 struct asc_board *boardp = shost_priv(shost);
4080 struct asc_stats *s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004082 int leftlen = cplen;
4083 int len, totlen = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004085 len = asc_prt_line(cp, leftlen,
4086 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
4087 shost->host_no);
4088 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004090 len = asc_prt_line(cp, leftlen,
4091 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
4092 s->queuecommand, s->reset, s->biosparam,
4093 s->interrupt);
4094 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004096 len = asc_prt_line(cp, leftlen,
4097 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
4098 s->callback, s->done, s->build_error,
4099 s->adv_build_noreq, s->adv_build_nosg);
4100 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004102 len = asc_prt_line(cp, leftlen,
4103 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
4104 s->exe_noerror, s->exe_busy, s->exe_error,
4105 s->exe_unknown);
4106 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004108 /*
4109 * Display data transfer statistics.
4110 */
4111 if (s->cont_cnt > 0) {
4112 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
4113 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004115 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
4116 s->cont_xfer / 2,
4117 ASC_TENTHS(s->cont_xfer, 2));
4118 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004120 /* Contiguous transfer average size */
4121 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
4122 (s->cont_xfer / 2) / s->cont_cnt,
4123 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
4124 ASC_PRT_NEXT();
4125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004127 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004129 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
4130 s->sg_cnt, s->sg_elem);
4131 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004133 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
4134 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
4135 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004137 /* Scatter gather transfer statistics */
4138 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
4139 s->sg_elem / s->sg_cnt,
4140 ASC_TENTHS(s->sg_elem, s->sg_cnt));
4141 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004143 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
4144 (s->sg_xfer / 2) / s->sg_elem,
4145 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
4146 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004148 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
4149 (s->sg_xfer / 2) / s->sg_cnt,
4150 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
4151 ASC_PRT_NEXT();
4152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004154 /*
4155 * Display request queuing statistics.
4156 */
4157 len = asc_prt_line(cp, leftlen,
4158 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
4159 HZ);
4160 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004162 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164#endif /* ADVANSYS_STATS */
4165
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166/*
Matthew Wilcox51219352007-10-02 21:55:22 -04004167 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
4168 *
4169 * *buffer: I/O buffer
4170 * **start: if inout == FALSE pointer into buffer where user read should start
4171 * offset: current offset into a /proc/scsi/advansys/[0...] file
4172 * length: length of buffer
4173 * hostno: Scsi_Host host_no
4174 * inout: TRUE - user is writing; FALSE - user is reading
4175 *
4176 * Return the number of bytes read from or written to a
4177 * /proc/scsi/advansys/[0...] file.
4178 *
4179 * Note: This function uses the per board buffer 'prtbuf' which is
4180 * allocated when the board is initialized in advansys_detect(). The
4181 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4182 * used to write to the buffer. The way asc_proc_copy() is written
4183 * if 'prtbuf' is too small it will not be overwritten. Instead the
4184 * user just won't get all the available statistics.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 */
Matthew Wilcox51219352007-10-02 21:55:22 -04004186static int
4187advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
4188 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004190 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04004191 char *cp;
4192 int cplen;
4193 int cnt;
4194 int totcnt;
4195 int leftlen;
4196 char *curbuf;
4197 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004199 ASC_DBG(1, "begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
Matthew Wilcox51219352007-10-02 21:55:22 -04004201 /*
4202 * User write not supported.
4203 */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004204 if (inout == TRUE)
4205 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
Matthew Wilcox51219352007-10-02 21:55:22 -04004207 /*
4208 * User read of /proc/scsi/advansys/[0...] file.
4209 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210
Matthew Wilcox51219352007-10-02 21:55:22 -04004211 /* Copy read data starting at the beginning of the buffer. */
4212 *start = buffer;
4213 curbuf = buffer;
4214 advoffset = 0;
4215 totcnt = 0;
4216 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
Matthew Wilcox51219352007-10-02 21:55:22 -04004218 /*
4219 * Get board configuration information.
4220 *
4221 * advansys_info() returns the board string from its own static buffer.
4222 */
4223 cp = (char *)advansys_info(shost);
4224 strcat(cp, "\n");
4225 cplen = strlen(cp);
4226 /* Copy board information. */
4227 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4228 totcnt += cnt;
4229 leftlen -= cnt;
4230 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004231 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004232 return totcnt;
4233 }
4234 advoffset += cplen;
4235 curbuf += cnt;
4236
4237 /*
4238 * Display Wide Board BIOS Information.
4239 */
Matthew Wilcox9a256fa2007-10-02 21:55:28 -04004240 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004241 cp = boardp->prtbuf;
4242 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
4243 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4244 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4245 cplen);
4246 totcnt += cnt;
4247 leftlen -= cnt;
4248 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004249 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004250 return totcnt;
4251 }
4252 advoffset += cplen;
4253 curbuf += cnt;
4254 }
4255
4256 /*
4257 * Display driver information for each device attached to the board.
4258 */
4259 cp = boardp->prtbuf;
4260 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
4261 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4262 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4263 totcnt += cnt;
4264 leftlen -= cnt;
4265 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004266 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004267 return totcnt;
4268 }
4269 advoffset += cplen;
4270 curbuf += cnt;
4271
4272 /*
4273 * Display EEPROM configuration for the board.
4274 */
4275 cp = boardp->prtbuf;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004276 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004277 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004278 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04004279 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004280 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004281 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4282 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4283 totcnt += cnt;
4284 leftlen -= cnt;
4285 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004286 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004287 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004288 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004289 advoffset += cplen;
4290 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291
Matthew Wilcox51219352007-10-02 21:55:22 -04004292 /*
4293 * Display driver configuration and information for the board.
4294 */
4295 cp = boardp->prtbuf;
4296 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
4297 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4298 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4299 totcnt += cnt;
4300 leftlen -= cnt;
4301 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004302 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004303 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004304 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004305 advoffset += cplen;
4306 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Matthew Wilcox51219352007-10-02 21:55:22 -04004308#ifdef ADVANSYS_STATS
4309 /*
4310 * Display driver statistics for the board.
4311 */
4312 cp = boardp->prtbuf;
4313 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
4314 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4315 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4316 totcnt += cnt;
4317 leftlen -= cnt;
4318 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004319 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004320 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004321 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004322 advoffset += cplen;
4323 curbuf += cnt;
4324#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325
Matthew Wilcox51219352007-10-02 21:55:22 -04004326 /*
4327 * Display Asc Library dynamic configuration information
4328 * for the board.
4329 */
4330 cp = boardp->prtbuf;
4331 if (ASC_NARROW_BOARD(boardp)) {
4332 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
4333 } else {
4334 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004335 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004336 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4337 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4338 totcnt += cnt;
4339 leftlen -= cnt;
4340 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004341 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004342 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004343 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004344 advoffset += cplen;
4345 curbuf += cnt;
4346
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004347 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004348
4349 return totcnt;
4350}
4351#endif /* CONFIG_PROC_FS */
4352
4353static void asc_scsi_done(struct scsi_cmnd *scp)
4354{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004355 struct asc_board *boardp = shost_priv(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04004356
4357 if (scp->use_sg)
4358 dma_unmap_sg(boardp->dev,
4359 (struct scatterlist *)scp->request_buffer,
4360 scp->use_sg, scp->sc_data_direction);
4361 else if (scp->request_bufflen)
4362 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
4363 scp->request_bufflen, scp->sc_data_direction);
4364
4365 ASC_STATS(scp->device->host, done);
4366
4367 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368}
4369
Matthew Wilcox51219352007-10-02 21:55:22 -04004370static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371{
Matthew Wilcox51219352007-10-02 21:55:22 -04004372 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
Matthew Wilcox51219352007-10-02 21:55:22 -04004374 val = AscGetChipControl(iop_base) &
4375 (~
4376 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
4377 CC_CHIP_RESET));
4378 if (bank == 1) {
4379 val |= CC_BANK_ONE;
4380 } else if (bank == 2) {
4381 val |= CC_DIAG | CC_BANK_ONE;
4382 } else {
4383 val &= ~CC_BANK_ONE;
4384 }
4385 AscSetChipControl(iop_base, val);
4386 return;
4387}
4388
4389static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
4390{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004391 AscSetBank(iop_base, 1);
Matthew Wilcox51219352007-10-02 21:55:22 -04004392 AscWriteChipIH(iop_base, ins_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004393 AscSetBank(iop_base, 0);
Matthew Wilcox51219352007-10-02 21:55:22 -04004394 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395}
4396
Matthew Wilcox51219352007-10-02 21:55:22 -04004397static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398{
Matthew Wilcox51219352007-10-02 21:55:22 -04004399 AscSetChipControl(iop_base, 0);
4400 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4401 return (0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004402 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004403 return (1);
4404}
4405
4406static int AscStopChip(PortAddr iop_base)
4407{
4408 uchar cc_val;
4409
4410 cc_val =
4411 AscGetChipControl(iop_base) &
4412 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
4413 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
4414 AscSetChipIH(iop_base, INS_HALT);
4415 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4416 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
4417 return (0);
4418 }
4419 return (1);
4420}
4421
4422static int AscIsChipHalted(PortAddr iop_base)
4423{
4424 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4425 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
4426 return (1);
4427 }
4428 }
4429 return (0);
4430}
4431
4432static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
4433{
4434 PortAddr iop_base;
4435 int i = 10;
4436
4437 iop_base = asc_dvc->iop_base;
4438 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
4439 && (i-- > 0)) {
4440 mdelay(100);
4441 }
4442 AscStopChip(iop_base);
4443 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
4444 udelay(60);
4445 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4446 AscSetChipIH(iop_base, INS_HALT);
4447 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
4448 AscSetChipControl(iop_base, CC_HALT);
4449 mdelay(200);
4450 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
4451 AscSetChipStatus(iop_base, 0);
4452 return (AscIsChipHalted(iop_base));
4453}
4454
4455static int AscFindSignature(PortAddr iop_base)
4456{
4457 ushort sig_word;
4458
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004459 ASC_DBG(1, "AscGetChipSignatureByte(0x%x) 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04004460 iop_base, AscGetChipSignatureByte(iop_base));
4461 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004462 ASC_DBG(1, "AscGetChipSignatureWord(0x%x) 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04004463 iop_base, AscGetChipSignatureWord(iop_base));
4464 sig_word = AscGetChipSignatureWord(iop_base);
4465 if ((sig_word == (ushort)ASC_1000_ID0W) ||
4466 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
4467 return (1);
4468 }
4469 }
4470 return (0);
4471}
4472
4473static void AscEnableInterrupt(PortAddr iop_base)
4474{
4475 ushort cfg;
4476
4477 cfg = AscGetChipCfgLsw(iop_base);
4478 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
4479 return;
4480}
4481
4482static void AscDisableInterrupt(PortAddr iop_base)
4483{
4484 ushort cfg;
4485
4486 cfg = AscGetChipCfgLsw(iop_base);
4487 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
4488 return;
4489}
4490
4491static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
4492{
4493 unsigned char byte_data;
4494 unsigned short word_data;
4495
4496 if (isodd_word(addr)) {
4497 AscSetChipLramAddr(iop_base, addr - 1);
4498 word_data = AscGetChipLramData(iop_base);
4499 byte_data = (word_data >> 8) & 0xFF;
4500 } else {
4501 AscSetChipLramAddr(iop_base, addr);
4502 word_data = AscGetChipLramData(iop_base);
4503 byte_data = word_data & 0xFF;
4504 }
4505 return byte_data;
4506}
4507
4508static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
4509{
4510 ushort word_data;
4511
4512 AscSetChipLramAddr(iop_base, addr);
4513 word_data = AscGetChipLramData(iop_base);
4514 return (word_data);
4515}
4516
4517#if CC_VERY_LONG_SG_LIST
4518static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
4519{
4520 ushort val_low, val_high;
4521 ASC_DCNT dword_data;
4522
4523 AscSetChipLramAddr(iop_base, addr);
4524 val_low = AscGetChipLramData(iop_base);
4525 val_high = AscGetChipLramData(iop_base);
4526 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
4527 return (dword_data);
4528}
4529#endif /* CC_VERY_LONG_SG_LIST */
4530
4531static void
4532AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
4533{
4534 int i;
4535
4536 AscSetChipLramAddr(iop_base, s_addr);
4537 for (i = 0; i < words; i++) {
4538 AscSetChipLramData(iop_base, set_wval);
4539 }
4540}
4541
4542static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
4543{
4544 AscSetChipLramAddr(iop_base, addr);
4545 AscSetChipLramData(iop_base, word_val);
4546 return;
4547}
4548
4549static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
4550{
4551 ushort word_data;
4552
4553 if (isodd_word(addr)) {
4554 addr--;
4555 word_data = AscReadLramWord(iop_base, addr);
4556 word_data &= 0x00FF;
4557 word_data |= (((ushort)byte_val << 8) & 0xFF00);
4558 } else {
4559 word_data = AscReadLramWord(iop_base, addr);
4560 word_data &= 0xFF00;
4561 word_data |= ((ushort)byte_val & 0x00FF);
4562 }
4563 AscWriteLramWord(iop_base, addr, word_data);
4564 return;
4565}
4566
4567/*
4568 * Copy 2 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 written to LRAM.
4572 */
4573static void
4574AscMemWordCopyPtrToLram(PortAddr iop_base,
4575 ushort s_addr, uchar *s_buffer, int words)
4576{
4577 int i;
4578
4579 AscSetChipLramAddr(iop_base, s_addr);
4580 for (i = 0; i < 2 * words; i += 2) {
4581 /*
4582 * On a little-endian system the second argument below
4583 * produces a little-endian ushort which is written to
4584 * LRAM in little-endian order. On a big-endian system
4585 * the second argument produces a big-endian ushort which
4586 * is "transparently" byte-swapped by outpw() and written
4587 * in little-endian order to LRAM.
4588 */
4589 outpw(iop_base + IOP_RAM_DATA,
4590 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
4591 }
4592 return;
4593}
4594
4595/*
4596 * Copy 4 bytes to LRAM.
4597 *
4598 * The source data is assumed to be in little-endian order in memory
4599 * and is maintained in little-endian order when writen to LRAM.
4600 */
4601static void
4602AscMemDWordCopyPtrToLram(PortAddr iop_base,
4603 ushort s_addr, uchar *s_buffer, int dwords)
4604{
4605 int i;
4606
4607 AscSetChipLramAddr(iop_base, s_addr);
4608 for (i = 0; i < 4 * dwords; i += 4) {
4609 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
4610 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
4611 }
4612 return;
4613}
4614
4615/*
4616 * Copy 2 bytes from LRAM.
4617 *
4618 * The source data is assumed to be in little-endian order in LRAM
4619 * and is maintained in little-endian order when written to memory.
4620 */
4621static void
4622AscMemWordCopyPtrFromLram(PortAddr iop_base,
4623 ushort s_addr, uchar *d_buffer, int words)
4624{
4625 int i;
4626 ushort word;
4627
4628 AscSetChipLramAddr(iop_base, s_addr);
4629 for (i = 0; i < 2 * words; i += 2) {
4630 word = inpw(iop_base + IOP_RAM_DATA);
4631 d_buffer[i] = word & 0xff;
4632 d_buffer[i + 1] = (word >> 8) & 0xff;
4633 }
4634 return;
4635}
4636
4637static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
4638{
4639 ASC_DCNT sum;
4640 int i;
4641
4642 sum = 0L;
4643 for (i = 0; i < words; i++, s_addr += 2) {
4644 sum += AscReadLramWord(iop_base, s_addr);
4645 }
4646 return (sum);
4647}
4648
4649static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
4650{
4651 uchar i;
4652 ushort s_addr;
4653 PortAddr iop_base;
4654 ushort warn_code;
4655
4656 iop_base = asc_dvc->iop_base;
4657 warn_code = 0;
4658 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
4659 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
4660 64) >> 1));
4661 i = ASC_MIN_ACTIVE_QNO;
4662 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
4663 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4664 (uchar)(i + 1));
4665 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4666 (uchar)(asc_dvc->max_total_qng));
4667 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4668 (uchar)i);
4669 i++;
4670 s_addr += ASC_QBLK_SIZE;
4671 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
4672 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4673 (uchar)(i + 1));
4674 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4675 (uchar)(i - 1));
4676 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4677 (uchar)i);
4678 }
4679 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4680 (uchar)ASC_QLINK_END);
4681 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4682 (uchar)(asc_dvc->max_total_qng - 1));
4683 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4684 (uchar)asc_dvc->max_total_qng);
4685 i++;
4686 s_addr += ASC_QBLK_SIZE;
4687 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
4688 i++, s_addr += ASC_QBLK_SIZE) {
4689 AscWriteLramByte(iop_base,
4690 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
4691 AscWriteLramByte(iop_base,
4692 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
4693 AscWriteLramByte(iop_base,
4694 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
4695 }
4696 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697}
4698
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004699static ASC_DCNT
4700AscLoadMicroCode(PortAddr iop_base,
4701 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004703 ASC_DCNT chksum;
4704 ushort mcode_word_size;
4705 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004707 /* Write the microcode buffer starting at LRAM address 0. */
4708 mcode_word_size = (ushort)(mcode_size >> 1);
4709 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
4710 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004712 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004713 ASC_DBG(1, "chksum 0x%lx\n", (ulong)chksum);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004714 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
4715 (ushort)ASC_CODE_SEC_BEG,
4716 (ushort)((mcode_size -
4717 s_addr - (ushort)
4718 ASC_CODE_SEC_BEG) /
4719 2));
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004720 ASC_DBG(1, "mcode_chksum 0x%lx\n", (ulong)mcode_chksum);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004721 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
4722 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004723 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724}
4725
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004727static uchar _asc_mcode_buf[] = {
4728 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004729 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
4734 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4735 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004736 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004737 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
4738 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
4739 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004740 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004741 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
4742 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
4743 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004744 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004745 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
4746 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
4747 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004748 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004749 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
4750 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
4751 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004752 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004753 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
4754 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
4755 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004756 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004757 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
4758 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
4759 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004760 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004761 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
4762 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
4763 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004764 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004765 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
4766 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
4767 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004768 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004769 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
4770 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
4771 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004772 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004773 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
4774 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
4775 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004776 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004777 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
4778 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
4779 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004780 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004781 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
4782 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
4783 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004784 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004785 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
4786 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
4787 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004788 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004789 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
4790 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
4791 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004792 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004793 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
4794 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
4795 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004796 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004797 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
4798 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
4799 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004800 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004801 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
4802 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
4803 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004804 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004805 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
4806 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
4807 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004808 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004809 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
4810 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
4811 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004812 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004813 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
4814 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
4815 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004816 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004817 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
4818 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
4819 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004820 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004821 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
4822 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
4823 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004824 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004825 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
4826 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
4827 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004828 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004829 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
4830 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
4831 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004832 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004833 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
4834 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
4835 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004836 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004837 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
4838 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
4839 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004840 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004841 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
4842 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
4843 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004844 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004845 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
4846 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
4847 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004848 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004849 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
4850 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
4851 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004852 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004853 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
4854 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
4855 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004856 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004857 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
4858 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
4859 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004860 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004861 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
4862 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
4863 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004864 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004865 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
4866 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
4867 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004868 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004869 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
4870 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
4871 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004872 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004873 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
4874 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
4875 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004876 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004877 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
4878 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
4879 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004880 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004881 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
4882 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
4883 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004884 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004885 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
4886 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
4887 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004888 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004889 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
4890 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
4891 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004892 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004893 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
4894 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
4895 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004896 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004897 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
4898 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
4899 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004900 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004901 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
4902 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
4903 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004904 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004905 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
4906 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
4907 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004908 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004909 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
4910 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
4911 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004912 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004913 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
4914 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
4915 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004916 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004917 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
4918 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
4919 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920};
4921
Matthew Wilcox51219352007-10-02 21:55:22 -04004922static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004923static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004926static unsigned char _adv_asc3550_buf[] = {
4927 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004928 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
4929 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
4930 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004931 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004932 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
4933 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
4934 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004935 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004936 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
4937 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
4938 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004939 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004940 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
4941 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
4942 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004943 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004944 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
4945 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
4946 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004947 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004948 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
4949 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
4950 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004951 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004952 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
4953 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
4954 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004955 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004956 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
4957 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
4958 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004959 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004960 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
4961 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
4962 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004963 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004964 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
4965 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
4966 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004967 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004968 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
4969 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
4970 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004971 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004972 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
4973 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
4974 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004975 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004976 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
4977 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
4978 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004979 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004980 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
4981 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
4982 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004983 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004984 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
4985 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
4986 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004987 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004988 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
4989 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
4990 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004991 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004992 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
4993 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
4994 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004995 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004996 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
4997 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
4998 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004999 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005000 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
5001 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
5002 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005003 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005004 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
5005 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
5006 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005007 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005008 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
5009 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
5010 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005011 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005012 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
5013 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
5014 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005015 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005016 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
5017 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
5018 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005019 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005020 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
5021 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
5022 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005023 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005024 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
5025 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
5026 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005027 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005028 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
5029 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
5030 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005031 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005032 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
5033 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
5034 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005035 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005036 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
5037 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
5038 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005039 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005040 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
5041 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
5042 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005043 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005044 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
5045 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
5046 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005047 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005048 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
5049 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
5050 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005051 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005052 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
5053 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
5054 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005055 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005056 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
5057 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
5058 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005059 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005060 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
5061 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
5062 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005063 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005064 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
5065 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
5066 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005067 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005068 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
5069 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
5070 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005071 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005072 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5073 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
5074 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005075 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005076 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
5077 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
5078 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005079 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005080 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
5081 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
5082 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005083 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005084 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
5085 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
5086 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005087 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005088 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
5089 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
5090 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005091 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005092 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
5093 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
5094 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005095 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005096 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
5097 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
5098 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005099 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005100 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
5101 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
5102 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005103 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005104 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
5105 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
5106 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005107 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005108 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
5109 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
5110 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005111 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005112 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
5113 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
5114 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005115 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005116 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
5117 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
5118 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005119 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005120 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
5121 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
5122 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005123 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005124 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
5125 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
5126 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005127 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005128 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
5129 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
5130 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005131 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005132 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
5133 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
5134 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005135 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005136 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
5137 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
5138 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005139 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005140 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
5141 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
5142 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005143 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005144 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
5145 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
5146 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005147 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005148 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
5149 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
5150 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005151 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005152 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
5153 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
5154 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005155 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005156 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
5157 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
5158 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005159 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005160 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
5161 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
5162 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005163 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005164 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
5165 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
5166 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005167 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005168 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
5169 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
5170 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005171 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005172 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
5173 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
5174 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005175 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005176 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
5177 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
5178 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005179 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005180 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
5181 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
5182 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005183 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005184 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
5185 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
5186 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005187 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005188 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
5189 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
5190 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005191 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005192 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
5193 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
5194 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005195 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005196 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
5197 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
5198 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005199 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005200 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
5201 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
5202 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005203 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005204 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
5205 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
5206 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005207 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005208 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
5209 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
5210 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005211 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005212 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
5213 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
5214 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005215 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005216 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
5217 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
5218 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005219 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005220 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
5221 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
5222 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005223 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005224 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
5225 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
5226 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005227 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005228 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
5229 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
5230 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005231 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005232 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
5233 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
5234 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005235 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005236 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
5237 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
5238 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005239 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005240 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
5241 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
5242 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005243 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005244 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
5245 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
5246 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005247 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005248 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
5249 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
5250 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005251 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005252 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
5253 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
5254 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005255 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005256 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
5257 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
5258 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005259 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005260 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
5261 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
5262 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005263 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005264 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
5265 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
5266 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005267 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005268 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
5269 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
5270 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005271 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005272 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
5273 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
5274 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005275 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005276 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
5277 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
5278 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005279 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005280 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
5281 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
5282 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005283 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005284 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
5285 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
5286 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005287 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005288 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
5289 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
5290 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005291 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005292 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
5293 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
5294 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005295 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005296 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
5297 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
5298 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005299 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005300 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
5301 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
5302 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005303 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005304 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
5305 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
5306 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005307 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005308 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
5309 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
5310 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005311 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005312 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
5313 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
5314 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005315 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005316 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
5317 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
5318 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005319 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005320 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
5321 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
5322 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005323 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005324 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
5325 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
5326 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005327 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005328 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
5329 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
5330 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005331 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005332 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
5333 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
5334 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005335 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005336 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
5337 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
5338 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005339 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005340 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
5341 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
5342 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005343 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005344 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
5345 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346};
5347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005348static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
5349static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350
5351/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005352static unsigned char _adv_asc38C0800_buf[] = {
5353 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005354 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
5355 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
5356 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005357 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005358 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
5359 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
5360 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005361 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005362 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
5363 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
5364 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005365 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005366 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
5367 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
5368 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005369 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005370 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
5371 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
5372 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005373 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005374 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
5375 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
5376 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005377 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005378 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
5379 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
5380 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005381 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005382 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
5383 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
5384 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005385 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005386 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
5387 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
5388 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005389 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005390 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
5391 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
5392 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005393 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005394 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
5395 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
5396 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005397 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005398 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
5399 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5400 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005401 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005402 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
5403 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
5404 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005405 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005406 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
5407 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5408 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005409 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005410 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
5411 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
5412 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005413 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005414 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
5415 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
5416 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005417 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005418 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
5419 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
5420 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005421 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005422 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
5423 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
5424 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005425 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005426 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
5427 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
5428 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005429 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005430 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
5431 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
5432 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005433 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005434 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
5435 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
5436 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005437 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005438 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
5439 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
5440 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005441 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005442 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
5443 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
5444 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005445 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005446 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
5447 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
5448 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005449 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005450 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
5451 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
5452 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005453 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005454 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
5455 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
5456 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005457 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005458 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
5459 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
5460 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005461 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005462 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
5463 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
5464 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005465 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005466 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
5467 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
5468 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005469 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005470 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
5471 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
5472 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005473 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005474 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
5475 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
5476 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005477 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005478 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
5479 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
5480 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005481 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005482 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
5483 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
5484 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005485 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005486 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
5487 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
5488 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005489 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005490 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
5491 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
5492 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005493 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005494 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
5495 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
5496 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005497 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005498 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
5499 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
5500 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005501 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005502 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
5503 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
5504 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005505 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005506 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
5507 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
5508 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005509 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005510 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
5511 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
5512 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005513 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005514 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
5515 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
5516 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005517 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005518 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
5519 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
5520 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005521 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005522 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
5523 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
5524 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005525 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005526 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
5527 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
5528 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005529 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005530 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
5531 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
5532 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005533 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005534 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
5535 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
5536 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005537 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005538 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
5539 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
5540 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005541 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005542 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
5543 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
5544 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005545 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005546 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
5547 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
5548 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005549 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005550 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
5551 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
5552 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005553 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005554 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
5555 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
5556 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005557 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005558 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
5559 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
5560 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005561 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005562 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
5563 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
5564 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005565 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005566 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
5567 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
5568 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005569 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005570 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
5571 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
5572 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005573 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005574 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
5575 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
5576 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005577 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005578 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
5579 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
5580 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005581 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005582 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
5583 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
5584 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005585 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005586 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
5587 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
5588 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005589 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005590 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
5591 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
5592 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005593 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005594 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
5595 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
5596 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005597 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005598 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
5599 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
5600 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005601 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005602 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
5603 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
5604 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005605 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005606 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
5607 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
5608 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005609 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005610 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
5611 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
5612 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005613 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005614 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
5615 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
5616 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005617 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005618 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
5619 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
5620 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005621 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005622 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
5623 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
5624 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005625 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005626 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
5627 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
5628 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005629 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005630 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
5631 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
5632 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005633 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005634 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
5635 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
5636 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005637 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005638 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
5639 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
5640 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005641 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005642 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
5643 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
5644 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005645 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005646 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
5647 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
5648 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005649 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005650 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
5651 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
5652 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005653 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005654 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
5655 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
5656 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005657 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005658 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
5659 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
5660 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005661 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005662 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
5663 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
5664 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005665 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005666 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
5667 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
5668 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005669 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005670 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
5671 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
5672 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005673 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005674 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
5675 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
5676 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005677 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005678 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
5679 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
5680 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005681 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005682 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
5683 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
5684 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005685 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005686 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
5687 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
5688 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005689 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005690 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
5691 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
5692 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005693 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005694 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
5695 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
5696 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005697 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005698 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
5699 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5700 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005701 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005702 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5703 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
5704 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005705 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005706 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
5707 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
5708 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005709 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005710 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
5711 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
5712 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005713 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005714 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
5715 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
5716 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005717 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005718 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
5719 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
5720 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005721 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005722 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
5723 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
5724 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005725 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005726 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
5727 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
5728 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005729 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005730 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
5731 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
5732 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005733 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005734 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
5735 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
5736 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005737 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005738 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
5739 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
5740 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005741 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005742 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
5743 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
5744 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005745 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005746 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
5747 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
5748 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005749 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005750 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
5751 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
5752 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005753 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005754 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
5755 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
5756 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005757 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005758 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
5759 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
5760 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005761 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005762 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
5763 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
5764 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005765 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005766 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
5767 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
5768 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005769 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005770 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
5771 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
5772 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005773 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005774 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
5775 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
5776 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005777 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005778 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
5779 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
5780 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005781 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005782 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
5783 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
5784 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005785 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005786 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
5787 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
5788 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005789 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005790 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
5791 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
5792 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005793 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005794 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
5795 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
5796 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005797 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798};
5799
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005800static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
5801static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802
5803/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005804static unsigned char _adv_asc38C1600_buf[] = {
5805 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005806 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
5807 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
5808 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005809 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005810 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
5811 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
5812 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005813 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005814 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
5815 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
5816 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005817 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005818 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
5819 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
5820 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005821 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005822 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
5823 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
5824 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005825 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005826 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
5827 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
5828 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005829 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005830 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
5831 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
5832 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005833 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005834 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
5835 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
5836 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005837 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005838 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
5839 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
5840 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005841 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005842 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
5843 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
5844 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005845 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005846 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
5847 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
5848 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005849 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005850 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
5851 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5852 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005853 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005854 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
5855 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
5856 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005857 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005858 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
5859 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
5860 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005861 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005862 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
5863 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
5864 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005865 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005866 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
5867 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
5868 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005869 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005870 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
5871 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
5872 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005873 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005874 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
5875 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
5876 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005877 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005878 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
5879 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
5880 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005881 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005882 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
5883 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
5884 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005885 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005886 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
5887 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
5888 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005889 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005890 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
5891 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
5892 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005893 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005894 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
5895 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
5896 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005897 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005898 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
5899 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
5900 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005901 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005902 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
5903 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
5904 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005905 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005906 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
5907 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
5908 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005909 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005910 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
5911 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
5912 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005913 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005914 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
5915 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
5916 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005917 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005918 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
5919 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
5920 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005921 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005922 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
5923 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
5924 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005925 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005926 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
5927 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
5928 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005929 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005930 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
5931 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
5932 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005933 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005934 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
5935 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
5936 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005937 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005938 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
5939 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
5940 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005941 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005942 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
5943 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
5944 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005945 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005946 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
5947 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
5948 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005949 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005950 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
5951 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
5952 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005953 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005954 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
5955 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
5956 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005957 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005958 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
5959 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
5960 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005961 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005962 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
5963 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
5964 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005965 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005966 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
5967 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
5968 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005969 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005970 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
5971 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5972 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005973 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005974 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
5975 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
5976 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005977 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005978 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
5979 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
5980 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005981 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005982 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
5983 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
5984 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005985 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005986 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
5987 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
5988 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005989 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005990 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
5991 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
5992 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005993 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005994 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
5995 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
5996 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005997 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005998 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
5999 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
6000 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006001 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006002 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
6003 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
6004 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006005 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006006 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
6007 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
6008 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006009 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006010 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
6011 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
6012 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006013 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006014 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
6015 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
6016 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006017 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006018 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
6019 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
6020 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006021 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006022 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
6023 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
6024 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006025 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006026 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
6027 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
6028 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006029 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006030 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
6031 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
6032 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006033 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006034 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
6035 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
6036 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006037 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006038 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
6039 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
6040 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006041 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006042 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
6043 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
6044 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006045 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006046 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
6047 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
6048 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006049 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006050 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
6051 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
6052 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006053 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006054 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
6055 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
6056 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006057 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006058 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
6059 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
6060 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006061 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006062 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
6063 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
6064 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006065 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006066 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
6067 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
6068 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006069 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006070 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
6071 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
6072 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006073 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006074 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
6075 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
6076 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006077 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006078 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
6079 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
6080 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006081 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006082 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
6083 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
6084 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006085 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006086 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
6087 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
6088 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006089 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006090 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
6091 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
6092 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006093 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006094 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
6095 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
6096 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006097 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006098 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
6099 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
6100 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006101 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006102 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
6103 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
6104 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006105 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006106 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
6107 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
6108 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006109 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006110 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
6111 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
6112 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006113 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006114 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
6115 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
6116 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006117 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006118 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
6119 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
6120 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006121 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006122 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
6123 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
6124 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006125 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006126 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
6127 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
6128 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006129 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006130 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
6131 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
6132 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006133 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006134 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
6135 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
6136 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006137 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006138 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
6139 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
6140 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006141 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006142 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
6143 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
6144 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006145 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006146 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
6147 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
6148 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006149 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006150 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
6151 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
6152 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006153 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006154 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
6155 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
6156 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006157 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006158 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
6159 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
6160 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006161 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006162 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
6163 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
6164 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006165 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006166 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
6167 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
6168 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006169 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006170 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
6171 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
6172 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006173 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006174 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
6175 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
6176 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006177 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006178 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
6179 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
6180 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006181 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006182 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
6183 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
6184 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006185 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006186 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
6187 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
6188 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006189 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006190 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
6191 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
6192 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006193 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006194 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
6195 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
6196 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006197 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006198 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
6199 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
6200 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006201 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006202 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
6203 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
6204 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006205 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006206 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
6207 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
6208 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006209 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006210 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
6211 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
6212 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006213 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006214 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
6215 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
6216 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006217 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006218 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
6219 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
6220 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006221 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006222 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
6223 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
6224 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006225 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006226 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
6227 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
6228 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006229 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006230 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
6231 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
6232 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006233 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006234 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
6235 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
6236 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006237 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006238 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
6239 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
6240 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006241 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006242 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
6243 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
6244 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006245 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006246 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
6247 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
6248 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006249 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006250 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
6251 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
6252 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006253 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006254 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
6255 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
6256 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006257 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006258 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
6259 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
6260 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006261 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006262 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
6263 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
6264 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006265 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006266 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
6267 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
6268 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006269 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006270 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
6271 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
6272 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006273 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006274 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
6275 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
6276 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006277 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006278 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
6279 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
6280 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006281 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006282 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
6283 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
6284 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006285 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006286 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
6287 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
6288 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006289 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006290 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
6291 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
6292 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006293 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006294 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
6295 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
6296 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006297 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006298 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
6299 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
6300 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006301 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006302 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
6303 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
6304 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006305 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006306 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
6307 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
6308 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006309 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006310 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
6311 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
6312 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006313 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006314 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
6315 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
6316 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006317 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006318 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
6319 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
6320 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006321 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006322 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
6323 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
6324 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006325 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006326 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
6327 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
6328 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006329 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006330 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
6331 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
6332 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006333};
6334
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006335static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
6336static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337
Matthew Wilcox51219352007-10-02 21:55:22 -04006338static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006339{
Matthew Wilcox51219352007-10-02 21:55:22 -04006340 PortAddr iop_base;
6341 int i;
6342 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006343
Matthew Wilcox51219352007-10-02 21:55:22 -04006344 iop_base = asc_dvc->iop_base;
6345 AscPutRiscVarFreeQHead(iop_base, 1);
6346 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6347 AscPutVarFreeQHead(iop_base, 1);
6348 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6349 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6350 (uchar)((int)asc_dvc->max_total_qng + 1));
6351 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6352 (uchar)((int)asc_dvc->max_total_qng + 2));
6353 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
6354 asc_dvc->max_total_qng);
6355 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6356 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6357 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6358 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6359 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6360 AscPutQDoneInProgress(iop_base, 0);
6361 lram_addr = ASC_QADR_BEG;
6362 for (i = 0; i < 32; i++, lram_addr += 2) {
6363 AscWriteLramWord(iop_base, lram_addr, 0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006365}
6366
Matthew Wilcox51219352007-10-02 21:55:22 -04006367static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006368{
Matthew Wilcox51219352007-10-02 21:55:22 -04006369 int i;
6370 ushort warn_code;
6371 PortAddr iop_base;
6372 ASC_PADDR phy_addr;
6373 ASC_DCNT phy_size;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006374
Matthew Wilcox51219352007-10-02 21:55:22 -04006375 iop_base = asc_dvc->iop_base;
6376 warn_code = 0;
6377 for (i = 0; i <= ASC_MAX_TID; i++) {
6378 AscPutMCodeInitSDTRAtID(iop_base, i,
6379 asc_dvc->cfg->sdtr_period_offset[i]);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006380 }
6381
Matthew Wilcox51219352007-10-02 21:55:22 -04006382 AscInitQLinkVar(asc_dvc);
6383 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
6384 asc_dvc->cfg->disc_enable);
6385 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
6386 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006387
Matthew Wilcox51219352007-10-02 21:55:22 -04006388 /* Align overrun buffer on an 8 byte boundary. */
6389 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
6390 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
6391 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
6392 (uchar *)&phy_addr, 1);
6393 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
6394 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
6395 (uchar *)&phy_size, 1);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006396
Matthew Wilcox51219352007-10-02 21:55:22 -04006397 asc_dvc->cfg->mcode_date =
6398 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
6399 asc_dvc->cfg->mcode_version =
6400 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006401
Matthew Wilcox51219352007-10-02 21:55:22 -04006402 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6403 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6404 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
6405 return warn_code;
6406 }
6407 if (AscStartChip(iop_base) != 1) {
6408 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
6409 return warn_code;
6410 }
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006411
Matthew Wilcox51219352007-10-02 21:55:22 -04006412 return warn_code;
6413}
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006414
Matthew Wilcox51219352007-10-02 21:55:22 -04006415static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
6416{
6417 ushort warn_code;
6418 PortAddr iop_base;
6419
6420 iop_base = asc_dvc->iop_base;
6421 warn_code = 0;
6422 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
6423 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
6424 AscResetChipAndScsiBus(asc_dvc);
6425 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6426 }
6427 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
6428 if (asc_dvc->err_code != 0)
6429 return UW_ERR;
6430 if (!AscFindSignature(asc_dvc->iop_base)) {
6431 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
6432 return warn_code;
6433 }
6434 AscDisableInterrupt(iop_base);
6435 warn_code |= AscInitLram(asc_dvc);
6436 if (asc_dvc->err_code != 0)
6437 return UW_ERR;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04006438 ASC_DBG(1, "_asc_mcode_chksum 0x%lx\n", (ulong)_asc_mcode_chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -04006439 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
6440 _asc_mcode_size) != _asc_mcode_chksum) {
6441 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
6442 return warn_code;
6443 }
6444 warn_code |= AscInitMicroCodeVar(asc_dvc);
6445 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
6446 AscEnableInterrupt(iop_base);
6447 return warn_code;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006448}
6449
Linus Torvalds1da177e2005-04-16 15:20:36 -07006450/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006451 * Load the Microcode
6452 *
6453 * Write the microcode image to RISC memory starting at address 0.
6454 *
6455 * The microcode is stored compressed in the following format:
6456 *
6457 * 254 word (508 byte) table indexed by byte code followed
6458 * by the following byte codes:
6459 *
6460 * 1-Byte Code:
6461 * 00: Emit word 0 in table.
6462 * 01: Emit word 1 in table.
6463 * .
6464 * FD: Emit word 253 in table.
6465 *
6466 * Multi-Byte Code:
6467 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
6468 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
6469 *
6470 * Returns 0 or an error if the checksum doesn't match
6471 */
6472static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
6473 int memsize, int chksum)
6474{
6475 int i, j, end, len = 0;
6476 ADV_DCNT sum;
6477
6478 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6479
6480 for (i = 253 * 2; i < size; i++) {
6481 if (buf[i] == 0xff) {
6482 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
6483 for (j = 0; j < buf[i + 1]; j++) {
6484 AdvWriteWordAutoIncLram(iop_base, word);
6485 len += 2;
6486 }
6487 i += 3;
6488 } else if (buf[i] == 0xfe) {
6489 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
6490 AdvWriteWordAutoIncLram(iop_base, word);
6491 i += 2;
6492 len += 2;
6493 } else {
6494 unsigned char off = buf[i] * 2;
6495 unsigned short word = (buf[off + 1] << 8) | buf[off];
6496 AdvWriteWordAutoIncLram(iop_base, word);
6497 len += 2;
6498 }
6499 }
6500
6501 end = len;
6502
6503 while (len < memsize) {
6504 AdvWriteWordAutoIncLram(iop_base, 0);
6505 len += 2;
6506 }
6507
6508 /* Verify the microcode checksum. */
6509 sum = 0;
6510 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6511
6512 for (len = 0; len < end; len += 2) {
6513 sum += AdvReadWordAutoIncLram(iop_base);
6514 }
6515
6516 if (sum != chksum)
6517 return ASC_IERR_MCODE_CHKSUM;
6518
6519 return 0;
6520}
6521
6522/*
Matthew Wilcox51219352007-10-02 21:55:22 -04006523 * DvcGetPhyAddr()
6524 *
6525 * Return the physical address of 'vaddr' and set '*lenp' to the
6526 * number of physically contiguous bytes that follow 'vaddr'.
6527 * 'flag' indicates the type of structure whose physical address
6528 * is being translated.
6529 *
6530 * Note: Because Linux currently doesn't page the kernel and all
6531 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
6532 */
6533ADV_PADDR
6534DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
6535 uchar *vaddr, ADV_SDCNT *lenp, int flag)
6536{
6537 ADV_PADDR paddr = virt_to_bus(vaddr);
6538
Matthew Wilcoxb352f922007-10-02 21:55:33 -04006539 ASC_DBG(4, "vaddr 0x%p, lenp 0x%p *lenp %lu, paddr 0x%lx\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04006540 vaddr, lenp, (ulong)*((ulong *)lenp), (ulong)paddr);
6541
6542 return paddr;
6543}
6544
6545static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
6546{
6547 ADV_CARR_T *carrp;
6548 ADV_SDCNT buf_size;
6549 ADV_PADDR carr_paddr;
6550
6551 BUG_ON(!asc_dvc->carrier_buf);
6552
6553 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
6554 asc_dvc->carr_freelist = NULL;
6555 if (carrp == asc_dvc->carrier_buf) {
6556 buf_size = ADV_CARRIER_BUFSIZE;
6557 } else {
6558 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
6559 }
6560
6561 do {
6562 /* Get physical address of the carrier 'carrp'. */
6563 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
6564 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
6565 (uchar *)carrp,
6566 (ADV_SDCNT *)&contig_len,
6567 ADV_IS_CARRIER_FLAG));
6568
6569 buf_size -= sizeof(ADV_CARR_T);
6570
6571 /*
6572 * If the current carrier is not physically contiguous, then
6573 * maybe there was a page crossing. Try the next carrier
6574 * aligned start address.
6575 */
6576 if (contig_len < sizeof(ADV_CARR_T)) {
6577 carrp++;
6578 continue;
6579 }
6580
6581 carrp->carr_pa = carr_paddr;
6582 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
6583
6584 /*
6585 * Insert the carrier at the beginning of the freelist.
6586 */
6587 carrp->next_vpa =
6588 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
6589 asc_dvc->carr_freelist = carrp;
6590
6591 carrp++;
6592 } while (buf_size > 0);
6593}
6594
6595/*
6596 * Send an idle command to the chip and wait for completion.
6597 *
6598 * Command completion is polled for once per microsecond.
6599 *
6600 * The function can be called from anywhere including an interrupt handler.
6601 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
6602 * functions to prevent reentrancy.
6603 *
6604 * Return Values:
6605 * ADV_TRUE - command completed successfully
6606 * ADV_FALSE - command failed
6607 * ADV_ERROR - command timed out
6608 */
6609static int
6610AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
6611 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
6612{
6613 int result;
6614 ADV_DCNT i, j;
6615 AdvPortAddr iop_base;
6616
6617 iop_base = asc_dvc->iop_base;
6618
6619 /*
6620 * Clear the idle command status which is set by the microcode
6621 * to a non-zero value to indicate when the command is completed.
6622 * The non-zero result is one of the IDLE_CMD_STATUS_* values
6623 */
6624 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
6625
6626 /*
6627 * Write the idle command value after the idle command parameter
6628 * has been written to avoid a race condition. If the order is not
6629 * followed, the microcode may process the idle command before the
6630 * parameters have been written to LRAM.
6631 */
6632 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
6633 cpu_to_le32(idle_cmd_parameter));
6634 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
6635
6636 /*
6637 * Tickle the RISC to tell it to process the idle command.
6638 */
6639 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
6640 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
6641 /*
6642 * Clear the tickle value. In the ASC-3550 the RISC flag
6643 * command 'clr_tickle_b' does not work unless the host
6644 * value is cleared.
6645 */
6646 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
6647 }
6648
6649 /* Wait for up to 100 millisecond for the idle command to timeout. */
6650 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
6651 /* Poll once each microsecond for command completion. */
6652 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
6653 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
6654 result);
6655 if (result != 0)
6656 return result;
6657 udelay(1);
6658 }
6659 }
6660
6661 BUG(); /* The idle command should never timeout. */
6662 return ADV_ERROR;
6663}
6664
6665/*
6666 * Reset SCSI Bus and purge all outstanding requests.
6667 *
6668 * Return Value:
6669 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
6670 * ADV_FALSE(0) - Microcode command failed.
6671 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
6672 * may be hung which requires driver recovery.
6673 */
6674static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
6675{
6676 int status;
6677
6678 /*
6679 * Send the SCSI Bus Reset idle start idle command which asserts
6680 * the SCSI Bus Reset signal.
6681 */
6682 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
6683 if (status != ADV_TRUE) {
6684 return status;
6685 }
6686
6687 /*
6688 * Delay for the specified SCSI Bus Reset hold time.
6689 *
6690 * The hold time delay is done on the host because the RISC has no
6691 * microsecond accurate timer.
6692 */
6693 udelay(ASC_SCSI_RESET_HOLD_TIME_US);
6694
6695 /*
6696 * Send the SCSI Bus Reset end idle command which de-asserts
6697 * the SCSI Bus Reset signal and purges any pending requests.
6698 */
6699 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
6700 if (status != ADV_TRUE) {
6701 return status;
6702 }
6703
6704 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6705
6706 return status;
6707}
6708
6709/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006710 * Initialize the ASC-3550.
6711 *
6712 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
6713 *
6714 * For a non-fatal error return a warning code. If there are no warnings
6715 * then 0 is returned.
6716 *
6717 * Needed after initialization for error recovery.
6718 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006719static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006720{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006721 AdvPortAddr iop_base;
6722 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006723 int begin_addr;
6724 int end_addr;
6725 ushort code_sum;
6726 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006727 int i;
6728 ushort scsi_cfg1;
6729 uchar tid;
6730 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
6731 ushort wdtr_able = 0, sdtr_able, tagqng_able;
6732 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006733
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006734 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006735 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006736 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006738 /*
6739 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
6740 */
6741 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006742 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006743 return ADV_ERROR;
6744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006745
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006746 warn_code = 0;
6747 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006749 /*
6750 * Save the RISC memory BIOS region before writing the microcode.
6751 * The BIOS may already be loaded and using its RISC LRAM region
6752 * so its region must be saved and restored.
6753 *
6754 * Note: This code makes the assumption, which is currently true,
6755 * that a chip reset does not clear RISC LRAM.
6756 */
6757 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6758 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6759 bios_mem[i]);
6760 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006761
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006762 /*
6763 * Save current per TID negotiated values.
6764 */
6765 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
6766 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006768 bios_version =
6769 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
6770 major = (bios_version >> 12) & 0xF;
6771 minor = (bios_version >> 8) & 0xF;
6772 if (major < 3 || (major == 3 && minor == 1)) {
6773 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
6774 AdvReadWordLram(iop_base, 0x120, wdtr_able);
6775 } else {
6776 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6777 }
6778 }
6779 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
6780 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6781 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6782 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
6783 max_cmd[tid]);
6784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006786 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
6787 _adv_asc3550_size, ADV_3550_MEMSIZE,
6788 _adv_asc3550_chksum);
6789 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006790 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006792 /*
6793 * Restore the RISC memory BIOS region.
6794 */
6795 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6796 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6797 bios_mem[i]);
6798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006799
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006800 /*
6801 * Calculate and write the microcode code checksum to the microcode
6802 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
6803 */
6804 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
6805 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
6806 code_sum = 0;
6807 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
6808 for (word = begin_addr; word < end_addr; word += 2) {
6809 code_sum += AdvReadWordAutoIncLram(iop_base);
6810 }
6811 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006813 /*
6814 * Read and save microcode version and date.
6815 */
6816 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
6817 asc_dvc->cfg->mcode_date);
6818 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
6819 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006820
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006821 /*
6822 * Set the chip type to indicate the ASC3550.
6823 */
6824 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006825
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006826 /*
6827 * If the PCI Configuration Command Register "Parity Error Response
6828 * Control" Bit was clear (0), then set the microcode variable
6829 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
6830 * to ignore DMA parity errors.
6831 */
6832 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
6833 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6834 word |= CONTROL_FLAG_IGNORE_PERR;
6835 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006838 /*
6839 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
6840 * threshold of 128 bytes. This register is only accessible to the host.
6841 */
6842 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
6843 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006844
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006845 /*
6846 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006847 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006848 * device reports it is capable of in Inquiry byte 7.
6849 *
6850 * If SCSI Bus Resets have been disabled, then directly set
6851 * SDTR and WDTR from the EEPROM configuration. This will allow
6852 * the BIOS and warm boot to work without a SCSI bus hang on
6853 * the Inquiry caused by host and target mismatched DTR values.
6854 * Without the SCSI Bus Reset, before an Inquiry a device can't
6855 * be assumed to be in Asynchronous, Narrow mode.
6856 */
6857 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
6858 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
6859 asc_dvc->wdtr_able);
6860 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
6861 asc_dvc->sdtr_able);
6862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006863
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006864 /*
6865 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
6866 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
6867 * bitmask. These values determine the maximum SDTR speed negotiated
6868 * with a device.
6869 *
6870 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
6871 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
6872 * without determining here whether the device supports SDTR.
6873 *
6874 * 4-bit speed SDTR speed name
6875 * =========== ===============
6876 * 0000b (0x0) SDTR disabled
6877 * 0001b (0x1) 5 Mhz
6878 * 0010b (0x2) 10 Mhz
6879 * 0011b (0x3) 20 Mhz (Ultra)
6880 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
6881 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
6882 * 0110b (0x6) Undefined
6883 * .
6884 * 1111b (0xF) Undefined
6885 */
6886 word = 0;
6887 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6888 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
6889 /* Set Ultra speed for TID 'tid'. */
6890 word |= (0x3 << (4 * (tid % 4)));
6891 } else {
6892 /* Set Fast speed for TID 'tid'. */
6893 word |= (0x2 << (4 * (tid % 4)));
6894 }
6895 if (tid == 3) { /* Check if done with sdtr_speed1. */
6896 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
6897 word = 0;
6898 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
6899 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
6900 word = 0;
6901 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
6902 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
6903 word = 0;
6904 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
6905 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
6906 /* End of loop. */
6907 }
6908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006910 /*
6911 * Set microcode operating variable for the disconnect per TID bitmask.
6912 */
6913 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
6914 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006916 /*
6917 * Set SCSI_CFG0 Microcode Default Value.
6918 *
6919 * The microcode will set the SCSI_CFG0 register using this value
6920 * after it is started below.
6921 */
6922 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
6923 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
6924 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006926 /*
6927 * Determine SCSI_CFG1 Microcode Default Value.
6928 *
6929 * The microcode will set the SCSI_CFG1 register using this value
6930 * after it is started below.
6931 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006932
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006933 /* Read current SCSI_CFG1 Register value. */
6934 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006936 /*
6937 * If all three connectors are in use, return an error.
6938 */
6939 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
6940 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
6941 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
6942 return ADV_ERROR;
6943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006944
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006945 /*
6946 * If the internal narrow cable is reversed all of the SCSI_CTRL
6947 * register signals will be set. Check for and return an error if
6948 * this condition is found.
6949 */
6950 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
6951 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
6952 return ADV_ERROR;
6953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006954
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006955 /*
6956 * If this is a differential board and a single-ended device
6957 * is attached to one of the connectors, return an error.
6958 */
6959 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
6960 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
6961 return ADV_ERROR;
6962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006964 /*
6965 * If automatic termination control is enabled, then set the
6966 * termination value based on a table listed in a_condor.h.
6967 *
6968 * If manual termination was specified with an EEPROM setting
6969 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
6970 * is ready to be 'ored' into SCSI_CFG1.
6971 */
6972 if (asc_dvc->cfg->termination == 0) {
6973 /*
6974 * The software always controls termination by setting TERM_CTL_SEL.
6975 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
6976 */
6977 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006978
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006979 switch (scsi_cfg1 & CABLE_DETECT) {
6980 /* TERM_CTL_H: on, TERM_CTL_L: on */
6981 case 0x3:
6982 case 0x7:
6983 case 0xB:
6984 case 0xD:
6985 case 0xE:
6986 case 0xF:
6987 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
6988 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006990 /* TERM_CTL_H: on, TERM_CTL_L: off */
6991 case 0x1:
6992 case 0x5:
6993 case 0x9:
6994 case 0xA:
6995 case 0xC:
6996 asc_dvc->cfg->termination |= TERM_CTL_H;
6997 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006999 /* TERM_CTL_H: off, TERM_CTL_L: off */
7000 case 0x2:
7001 case 0x6:
7002 break;
7003 }
7004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007006 /*
7007 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
7008 */
7009 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007011 /*
7012 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
7013 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
7014 * referenced, because the hardware internally inverts
7015 * the Termination High and Low bits if TERM_POL is set.
7016 */
7017 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007018
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007019 /*
7020 * Set SCSI_CFG1 Microcode Default Value
7021 *
7022 * Set filter value and possibly modified termination control
7023 * bits in the Microcode SCSI_CFG1 Register Value.
7024 *
7025 * The microcode will set the SCSI_CFG1 register using this value
7026 * after it is started below.
7027 */
7028 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
7029 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007031 /*
7032 * Set MEM_CFG Microcode Default Value
7033 *
7034 * The microcode will set the MEM_CFG register using this value
7035 * after it is started below.
7036 *
7037 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7038 * are defined.
7039 *
7040 * ASC-3550 has 8KB internal memory.
7041 */
7042 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7043 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007044
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007045 /*
7046 * Set SEL_MASK Microcode Default Value
7047 *
7048 * The microcode will set the SEL_MASK register using this value
7049 * after it is started below.
7050 */
7051 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7052 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007053
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007054 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007055
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007056 /*
7057 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7058 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007060 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7061 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7062 return ADV_ERROR;
7063 }
7064 asc_dvc->carr_freelist = (ADV_CARR_T *)
7065 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007067 /*
7068 * The first command issued will be placed in the stopper carrier.
7069 */
7070 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007072 /*
7073 * Set RISC ICQ physical address start value.
7074 */
7075 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007077 /*
7078 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7079 */
7080 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7081 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7082 return ADV_ERROR;
7083 }
7084 asc_dvc->carr_freelist = (ADV_CARR_T *)
7085 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007086
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007087 /*
7088 * The first command completed by the RISC will be placed in
7089 * the stopper.
7090 *
7091 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7092 * completed the RISC will set the ASC_RQ_STOPPER bit.
7093 */
7094 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007095
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007096 /*
7097 * Set RISC IRQ physical address start value.
7098 */
7099 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7100 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007102 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7103 (ADV_INTR_ENABLE_HOST_INTR |
7104 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007106 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7107 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007109 /* finally, finally, gentlemen, start your engine */
7110 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007112 /*
7113 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7114 * Resets should be performed. The RISC has to be running
7115 * to issue a SCSI Bus Reset.
7116 */
7117 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7118 /*
7119 * If the BIOS Signature is present in memory, restore the
7120 * BIOS Handshake Configuration Table and do not perform
7121 * a SCSI Bus Reset.
7122 */
7123 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7124 0x55AA) {
7125 /*
7126 * Restore per TID negotiated values.
7127 */
7128 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7129 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7130 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7131 tagqng_able);
7132 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7133 AdvWriteByteLram(iop_base,
7134 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7135 max_cmd[tid]);
7136 }
7137 } else {
7138 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7139 warn_code = ASC_WARN_BUSRESET_ERROR;
7140 }
7141 }
7142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007143
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007144 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007145}
7146
7147/*
7148 * Initialize the ASC-38C0800.
7149 *
7150 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
7151 *
7152 * For a non-fatal error return a warning code. If there are no warnings
7153 * then 0 is returned.
7154 *
7155 * Needed after initialization for error recovery.
7156 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007157static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007158{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007159 AdvPortAddr iop_base;
7160 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007161 int begin_addr;
7162 int end_addr;
7163 ushort code_sum;
7164 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007165 int i;
7166 ushort scsi_cfg1;
7167 uchar byte;
7168 uchar tid;
7169 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7170 ushort wdtr_able, sdtr_able, tagqng_able;
7171 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007173 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007174 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007175 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007177 /*
7178 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
7179 */
7180 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
7181 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7182 return ADV_ERROR;
7183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007185 warn_code = 0;
7186 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007188 /*
7189 * Save the RISC memory BIOS region before writing the microcode.
7190 * The BIOS may already be loaded and using its RISC LRAM region
7191 * so its region must be saved and restored.
7192 *
7193 * Note: This code makes the assumption, which is currently true,
7194 * that a chip reset does not clear RISC LRAM.
7195 */
7196 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7197 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7198 bios_mem[i]);
7199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007201 /*
7202 * Save current per TID negotiated values.
7203 */
7204 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7205 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7206 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7207 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7208 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7209 max_cmd[tid]);
7210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007211
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007212 /*
7213 * RAM BIST (RAM Built-In Self Test)
7214 *
7215 * Address : I/O base + offset 0x38h register (byte).
7216 * Function: Bit 7-6(RW) : RAM mode
7217 * Normal Mode : 0x00
7218 * Pre-test Mode : 0x40
7219 * RAM Test Mode : 0x80
7220 * Bit 5 : unused
7221 * Bit 4(RO) : Done bit
7222 * Bit 3-0(RO) : Status
7223 * Host Error : 0x08
7224 * Int_RAM Error : 0x04
7225 * RISC Error : 0x02
7226 * SCSI Error : 0x01
7227 * No Error : 0x00
7228 *
7229 * Note: RAM BIST code should be put right here, before loading the
7230 * microcode and after saving the RISC memory BIOS region.
7231 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007233 /*
7234 * LRAM Pre-test
7235 *
7236 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7237 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7238 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7239 * to NORMAL_MODE, return an error too.
7240 */
7241 for (i = 0; i < 2; i++) {
7242 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007243 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007244 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7245 if ((byte & RAM_TEST_DONE) == 0
7246 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007247 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007248 return ADV_ERROR;
7249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007251 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007252 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007253 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7254 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007255 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007256 return ADV_ERROR;
7257 }
7258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007259
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007260 /*
7261 * LRAM Test - It takes about 1.5 ms to run through the test.
7262 *
7263 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7264 * If Done bit not set or Status not 0, save register byte, set the
7265 * err_code, and return an error.
7266 */
7267 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007268 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007270 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7271 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7272 /* Get here if Done bit not set or Status not 0. */
7273 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007274 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007275 return ADV_ERROR;
7276 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007278 /* We need to reset back to normal mode after LRAM test passes. */
7279 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007280
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007281 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
7282 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
7283 _adv_asc38C0800_chksum);
7284 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007285 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007286
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007287 /*
7288 * Restore the RISC memory BIOS region.
7289 */
7290 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7291 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7292 bios_mem[i]);
7293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007294
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007295 /*
7296 * Calculate and write the microcode code checksum to the microcode
7297 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7298 */
7299 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7300 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7301 code_sum = 0;
7302 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7303 for (word = begin_addr; word < end_addr; word += 2) {
7304 code_sum += AdvReadWordAutoIncLram(iop_base);
7305 }
7306 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007307
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007308 /*
7309 * Read microcode version and date.
7310 */
7311 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7312 asc_dvc->cfg->mcode_date);
7313 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7314 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007316 /*
7317 * Set the chip type to indicate the ASC38C0800.
7318 */
7319 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007320
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007321 /*
7322 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7323 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7324 * cable detection and then we are able to read C_DET[3:0].
7325 *
7326 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7327 * Microcode Default Value' section below.
7328 */
7329 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7330 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7331 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007332
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007333 /*
7334 * If the PCI Configuration Command Register "Parity Error Response
7335 * Control" Bit was clear (0), then set the microcode variable
7336 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7337 * to ignore DMA parity errors.
7338 */
7339 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7340 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7341 word |= CONTROL_FLAG_IGNORE_PERR;
7342 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7343 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007345 /*
7346 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
7347 * bits for the default FIFO threshold.
7348 *
7349 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
7350 *
7351 * For DMA Errata #4 set the BC_THRESH_ENB bit.
7352 */
7353 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7354 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
7355 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007356
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007357 /*
7358 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007359 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007360 * device reports it is capable of in Inquiry byte 7.
7361 *
7362 * If SCSI Bus Resets have been disabled, then directly set
7363 * SDTR and WDTR from the EEPROM configuration. This will allow
7364 * the BIOS and warm boot to work without a SCSI bus hang on
7365 * the Inquiry caused by host and target mismatched DTR values.
7366 * Without the SCSI Bus Reset, before an Inquiry a device can't
7367 * be assumed to be in Asynchronous, Narrow mode.
7368 */
7369 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7370 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7371 asc_dvc->wdtr_able);
7372 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7373 asc_dvc->sdtr_able);
7374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007375
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007376 /*
7377 * Set microcode operating variables for DISC and SDTR_SPEED1,
7378 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7379 * configuration values.
7380 *
7381 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7382 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7383 * without determining here whether the device supports SDTR.
7384 */
7385 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7386 asc_dvc->cfg->disc_enable);
7387 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7388 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7389 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7390 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007392 /*
7393 * Set SCSI_CFG0 Microcode Default Value.
7394 *
7395 * The microcode will set the SCSI_CFG0 register using this value
7396 * after it is started below.
7397 */
7398 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7399 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7400 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007401
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007402 /*
7403 * Determine SCSI_CFG1 Microcode Default Value.
7404 *
7405 * The microcode will set the SCSI_CFG1 register using this value
7406 * after it is started below.
7407 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007409 /* Read current SCSI_CFG1 Register value. */
7410 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007411
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007412 /*
7413 * If the internal narrow cable is reversed all of the SCSI_CTRL
7414 * register signals will be set. Check for and return an error if
7415 * this condition is found.
7416 */
7417 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7418 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7419 return ADV_ERROR;
7420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007421
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007422 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007423 * All kind of combinations of devices attached to one of four
7424 * connectors are acceptable except HVD device attached. For example,
7425 * LVD device can be attached to SE connector while SE device attached
7426 * to LVD connector. If LVD device attached to SE connector, it only
7427 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007428 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007429 * If an HVD device is attached to one of LVD connectors, return an
7430 * error. However, there is no way to detect HVD device attached to
7431 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007432 */
7433 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007434 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007435 return ADV_ERROR;
7436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007438 /*
7439 * If either SE or LVD automatic termination control is enabled, then
7440 * set the termination value based on a table listed in a_condor.h.
7441 *
7442 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007443 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
7444 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007445 */
7446 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
7447 /* SE automatic termination control is enabled. */
7448 switch (scsi_cfg1 & C_DET_SE) {
7449 /* TERM_SE_HI: on, TERM_SE_LO: on */
7450 case 0x1:
7451 case 0x2:
7452 case 0x3:
7453 asc_dvc->cfg->termination |= TERM_SE;
7454 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007455
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007456 /* TERM_SE_HI: on, TERM_SE_LO: off */
7457 case 0x0:
7458 asc_dvc->cfg->termination |= TERM_SE_HI;
7459 break;
7460 }
7461 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007463 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
7464 /* LVD automatic termination control is enabled. */
7465 switch (scsi_cfg1 & C_DET_LVD) {
7466 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
7467 case 0x4:
7468 case 0x8:
7469 case 0xC:
7470 asc_dvc->cfg->termination |= TERM_LVD;
7471 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007472
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007473 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
7474 case 0x0:
7475 break;
7476 }
7477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007478
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007479 /*
7480 * Clear any set TERM_SE and TERM_LVD bits.
7481 */
7482 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007484 /*
7485 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
7486 */
7487 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007489 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007490 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
7491 * bits and set possibly modified termination control bits in the
7492 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007493 */
7494 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007495
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007496 /*
7497 * Set SCSI_CFG1 Microcode Default Value
7498 *
7499 * Set possibly modified termination control and reset DIS_TERM_DRV
7500 * bits in the Microcode SCSI_CFG1 Register Value.
7501 *
7502 * The microcode will set the SCSI_CFG1 register using this value
7503 * after it is started below.
7504 */
7505 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007507 /*
7508 * Set MEM_CFG Microcode Default Value
7509 *
7510 * The microcode will set the MEM_CFG register using this value
7511 * after it is started below.
7512 *
7513 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7514 * are defined.
7515 *
7516 * ASC-38C0800 has 16KB internal memory.
7517 */
7518 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7519 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007520
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007521 /*
7522 * Set SEL_MASK Microcode Default Value
7523 *
7524 * The microcode will set the SEL_MASK register using this value
7525 * after it is started below.
7526 */
7527 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7528 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007529
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007530 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007531
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007532 /*
7533 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7534 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007535
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007536 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7537 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7538 return ADV_ERROR;
7539 }
7540 asc_dvc->carr_freelist = (ADV_CARR_T *)
7541 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007542
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007543 /*
7544 * The first command issued will be placed in the stopper carrier.
7545 */
7546 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007548 /*
7549 * Set RISC ICQ physical address start value.
7550 * carr_pa is LE, must be native before write
7551 */
7552 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007554 /*
7555 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7556 */
7557 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7558 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7559 return ADV_ERROR;
7560 }
7561 asc_dvc->carr_freelist = (ADV_CARR_T *)
7562 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007563
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007564 /*
7565 * The first command completed by the RISC will be placed in
7566 * the stopper.
7567 *
7568 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7569 * completed the RISC will set the ASC_RQ_STOPPER bit.
7570 */
7571 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007572
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007573 /*
7574 * Set RISC IRQ physical address start value.
7575 *
7576 * carr_pa is LE, must be native before write *
7577 */
7578 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7579 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007580
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007581 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7582 (ADV_INTR_ENABLE_HOST_INTR |
7583 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007584
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007585 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7586 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007588 /* finally, finally, gentlemen, start your engine */
7589 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007590
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007591 /*
7592 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7593 * Resets should be performed. The RISC has to be running
7594 * to issue a SCSI Bus Reset.
7595 */
7596 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7597 /*
7598 * If the BIOS Signature is present in memory, restore the
7599 * BIOS Handshake Configuration Table and do not perform
7600 * a SCSI Bus Reset.
7601 */
7602 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7603 0x55AA) {
7604 /*
7605 * Restore per TID negotiated values.
7606 */
7607 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7608 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7609 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7610 tagqng_able);
7611 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7612 AdvWriteByteLram(iop_base,
7613 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7614 max_cmd[tid]);
7615 }
7616 } else {
7617 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7618 warn_code = ASC_WARN_BUSRESET_ERROR;
7619 }
7620 }
7621 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007622
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007623 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007624}
7625
7626/*
7627 * Initialize the ASC-38C1600.
7628 *
7629 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
7630 *
7631 * For a non-fatal error return a warning code. If there are no warnings
7632 * then 0 is returned.
7633 *
7634 * Needed after initialization for error recovery.
7635 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007636static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007637{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007638 AdvPortAddr iop_base;
7639 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007640 int begin_addr;
7641 int end_addr;
7642 ushort code_sum;
7643 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007644 int i;
7645 ushort scsi_cfg1;
7646 uchar byte;
7647 uchar tid;
7648 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7649 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
7650 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007651
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007652 /* If there is already an error, don't continue. */
7653 if (asc_dvc->err_code != 0) {
7654 return ADV_ERROR;
7655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007657 /*
7658 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
7659 */
7660 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
7661 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7662 return ADV_ERROR;
7663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007664
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007665 warn_code = 0;
7666 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007667
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007668 /*
7669 * Save the RISC memory BIOS region before writing the microcode.
7670 * The BIOS may already be loaded and using its RISC LRAM region
7671 * so its region must be saved and restored.
7672 *
7673 * Note: This code makes the assumption, which is currently true,
7674 * that a chip reset does not clear RISC LRAM.
7675 */
7676 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7677 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7678 bios_mem[i]);
7679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007680
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007681 /*
7682 * Save current per TID negotiated values.
7683 */
7684 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7685 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7686 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
7687 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7688 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7689 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7690 max_cmd[tid]);
7691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007692
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007693 /*
7694 * RAM BIST (Built-In Self Test)
7695 *
7696 * Address : I/O base + offset 0x38h register (byte).
7697 * Function: Bit 7-6(RW) : RAM mode
7698 * Normal Mode : 0x00
7699 * Pre-test Mode : 0x40
7700 * RAM Test Mode : 0x80
7701 * Bit 5 : unused
7702 * Bit 4(RO) : Done bit
7703 * Bit 3-0(RO) : Status
7704 * Host Error : 0x08
7705 * Int_RAM Error : 0x04
7706 * RISC Error : 0x02
7707 * SCSI Error : 0x01
7708 * No Error : 0x00
7709 *
7710 * Note: RAM BIST code should be put right here, before loading the
7711 * microcode and after saving the RISC memory BIOS region.
7712 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007713
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007714 /*
7715 * LRAM Pre-test
7716 *
7717 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7718 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7719 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7720 * to NORMAL_MODE, return an error too.
7721 */
7722 for (i = 0; i < 2; i++) {
7723 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007724 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007725 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7726 if ((byte & RAM_TEST_DONE) == 0
7727 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007728 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007729 return ADV_ERROR;
7730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007732 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007733 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007734 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7735 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007736 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007737 return ADV_ERROR;
7738 }
7739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007741 /*
7742 * LRAM Test - It takes about 1.5 ms to run through the test.
7743 *
7744 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7745 * If Done bit not set or Status not 0, save register byte, set the
7746 * err_code, and return an error.
7747 */
7748 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007749 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007750
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007751 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7752 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7753 /* Get here if Done bit not set or Status not 0. */
7754 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007755 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007756 return ADV_ERROR;
7757 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007759 /* We need to reset back to normal mode after LRAM test passes. */
7760 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007761
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007762 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
7763 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
7764 _adv_asc38C1600_chksum);
7765 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007766 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007768 /*
7769 * Restore the RISC memory BIOS region.
7770 */
7771 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7772 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7773 bios_mem[i]);
7774 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007775
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007776 /*
7777 * Calculate and write the microcode code checksum to the microcode
7778 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7779 */
7780 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7781 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7782 code_sum = 0;
7783 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7784 for (word = begin_addr; word < end_addr; word += 2) {
7785 code_sum += AdvReadWordAutoIncLram(iop_base);
7786 }
7787 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007788
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007789 /*
7790 * Read microcode version and date.
7791 */
7792 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7793 asc_dvc->cfg->mcode_date);
7794 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7795 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007796
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007797 /*
7798 * Set the chip type to indicate the ASC38C1600.
7799 */
7800 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007802 /*
7803 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7804 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7805 * cable detection and then we are able to read C_DET[3:0].
7806 *
7807 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7808 * Microcode Default Value' section below.
7809 */
7810 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7811 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7812 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007813
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007814 /*
7815 * If the PCI Configuration Command Register "Parity Error Response
7816 * Control" Bit was clear (0), then set the microcode variable
7817 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7818 * to ignore DMA parity errors.
7819 */
7820 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7821 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7822 word |= CONTROL_FLAG_IGNORE_PERR;
7823 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7824 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007825
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007826 /*
7827 * If the BIOS control flag AIPP (Asynchronous Information
7828 * Phase Protection) disable bit is not set, then set the firmware
7829 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
7830 * AIPP checking and encoding.
7831 */
7832 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
7833 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7834 word |= CONTROL_FLAG_ENABLE_AIPP;
7835 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007838 /*
7839 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
7840 * and START_CTL_TH [3:2].
7841 */
7842 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7843 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007844
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007845 /*
7846 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007847 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007848 * device reports it is capable of in Inquiry byte 7.
7849 *
7850 * If SCSI Bus Resets have been disabled, then directly set
7851 * SDTR and WDTR from the EEPROM configuration. This will allow
7852 * the BIOS and warm boot to work without a SCSI bus hang on
7853 * the Inquiry caused by host and target mismatched DTR values.
7854 * Without the SCSI Bus Reset, before an Inquiry a device can't
7855 * be assumed to be in Asynchronous, Narrow mode.
7856 */
7857 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7858 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7859 asc_dvc->wdtr_able);
7860 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7861 asc_dvc->sdtr_able);
7862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007863
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007864 /*
7865 * Set microcode operating variables for DISC and SDTR_SPEED1,
7866 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7867 * configuration values.
7868 *
7869 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7870 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7871 * without determining here whether the device supports SDTR.
7872 */
7873 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7874 asc_dvc->cfg->disc_enable);
7875 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7876 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7877 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7878 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007879
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007880 /*
7881 * Set SCSI_CFG0 Microcode Default Value.
7882 *
7883 * The microcode will set the SCSI_CFG0 register using this value
7884 * after it is started below.
7885 */
7886 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7887 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7888 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007889
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007890 /*
7891 * Calculate SCSI_CFG1 Microcode Default Value.
7892 *
7893 * The microcode will set the SCSI_CFG1 register using this value
7894 * after it is started below.
7895 *
7896 * Each ASC-38C1600 function has only two cable detect bits.
7897 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
7898 */
7899 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007900
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007901 /*
7902 * If the cable is reversed all of the SCSI_CTRL register signals
7903 * will be set. Check for and return an error if this condition is
7904 * found.
7905 */
7906 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7907 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7908 return ADV_ERROR;
7909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007910
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007911 /*
7912 * Each ASC-38C1600 function has two connectors. Only an HVD device
7913 * can not be connected to either connector. An LVD device or SE device
7914 * may be connected to either connecor. If an SE device is connected,
7915 * then at most Ultra speed (20 Mhz) can be used on both connectors.
7916 *
7917 * If an HVD device is attached, return an error.
7918 */
7919 if (scsi_cfg1 & HVD) {
7920 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
7921 return ADV_ERROR;
7922 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007923
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007924 /*
7925 * Each function in the ASC-38C1600 uses only the SE cable detect and
7926 * termination because there are two connectors for each function. Each
7927 * function may use either LVD or SE mode. Corresponding the SE automatic
7928 * termination control EEPROM bits are used for each function. Each
7929 * function has its own EEPROM. If SE automatic control is enabled for
7930 * the function, then set the termination value based on a table listed
7931 * in a_condor.h.
7932 *
7933 * If manual termination is specified in the EEPROM for the function,
7934 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
7935 * ready to be 'ored' into SCSI_CFG1.
7936 */
7937 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06007938 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007939 /* SE automatic termination control is enabled. */
7940 switch (scsi_cfg1 & C_DET_SE) {
7941 /* TERM_SE_HI: on, TERM_SE_LO: on */
7942 case 0x1:
7943 case 0x2:
7944 case 0x3:
7945 asc_dvc->cfg->termination |= TERM_SE;
7946 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007948 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06007949 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007950 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
7951 } else {
7952 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
7953 asc_dvc->cfg->termination |= TERM_SE_HI;
7954 }
7955 break;
7956 }
7957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007959 /*
7960 * Clear any set TERM_SE bits.
7961 */
7962 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007964 /*
7965 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
7966 */
7967 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007969 /*
7970 * Clear Big Endian and Terminator Polarity bits and set possibly
7971 * modified termination control bits in the Microcode SCSI_CFG1
7972 * Register Value.
7973 *
7974 * Big Endian bit is not used even on big endian machines.
7975 */
7976 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007978 /*
7979 * Set SCSI_CFG1 Microcode Default Value
7980 *
7981 * Set possibly modified termination control bits in the Microcode
7982 * SCSI_CFG1 Register Value.
7983 *
7984 * The microcode will set the SCSI_CFG1 register using this value
7985 * after it is started below.
7986 */
7987 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007989 /*
7990 * Set MEM_CFG Microcode Default Value
7991 *
7992 * The microcode will set the MEM_CFG register using this value
7993 * after it is started below.
7994 *
7995 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7996 * are defined.
7997 *
7998 * ASC-38C1600 has 32KB internal memory.
7999 *
8000 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
8001 * out a special 16K Adv Library and Microcode version. After the issue
8002 * resolved, we should turn back to the 32K support. Both a_condor.h and
8003 * mcode.sas files also need to be updated.
8004 *
8005 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8006 * BIOS_EN | RAM_SZ_32KB);
8007 */
8008 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8009 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008011 /*
8012 * Set SEL_MASK Microcode Default Value
8013 *
8014 * The microcode will set the SEL_MASK register using this value
8015 * after it is started below.
8016 */
8017 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
8018 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008019
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06008020 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008021
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008022 /*
8023 * Set-up the Host->RISC Initiator Command Queue (ICQ).
8024 */
8025 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
8026 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8027 return ADV_ERROR;
8028 }
8029 asc_dvc->carr_freelist = (ADV_CARR_T *)
8030 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008031
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008032 /*
8033 * The first command issued will be placed in the stopper carrier.
8034 */
8035 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008036
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008037 /*
8038 * Set RISC ICQ physical address start value. Initialize the
8039 * COMMA register to the same value otherwise the RISC will
8040 * prematurely detect a command is available.
8041 */
8042 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
8043 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
8044 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008045
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008046 /*
8047 * Set-up the RISC->Host Initiator Response Queue (IRQ).
8048 */
8049 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
8050 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8051 return ADV_ERROR;
8052 }
8053 asc_dvc->carr_freelist = (ADV_CARR_T *)
8054 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008055
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008056 /*
8057 * The first command completed by the RISC will be placed in
8058 * the stopper.
8059 *
8060 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
8061 * completed the RISC will set the ASC_RQ_STOPPER bit.
8062 */
8063 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008064
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008065 /*
8066 * Set RISC IRQ physical address start value.
8067 */
8068 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
8069 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008071 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
8072 (ADV_INTR_ENABLE_HOST_INTR |
8073 ADV_INTR_ENABLE_GLOBAL_INTR));
8074 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
8075 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008077 /* finally, finally, gentlemen, start your engine */
8078 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008079
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008080 /*
8081 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
8082 * Resets should be performed. The RISC has to be running
8083 * to issue a SCSI Bus Reset.
8084 */
8085 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
8086 /*
8087 * If the BIOS Signature is present in memory, restore the
8088 * per TID microcode operating variables.
8089 */
8090 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
8091 0x55AA) {
8092 /*
8093 * Restore per TID negotiated values.
8094 */
8095 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8096 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8097 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8098 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
8099 tagqng_able);
8100 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
8101 AdvWriteByteLram(iop_base,
8102 ASC_MC_NUMBER_OF_MAX_CMD + tid,
8103 max_cmd[tid]);
8104 }
8105 } else {
8106 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
8107 warn_code = ASC_WARN_BUSRESET_ERROR;
8108 }
8109 }
8110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008112 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008113}
8114
8115/*
Matthew Wilcox51219352007-10-02 21:55:22 -04008116 * Reset chip and SCSI Bus.
8117 *
8118 * Return Value:
8119 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
8120 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
8121 */
8122static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
8123{
8124 int status;
8125 ushort wdtr_able, sdtr_able, tagqng_able;
8126 ushort ppr_able = 0;
8127 uchar tid, max_cmd[ADV_MAX_TID + 1];
8128 AdvPortAddr iop_base;
8129 ushort bios_sig;
8130
8131 iop_base = asc_dvc->iop_base;
8132
8133 /*
8134 * Save current per TID negotiated values.
8135 */
8136 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8137 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8138 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8139 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8140 }
8141 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8142 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8143 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8144 max_cmd[tid]);
8145 }
8146
8147 /*
8148 * Force the AdvInitAsc3550/38C0800Driver() function to
8149 * perform a SCSI Bus Reset by clearing the BIOS signature word.
8150 * The initialization functions assumes a SCSI Bus Reset is not
8151 * needed if the BIOS signature word is present.
8152 */
8153 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8154 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
8155
8156 /*
8157 * Stop chip and reset it.
8158 */
8159 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
8160 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
8161 mdelay(100);
8162 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
8163 ADV_CTRL_REG_CMD_WR_IO_REG);
8164
8165 /*
8166 * Reset Adv Library error code, if any, and try
8167 * re-initializing the chip.
8168 */
8169 asc_dvc->err_code = 0;
8170 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8171 status = AdvInitAsc38C1600Driver(asc_dvc);
8172 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8173 status = AdvInitAsc38C0800Driver(asc_dvc);
8174 } else {
8175 status = AdvInitAsc3550Driver(asc_dvc);
8176 }
8177
8178 /* Translate initialization return value to status value. */
8179 if (status == 0) {
8180 status = ADV_TRUE;
8181 } else {
8182 status = ADV_FALSE;
8183 }
8184
8185 /*
8186 * Restore the BIOS signature word.
8187 */
8188 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8189
8190 /*
8191 * Restore per TID negotiated values.
8192 */
8193 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8194 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8195 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8196 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8197 }
8198 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8199 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8200 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8201 max_cmd[tid]);
8202 }
8203
8204 return status;
8205}
8206
8207/*
8208 * adv_async_callback() - Adv Library asynchronous event callback function.
8209 */
8210static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
8211{
8212 switch (code) {
8213 case ADV_ASYNC_SCSI_BUS_RESET_DET:
8214 /*
8215 * The firmware detected a SCSI Bus reset.
8216 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008217 ASC_DBG(0, "ADV_ASYNC_SCSI_BUS_RESET_DET\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008218 break;
8219
8220 case ADV_ASYNC_RDMA_FAILURE:
8221 /*
8222 * Handle RDMA failure by resetting the SCSI Bus and
8223 * possibly the chip if it is unresponsive. Log the error
8224 * with a unique code.
8225 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008226 ASC_DBG(0, "ADV_ASYNC_RDMA_FAILURE\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008227 AdvResetChipAndSB(adv_dvc_varp);
8228 break;
8229
8230 case ADV_HOST_SCSI_BUS_RESET:
8231 /*
8232 * Host generated SCSI bus reset occurred.
8233 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008234 ASC_DBG(0, "ADV_HOST_SCSI_BUS_RESET\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008235 break;
8236
8237 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008238 ASC_DBG(0, "unknown code 0x%x\n", code);
Matthew Wilcox51219352007-10-02 21:55:22 -04008239 break;
8240 }
8241}
8242
8243/*
8244 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
8245 *
8246 * Callback function for the Wide SCSI Adv Library.
8247 */
8248static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
8249{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008250 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04008251 adv_req_t *reqp;
8252 adv_sgblk_t *sgblkp;
8253 struct scsi_cmnd *scp;
8254 struct Scsi_Host *shost;
8255 ADV_DCNT resid_cnt;
8256
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008257 ASC_DBG(1, "adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04008258 (ulong)adv_dvc_varp, (ulong)scsiqp);
8259 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
8260
8261 /*
8262 * Get the adv_req_t structure for the command that has been
8263 * completed. The adv_req_t structure actually contains the
8264 * completed ADV_SCSI_REQ_Q structure.
8265 */
8266 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008267 ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp);
Matthew Wilcox51219352007-10-02 21:55:22 -04008268 if (reqp == NULL) {
8269 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
8270 return;
8271 }
8272
8273 /*
8274 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
8275 * command that has been completed.
8276 *
8277 * Note: The adv_req_t request structure and adv_sgblk_t structure,
8278 * if any, are dropped, because a board structure pointer can not be
8279 * determined.
8280 */
8281 scp = reqp->cmndp;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008282 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04008283 if (scp == NULL) {
8284 ASC_PRINT
8285 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
8286 return;
8287 }
8288 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
8289
8290 shost = scp->device->host;
8291 ASC_STATS(shost, callback);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008292 ASC_DBG(1, "shost 0x%p\n", shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04008293
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008294 boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04008295 BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
8296
8297 /*
8298 * 'done_status' contains the command's ending status.
8299 */
8300 switch (scsiqp->done_status) {
8301 case QD_NO_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008302 ASC_DBG(2, "QD_NO_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008303 scp->result = 0;
8304
8305 /*
8306 * Check for an underrun condition.
8307 *
8308 * If there was no error and an underrun condition, then
8309 * then return the number of underrun bytes.
8310 */
8311 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
8312 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
8313 resid_cnt <= scp->request_bufflen) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008314 ASC_DBG(1, "underrun condition %lu bytes\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04008315 (ulong)resid_cnt);
8316 scp->resid = resid_cnt;
8317 }
8318 break;
8319
8320 case QD_WITH_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008321 ASC_DBG(2, "QD_WITH_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008322 switch (scsiqp->host_status) {
8323 case QHSTA_NO_ERROR:
8324 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008325 ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008326 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
8327 sizeof(scp->sense_buffer));
8328 /*
8329 * Note: The 'status_byte()' macro used by
8330 * target drivers defined in scsi.h shifts the
8331 * status byte returned by host drivers right
8332 * by 1 bit. This is why target drivers also
8333 * use right shifted status byte definitions.
8334 * For instance target drivers use
8335 * CHECK_CONDITION, defined to 0x1, instead of
8336 * the SCSI defined check condition value of
8337 * 0x2. Host drivers are supposed to return
8338 * the status byte as it is defined by SCSI.
8339 */
8340 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
8341 STATUS_BYTE(scsiqp->scsi_status);
8342 } else {
8343 scp->result = STATUS_BYTE(scsiqp->scsi_status);
8344 }
8345 break;
8346
8347 default:
8348 /* Some other QHSTA error occurred. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008349 ASC_DBG(1, "host_status 0x%x\n", scsiqp->host_status);
Matthew Wilcox51219352007-10-02 21:55:22 -04008350 scp->result = HOST_BYTE(DID_BAD_TARGET);
8351 break;
8352 }
8353 break;
8354
8355 case QD_ABORTED_BY_HOST:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008356 ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008357 scp->result =
8358 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
8359 break;
8360
8361 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008362 ASC_DBG(1, "done_status 0x%x\n", scsiqp->done_status);
Matthew Wilcox51219352007-10-02 21:55:22 -04008363 scp->result =
8364 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
8365 break;
8366 }
8367
8368 /*
8369 * If the 'init_tidmask' bit isn't already set for the target and the
8370 * current request finished normally, then set the bit for the target
8371 * to indicate that a device is present.
8372 */
8373 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
8374 scsiqp->done_status == QD_NO_ERROR &&
8375 scsiqp->host_status == QHSTA_NO_ERROR) {
8376 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
8377 }
8378
8379 asc_scsi_done(scp);
8380
8381 /*
8382 * Free all 'adv_sgblk_t' structures allocated for the request.
8383 */
8384 while ((sgblkp = reqp->sgblkp) != NULL) {
8385 /* Remove 'sgblkp' from the request list. */
8386 reqp->sgblkp = sgblkp->next_sgblkp;
8387
8388 /* Add 'sgblkp' to the board free list. */
8389 sgblkp->next_sgblkp = boardp->adv_sgblkp;
8390 boardp->adv_sgblkp = sgblkp;
8391 }
8392
8393 /*
8394 * Free the adv_req_t structure used with the command by adding
8395 * it back to the board free list.
8396 */
8397 reqp->next_reqp = boardp->adv_reqp;
8398 boardp->adv_reqp = reqp;
8399
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008400 ASC_DBG(1, "done\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008401
8402 return;
8403}
8404
8405/*
8406 * Adv Library Interrupt Service Routine
8407 *
8408 * This function is called by a driver's interrupt service routine.
8409 * The function disables and re-enables interrupts.
8410 *
8411 * When a microcode idle command is completed, the ADV_DVC_VAR
8412 * 'idle_cmd_done' field is set to ADV_TRUE.
8413 *
8414 * Note: AdvISR() can be called when interrupts are disabled or even
8415 * when there is no hardware interrupt condition present. It will
8416 * always check for completed idle commands and microcode requests.
8417 * This is an important feature that shouldn't be changed because it
8418 * allows commands to be completed from polling mode loops.
8419 *
8420 * Return:
8421 * ADV_TRUE(1) - interrupt was pending
8422 * ADV_FALSE(0) - no interrupt was pending
8423 */
8424static int AdvISR(ADV_DVC_VAR *asc_dvc)
8425{
8426 AdvPortAddr iop_base;
8427 uchar int_stat;
8428 ushort target_bit;
8429 ADV_CARR_T *free_carrp;
8430 ADV_VADDR irq_next_vpa;
8431 ADV_SCSI_REQ_Q *scsiq;
8432
8433 iop_base = asc_dvc->iop_base;
8434
8435 /* Reading the register clears the interrupt. */
8436 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
8437
8438 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
8439 ADV_INTR_STATUS_INTRC)) == 0) {
8440 return ADV_FALSE;
8441 }
8442
8443 /*
8444 * Notify the driver of an asynchronous microcode condition by
8445 * calling the adv_async_callback function. The function
8446 * is passed the microcode ASC_MC_INTRB_CODE byte value.
8447 */
8448 if (int_stat & ADV_INTR_STATUS_INTRB) {
8449 uchar intrb_code;
8450
8451 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
8452
8453 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
8454 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8455 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
8456 asc_dvc->carr_pending_cnt != 0) {
8457 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
8458 ADV_TICKLE_A);
8459 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
8460 AdvWriteByteRegister(iop_base,
8461 IOPB_TICKLE,
8462 ADV_TICKLE_NOP);
8463 }
8464 }
8465 }
8466
8467 adv_async_callback(asc_dvc, intrb_code);
8468 }
8469
8470 /*
8471 * Check if the IRQ stopper carrier contains a completed request.
8472 */
8473 while (((irq_next_vpa =
8474 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
8475 /*
8476 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
8477 * The RISC will have set 'areq_vpa' to a virtual address.
8478 *
8479 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
8480 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
8481 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
8482 * in AdvExeScsiQueue().
8483 */
8484 scsiq = (ADV_SCSI_REQ_Q *)
8485 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
8486
8487 /*
8488 * Request finished with good status and the queue was not
8489 * DMAed to host memory by the firmware. Set all status fields
8490 * to indicate good status.
8491 */
8492 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
8493 scsiq->done_status = QD_NO_ERROR;
8494 scsiq->host_status = scsiq->scsi_status = 0;
8495 scsiq->data_cnt = 0L;
8496 }
8497
8498 /*
8499 * Advance the stopper pointer to the next carrier
8500 * ignoring the lower four bits. Free the previous
8501 * stopper carrier.
8502 */
8503 free_carrp = asc_dvc->irq_sp;
8504 asc_dvc->irq_sp = (ADV_CARR_T *)
8505 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
8506
8507 free_carrp->next_vpa =
8508 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
8509 asc_dvc->carr_freelist = free_carrp;
8510 asc_dvc->carr_pending_cnt--;
8511
8512 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
8513
8514 /*
8515 * Clear request microcode control flag.
8516 */
8517 scsiq->cntl = 0;
8518
8519 /*
8520 * Notify the driver of the completed request by passing
8521 * the ADV_SCSI_REQ_Q pointer to its callback function.
8522 */
8523 scsiq->a_flag |= ADV_SCSIQ_DONE;
8524 adv_isr_callback(asc_dvc, scsiq);
8525 /*
8526 * Note: After the driver callback function is called, 'scsiq'
8527 * can no longer be referenced.
8528 *
8529 * Fall through and continue processing other completed
8530 * requests...
8531 */
8532 }
8533 return ADV_TRUE;
8534}
8535
8536static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
8537{
8538 if (asc_dvc->err_code == 0) {
8539 asc_dvc->err_code = err_code;
8540 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8541 err_code);
8542 }
8543 return err_code;
8544}
8545
8546static void AscAckInterrupt(PortAddr iop_base)
8547{
8548 uchar host_flag;
8549 uchar risc_flag;
8550 ushort loop;
8551
8552 loop = 0;
8553 do {
8554 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8555 if (loop++ > 0x7FFF) {
8556 break;
8557 }
8558 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8559 host_flag =
8560 AscReadLramByte(iop_base,
8561 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8562 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8563 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8564 AscSetChipStatus(iop_base, CIW_INT_ACK);
8565 loop = 0;
8566 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8567 AscSetChipStatus(iop_base, CIW_INT_ACK);
8568 if (loop++ > 3) {
8569 break;
8570 }
8571 }
8572 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8573 return;
8574}
8575
8576static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
8577{
8578 uchar *period_table;
8579 int max_index;
8580 int min_index;
8581 int i;
8582
8583 period_table = asc_dvc->sdtr_period_tbl;
8584 max_index = (int)asc_dvc->max_sdtr_index;
8585 min_index = (int)asc_dvc->host_init_sdtr_index;
8586 if ((syn_time <= period_table[max_index])) {
8587 for (i = min_index; i < (max_index - 1); i++) {
8588 if (syn_time <= period_table[i]) {
8589 return (uchar)i;
8590 }
8591 }
8592 return (uchar)max_index;
8593 } else {
8594 return (uchar)(max_index + 1);
8595 }
8596}
8597
8598static uchar
8599AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
8600{
8601 EXT_MSG sdtr_buf;
8602 uchar sdtr_period_index;
8603 PortAddr iop_base;
8604
8605 iop_base = asc_dvc->iop_base;
8606 sdtr_buf.msg_type = EXTENDED_MESSAGE;
8607 sdtr_buf.msg_len = MS_SDTR_LEN;
8608 sdtr_buf.msg_req = EXTENDED_SDTR;
8609 sdtr_buf.xfer_period = sdtr_period;
8610 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8611 sdtr_buf.req_ack_offset = sdtr_offset;
8612 sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8613 if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
8614 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8615 (uchar *)&sdtr_buf,
8616 sizeof(EXT_MSG) >> 1);
8617 return ((sdtr_period_index << 4) | sdtr_offset);
8618 } else {
8619 sdtr_buf.req_ack_offset = 0;
8620 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8621 (uchar *)&sdtr_buf,
8622 sizeof(EXT_MSG) >> 1);
8623 return 0;
8624 }
8625}
8626
8627static uchar
8628AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
8629{
8630 uchar byte;
8631 uchar sdtr_period_ix;
8632
8633 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8634 if (sdtr_period_ix > asc_dvc->max_sdtr_index) {
8635 return 0xFF;
8636 }
8637 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8638 return byte;
8639}
8640
8641static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
8642{
8643 ASC_SCSI_BIT_ID_TYPE org_id;
8644 int i;
8645 int sta = TRUE;
8646
8647 AscSetBank(iop_base, 1);
8648 org_id = AscReadChipDvcID(iop_base);
8649 for (i = 0; i <= ASC_MAX_TID; i++) {
8650 if (org_id == (0x01 << i))
8651 break;
8652 }
8653 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8654 AscWriteChipDvcID(iop_base, id);
8655 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8656 AscSetBank(iop_base, 0);
8657 AscSetChipSyn(iop_base, sdtr_data);
8658 if (AscGetChipSyn(iop_base) != sdtr_data) {
8659 sta = FALSE;
8660 }
8661 } else {
8662 sta = FALSE;
8663 }
8664 AscSetBank(iop_base, 1);
8665 AscWriteChipDvcID(iop_base, org_id);
8666 AscSetBank(iop_base, 0);
8667 return (sta);
8668}
8669
8670static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
8671{
8672 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8673 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8674}
8675
8676static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
8677{
8678 EXT_MSG ext_msg;
8679 EXT_MSG out_msg;
8680 ushort halt_q_addr;
8681 int sdtr_accept;
8682 ushort int_halt_code;
8683 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8684 ASC_SCSI_BIT_ID_TYPE target_id;
8685 PortAddr iop_base;
8686 uchar tag_code;
8687 uchar q_status;
8688 uchar halt_qp;
8689 uchar sdtr_data;
8690 uchar target_ix;
8691 uchar q_cntl, tid_no;
8692 uchar cur_dvc_qng;
8693 uchar asyn_sdtr;
8694 uchar scsi_status;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008695 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04008696
8697 BUG_ON(!asc_dvc->drv_ptr);
8698 boardp = asc_dvc->drv_ptr;
8699
8700 iop_base = asc_dvc->iop_base;
8701 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
8702
8703 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8704 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8705 target_ix = AscReadLramByte(iop_base,
8706 (ushort)(halt_q_addr +
8707 (ushort)ASC_SCSIQ_B_TARGET_IX));
8708 q_cntl = AscReadLramByte(iop_base,
8709 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8710 tid_no = ASC_TIX_TO_TID(target_ix);
8711 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8712 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8713 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8714 } else {
8715 asyn_sdtr = 0;
8716 }
8717 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8718 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8719 AscSetChipSDTR(iop_base, 0, tid_no);
8720 boardp->sdtr_data[tid_no] = 0;
8721 }
8722 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8723 return (0);
8724 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8725 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8726 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8727 boardp->sdtr_data[tid_no] = asyn_sdtr;
8728 }
8729 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8730 return (0);
8731 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
8732 AscMemWordCopyPtrFromLram(iop_base,
8733 ASCV_MSGIN_BEG,
8734 (uchar *)&ext_msg,
8735 sizeof(EXT_MSG) >> 1);
8736
8737 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8738 ext_msg.msg_req == EXTENDED_SDTR &&
8739 ext_msg.msg_len == MS_SDTR_LEN) {
8740 sdtr_accept = TRUE;
8741 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
8742
8743 sdtr_accept = FALSE;
8744 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8745 }
8746 if ((ext_msg.xfer_period <
8747 asc_dvc->sdtr_period_tbl[asc_dvc->
8748 host_init_sdtr_index])
8749 || (ext_msg.xfer_period >
8750 asc_dvc->sdtr_period_tbl[asc_dvc->
8751 max_sdtr_index])) {
8752 sdtr_accept = FALSE;
8753 ext_msg.xfer_period =
8754 asc_dvc->sdtr_period_tbl[asc_dvc->
8755 host_init_sdtr_index];
8756 }
8757 if (sdtr_accept) {
8758 sdtr_data =
8759 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8760 ext_msg.req_ack_offset);
8761 if ((sdtr_data == 0xFF)) {
8762
8763 q_cntl |= QC_MSG_OUT;
8764 asc_dvc->init_sdtr &= ~target_id;
8765 asc_dvc->sdtr_done &= ~target_id;
8766 AscSetChipSDTR(iop_base, asyn_sdtr,
8767 tid_no);
8768 boardp->sdtr_data[tid_no] = asyn_sdtr;
8769 }
8770 }
8771 if (ext_msg.req_ack_offset == 0) {
8772
8773 q_cntl &= ~QC_MSG_OUT;
8774 asc_dvc->init_sdtr &= ~target_id;
8775 asc_dvc->sdtr_done &= ~target_id;
8776 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8777 } else {
8778 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
8779
8780 q_cntl &= ~QC_MSG_OUT;
8781 asc_dvc->sdtr_done |= target_id;
8782 asc_dvc->init_sdtr |= target_id;
8783 asc_dvc->pci_fix_asyn_xfer &=
8784 ~target_id;
8785 sdtr_data =
8786 AscCalSDTRData(asc_dvc,
8787 ext_msg.xfer_period,
8788 ext_msg.
8789 req_ack_offset);
8790 AscSetChipSDTR(iop_base, sdtr_data,
8791 tid_no);
8792 boardp->sdtr_data[tid_no] = sdtr_data;
8793 } else {
8794
8795 q_cntl |= QC_MSG_OUT;
8796 AscMsgOutSDTR(asc_dvc,
8797 ext_msg.xfer_period,
8798 ext_msg.req_ack_offset);
8799 asc_dvc->pci_fix_asyn_xfer &=
8800 ~target_id;
8801 sdtr_data =
8802 AscCalSDTRData(asc_dvc,
8803 ext_msg.xfer_period,
8804 ext_msg.
8805 req_ack_offset);
8806 AscSetChipSDTR(iop_base, sdtr_data,
8807 tid_no);
8808 boardp->sdtr_data[tid_no] = sdtr_data;
8809 asc_dvc->sdtr_done |= target_id;
8810 asc_dvc->init_sdtr |= target_id;
8811 }
8812 }
8813
8814 AscWriteLramByte(iop_base,
8815 (ushort)(halt_q_addr +
8816 (ushort)ASC_SCSIQ_B_CNTL),
8817 q_cntl);
8818 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8819 return (0);
8820 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8821 ext_msg.msg_req == EXTENDED_WDTR &&
8822 ext_msg.msg_len == MS_WDTR_LEN) {
8823
8824 ext_msg.wdtr_width = 0;
8825 AscMemWordCopyPtrToLram(iop_base,
8826 ASCV_MSGOUT_BEG,
8827 (uchar *)&ext_msg,
8828 sizeof(EXT_MSG) >> 1);
8829 q_cntl |= QC_MSG_OUT;
8830 AscWriteLramByte(iop_base,
8831 (ushort)(halt_q_addr +
8832 (ushort)ASC_SCSIQ_B_CNTL),
8833 q_cntl);
8834 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8835 return (0);
8836 } else {
8837
8838 ext_msg.msg_type = MESSAGE_REJECT;
8839 AscMemWordCopyPtrToLram(iop_base,
8840 ASCV_MSGOUT_BEG,
8841 (uchar *)&ext_msg,
8842 sizeof(EXT_MSG) >> 1);
8843 q_cntl |= QC_MSG_OUT;
8844 AscWriteLramByte(iop_base,
8845 (ushort)(halt_q_addr +
8846 (ushort)ASC_SCSIQ_B_CNTL),
8847 q_cntl);
8848 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8849 return (0);
8850 }
8851 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
8852
8853 q_cntl |= QC_REQ_SENSE;
8854
8855 if ((asc_dvc->init_sdtr & target_id) != 0) {
8856
8857 asc_dvc->sdtr_done &= ~target_id;
8858
8859 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8860 q_cntl |= QC_MSG_OUT;
8861 AscMsgOutSDTR(asc_dvc,
8862 asc_dvc->
8863 sdtr_period_tbl[(sdtr_data >> 4) &
8864 (uchar)(asc_dvc->
8865 max_sdtr_index -
8866 1)],
8867 (uchar)(sdtr_data & (uchar)
8868 ASC_SYN_MAX_OFFSET));
8869 }
8870
8871 AscWriteLramByte(iop_base,
8872 (ushort)(halt_q_addr +
8873 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8874
8875 tag_code = AscReadLramByte(iop_base,
8876 (ushort)(halt_q_addr + (ushort)
8877 ASC_SCSIQ_B_TAG_CODE));
8878 tag_code &= 0xDC;
8879 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
8880 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
8881 ) {
8882
8883 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
8884 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
8885
8886 }
8887 AscWriteLramByte(iop_base,
8888 (ushort)(halt_q_addr +
8889 (ushort)ASC_SCSIQ_B_TAG_CODE),
8890 tag_code);
8891
8892 q_status = AscReadLramByte(iop_base,
8893 (ushort)(halt_q_addr + (ushort)
8894 ASC_SCSIQ_B_STATUS));
8895 q_status |= (QS_READY | QS_BUSY);
8896 AscWriteLramByte(iop_base,
8897 (ushort)(halt_q_addr +
8898 (ushort)ASC_SCSIQ_B_STATUS),
8899 q_status);
8900
8901 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
8902 scsi_busy &= ~target_id;
8903 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8904
8905 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8906 return (0);
8907 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
8908
8909 AscMemWordCopyPtrFromLram(iop_base,
8910 ASCV_MSGOUT_BEG,
8911 (uchar *)&out_msg,
8912 sizeof(EXT_MSG) >> 1);
8913
8914 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
8915 (out_msg.msg_len == MS_SDTR_LEN) &&
8916 (out_msg.msg_req == EXTENDED_SDTR)) {
8917
8918 asc_dvc->init_sdtr &= ~target_id;
8919 asc_dvc->sdtr_done &= ~target_id;
8920 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8921 boardp->sdtr_data[tid_no] = asyn_sdtr;
8922 }
8923 q_cntl &= ~QC_MSG_OUT;
8924 AscWriteLramByte(iop_base,
8925 (ushort)(halt_q_addr +
8926 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8927 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8928 return (0);
8929 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
8930
8931 scsi_status = AscReadLramByte(iop_base,
8932 (ushort)((ushort)halt_q_addr +
8933 (ushort)
8934 ASC_SCSIQ_SCSI_STATUS));
8935 cur_dvc_qng =
8936 AscReadLramByte(iop_base,
8937 (ushort)((ushort)ASC_QADR_BEG +
8938 (ushort)target_ix));
8939 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
8940
8941 scsi_busy = AscReadLramByte(iop_base,
8942 (ushort)ASCV_SCSIBUSY_B);
8943 scsi_busy |= target_id;
8944 AscWriteLramByte(iop_base,
8945 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8946 asc_dvc->queue_full_or_busy |= target_id;
8947
8948 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
8949 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
8950 cur_dvc_qng -= 1;
8951 asc_dvc->max_dvc_qng[tid_no] =
8952 cur_dvc_qng;
8953
8954 AscWriteLramByte(iop_base,
8955 (ushort)((ushort)
8956 ASCV_MAX_DVC_QNG_BEG
8957 + (ushort)
8958 tid_no),
8959 cur_dvc_qng);
8960
8961 /*
8962 * Set the device queue depth to the
8963 * number of active requests when the
8964 * QUEUE FULL condition was encountered.
8965 */
8966 boardp->queue_full |= target_id;
8967 boardp->queue_full_cnt[tid_no] =
8968 cur_dvc_qng;
8969 }
8970 }
8971 }
8972 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8973 return (0);
8974 }
8975#if CC_VERY_LONG_SG_LIST
8976 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
8977 uchar q_no;
8978 ushort q_addr;
8979 uchar sg_wk_q_no;
8980 uchar first_sg_wk_q_no;
8981 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
8982 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
8983 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
8984 ushort sg_list_dwords;
8985 ushort sg_entry_cnt;
8986 uchar next_qp;
8987 int i;
8988
8989 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
8990 if (q_no == ASC_QLINK_END)
8991 return 0;
8992
8993 q_addr = ASC_QNO_TO_QADDR(q_no);
8994
8995 /*
8996 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
8997 * structure pointer using a macro provided by the driver.
8998 * The ASC_SCSI_REQ pointer provides a pointer to the
8999 * host ASC_SG_HEAD structure.
9000 */
9001 /* Read request's SRB pointer. */
9002 scsiq = (ASC_SCSI_Q *)
9003 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
9004 (ushort)
9005 (q_addr +
9006 ASC_SCSIQ_D_SRBPTR))));
9007
9008 /*
9009 * Get request's first and working SG queue.
9010 */
9011 sg_wk_q_no = AscReadLramByte(iop_base,
9012 (ushort)(q_addr +
9013 ASC_SCSIQ_B_SG_WK_QP));
9014
9015 first_sg_wk_q_no = AscReadLramByte(iop_base,
9016 (ushort)(q_addr +
9017 ASC_SCSIQ_B_FIRST_SG_WK_QP));
9018
9019 /*
9020 * Reset request's working SG queue back to the
9021 * first SG queue.
9022 */
9023 AscWriteLramByte(iop_base,
9024 (ushort)(q_addr +
9025 (ushort)ASC_SCSIQ_B_SG_WK_QP),
9026 first_sg_wk_q_no);
9027
9028 sg_head = scsiq->sg_head;
9029
9030 /*
9031 * Set sg_entry_cnt to the number of SG elements
9032 * that will be completed on this interrupt.
9033 *
9034 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
9035 * SG elements. The data_cnt and data_addr fields which
9036 * add 1 to the SG element capacity are not used when
9037 * restarting SG handling after a halt.
9038 */
9039 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
9040 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
9041
9042 /*
9043 * Keep track of remaining number of SG elements that
9044 * will need to be handled on the next interrupt.
9045 */
9046 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
9047 } else {
9048 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
9049 scsiq->remain_sg_entry_cnt = 0;
9050 }
9051
9052 /*
9053 * Copy SG elements into the list of allocated SG queues.
9054 *
9055 * Last index completed is saved in scsiq->next_sg_index.
9056 */
9057 next_qp = first_sg_wk_q_no;
9058 q_addr = ASC_QNO_TO_QADDR(next_qp);
9059 scsi_sg_q.sg_head_qp = q_no;
9060 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9061 for (i = 0; i < sg_head->queue_cnt; i++) {
9062 scsi_sg_q.seq_no = i + 1;
9063 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9064 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9065 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9066 /*
9067 * After very first SG queue RISC FW uses next
9068 * SG queue first element then checks sg_list_cnt
9069 * against zero and then decrements, so set
9070 * sg_list_cnt 1 less than number of SG elements
9071 * in each SG queue.
9072 */
9073 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
9074 scsi_sg_q.sg_cur_list_cnt =
9075 ASC_SG_LIST_PER_Q - 1;
9076 } else {
9077 /*
9078 * This is the last SG queue in the list of
9079 * allocated SG queues. If there are more
9080 * SG elements than will fit in the allocated
9081 * queues, then set the QCSG_SG_XFER_MORE flag.
9082 */
9083 if (scsiq->remain_sg_entry_cnt != 0) {
9084 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9085 } else {
9086 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
9087 }
9088 /* equals sg_entry_cnt * 2 */
9089 sg_list_dwords = sg_entry_cnt << 1;
9090 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
9091 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
9092 sg_entry_cnt = 0;
9093 }
9094
9095 scsi_sg_q.q_no = next_qp;
9096 AscMemWordCopyPtrToLram(iop_base,
9097 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9098 (uchar *)&scsi_sg_q,
9099 sizeof(ASC_SG_LIST_Q) >> 1);
9100
9101 AscMemDWordCopyPtrToLram(iop_base,
9102 q_addr + ASC_SGQ_LIST_BEG,
9103 (uchar *)&sg_head->
9104 sg_list[scsiq->next_sg_index],
9105 sg_list_dwords);
9106
9107 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
9108
9109 /*
9110 * If the just completed SG queue contained the
9111 * last SG element, then no more SG queues need
9112 * to be written.
9113 */
9114 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
9115 break;
9116 }
9117
9118 next_qp = AscReadLramByte(iop_base,
9119 (ushort)(q_addr +
9120 ASC_SCSIQ_B_FWD));
9121 q_addr = ASC_QNO_TO_QADDR(next_qp);
9122 }
9123
9124 /*
9125 * Clear the halt condition so the RISC will be restarted
9126 * after the return.
9127 */
9128 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9129 return (0);
9130 }
9131#endif /* CC_VERY_LONG_SG_LIST */
9132 return (0);
9133}
9134
9135/*
9136 * void
9137 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9138 *
9139 * Calling/Exit State:
9140 * none
9141 *
9142 * Description:
9143 * Input an ASC_QDONE_INFO structure from the chip
9144 */
9145static void
9146DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9147{
9148 int i;
9149 ushort word;
9150
9151 AscSetChipLramAddr(iop_base, s_addr);
9152 for (i = 0; i < 2 * words; i += 2) {
9153 if (i == 10) {
9154 continue;
9155 }
9156 word = inpw(iop_base + IOP_RAM_DATA);
9157 inbuf[i] = word & 0xff;
9158 inbuf[i + 1] = (word >> 8) & 0xff;
9159 }
9160 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
9161}
9162
9163static uchar
9164_AscCopyLramScsiDoneQ(PortAddr iop_base,
9165 ushort q_addr,
9166 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
9167{
9168 ushort _val;
9169 uchar sg_queue_cnt;
9170
9171 DvcGetQinfo(iop_base,
9172 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
9173 (uchar *)scsiq,
9174 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
9175
9176 _val = AscReadLramWord(iop_base,
9177 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
9178 scsiq->q_status = (uchar)_val;
9179 scsiq->q_no = (uchar)(_val >> 8);
9180 _val = AscReadLramWord(iop_base,
9181 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
9182 scsiq->cntl = (uchar)_val;
9183 sg_queue_cnt = (uchar)(_val >> 8);
9184 _val = AscReadLramWord(iop_base,
9185 (ushort)(q_addr +
9186 (ushort)ASC_SCSIQ_B_SENSE_LEN));
9187 scsiq->sense_len = (uchar)_val;
9188 scsiq->extra_bytes = (uchar)(_val >> 8);
9189
9190 /*
9191 * Read high word of remain bytes from alternate location.
9192 */
9193 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
9194 (ushort)(q_addr +
9195 (ushort)
9196 ASC_SCSIQ_W_ALT_DC1)))
9197 << 16);
9198 /*
9199 * Read low word of remain bytes from original location.
9200 */
9201 scsiq->remain_bytes += AscReadLramWord(iop_base,
9202 (ushort)(q_addr + (ushort)
9203 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
9204
9205 scsiq->remain_bytes &= max_dma_count;
9206 return sg_queue_cnt;
9207}
9208
9209/*
9210 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
9211 *
9212 * Interrupt callback function for the Narrow SCSI Asc Library.
9213 */
9214static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9215{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009216 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04009217 struct scsi_cmnd *scp;
9218 struct Scsi_Host *shost;
9219
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009220 ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
Matthew Wilcox51219352007-10-02 21:55:22 -04009221 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
9222
9223 /*
9224 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
9225 * command that has been completed.
9226 */
9227 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009228 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009229
9230 if (scp == NULL) {
9231 ASC_PRINT("asc_isr_callback: scp is NULL\n");
9232 return;
9233 }
9234 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
9235
9236 shost = scp->device->host;
9237 ASC_STATS(shost, callback);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009238 ASC_DBG(1, "shost 0x%p\n", shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009239
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009240 boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009241 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
9242
9243 /*
9244 * 'qdonep' contains the command's ending status.
9245 */
9246 switch (qdonep->d3.done_stat) {
9247 case QD_NO_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009248 ASC_DBG(2, "QD_NO_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009249 scp->result = 0;
9250
9251 /*
9252 * Check for an underrun condition.
9253 *
9254 * If there was no error and an underrun condition, then
9255 * return the number of underrun bytes.
9256 */
9257 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
9258 qdonep->remain_bytes <= scp->request_bufflen) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009259 ASC_DBG(1, "underrun condition %u bytes\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04009260 (unsigned)qdonep->remain_bytes);
9261 scp->resid = qdonep->remain_bytes;
9262 }
9263 break;
9264
9265 case QD_WITH_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009266 ASC_DBG(2, "QD_WITH_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009267 switch (qdonep->d3.host_stat) {
9268 case QHSTA_NO_ERROR:
9269 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009270 ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009271 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
9272 sizeof(scp->sense_buffer));
9273 /*
9274 * Note: The 'status_byte()' macro used by
9275 * target drivers defined in scsi.h shifts the
9276 * status byte returned by host drivers right
9277 * by 1 bit. This is why target drivers also
9278 * use right shifted status byte definitions.
9279 * For instance target drivers use
9280 * CHECK_CONDITION, defined to 0x1, instead of
9281 * the SCSI defined check condition value of
9282 * 0x2. Host drivers are supposed to return
9283 * the status byte as it is defined by SCSI.
9284 */
9285 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
9286 STATUS_BYTE(qdonep->d3.scsi_stat);
9287 } else {
9288 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
9289 }
9290 break;
9291
9292 default:
9293 /* QHSTA error occurred */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009294 ASC_DBG(1, "host_stat 0x%x\n", qdonep->d3.host_stat);
Matthew Wilcox51219352007-10-02 21:55:22 -04009295 scp->result = HOST_BYTE(DID_BAD_TARGET);
9296 break;
9297 }
9298 break;
9299
9300 case QD_ABORTED_BY_HOST:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009301 ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009302 scp->result =
9303 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
9304 scsi_msg) |
9305 STATUS_BYTE(qdonep->d3.scsi_stat);
9306 break;
9307
9308 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009309 ASC_DBG(1, "done_stat 0x%x\n", qdonep->d3.done_stat);
Matthew Wilcox51219352007-10-02 21:55:22 -04009310 scp->result =
9311 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
9312 scsi_msg) |
9313 STATUS_BYTE(qdonep->d3.scsi_stat);
9314 break;
9315 }
9316
9317 /*
9318 * If the 'init_tidmask' bit isn't already set for the target and the
9319 * current request finished normally, then set the bit for the target
9320 * to indicate that a device is present.
9321 */
9322 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
9323 qdonep->d3.done_stat == QD_NO_ERROR &&
9324 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
9325 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
9326 }
9327
9328 asc_scsi_done(scp);
9329
9330 return;
9331}
9332
9333static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
9334{
9335 uchar next_qp;
9336 uchar n_q_used;
9337 uchar sg_list_qp;
9338 uchar sg_queue_cnt;
9339 uchar q_cnt;
9340 uchar done_q_tail;
9341 uchar tid_no;
9342 ASC_SCSI_BIT_ID_TYPE scsi_busy;
9343 ASC_SCSI_BIT_ID_TYPE target_id;
9344 PortAddr iop_base;
9345 ushort q_addr;
9346 ushort sg_q_addr;
9347 uchar cur_target_qng;
9348 ASC_QDONE_INFO scsiq_buf;
9349 ASC_QDONE_INFO *scsiq;
9350 int false_overrun;
9351
9352 iop_base = asc_dvc->iop_base;
9353 n_q_used = 1;
9354 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
9355 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
9356 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
9357 next_qp = AscReadLramByte(iop_base,
9358 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
9359 if (next_qp != ASC_QLINK_END) {
9360 AscPutVarDoneQTail(iop_base, next_qp);
9361 q_addr = ASC_QNO_TO_QADDR(next_qp);
9362 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
9363 asc_dvc->max_dma_count);
9364 AscWriteLramByte(iop_base,
9365 (ushort)(q_addr +
9366 (ushort)ASC_SCSIQ_B_STATUS),
9367 (uchar)(scsiq->
9368 q_status & (uchar)~(QS_READY |
9369 QS_ABORTED)));
9370 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
9371 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
9372 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
9373 sg_q_addr = q_addr;
9374 sg_list_qp = next_qp;
9375 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
9376 sg_list_qp = AscReadLramByte(iop_base,
9377 (ushort)(sg_q_addr
9378 + (ushort)
9379 ASC_SCSIQ_B_FWD));
9380 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
9381 if (sg_list_qp == ASC_QLINK_END) {
9382 AscSetLibErrorCode(asc_dvc,
9383 ASCQ_ERR_SG_Q_LINKS);
9384 scsiq->d3.done_stat = QD_WITH_ERROR;
9385 scsiq->d3.host_stat =
9386 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
9387 goto FATAL_ERR_QDONE;
9388 }
9389 AscWriteLramByte(iop_base,
9390 (ushort)(sg_q_addr + (ushort)
9391 ASC_SCSIQ_B_STATUS),
9392 QS_FREE);
9393 }
9394 n_q_used = sg_queue_cnt + 1;
9395 AscPutVarDoneQTail(iop_base, sg_list_qp);
9396 }
9397 if (asc_dvc->queue_full_or_busy & target_id) {
9398 cur_target_qng = AscReadLramByte(iop_base,
9399 (ushort)((ushort)
9400 ASC_QADR_BEG
9401 + (ushort)
9402 scsiq->d2.
9403 target_ix));
9404 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
9405 scsi_busy = AscReadLramByte(iop_base, (ushort)
9406 ASCV_SCSIBUSY_B);
9407 scsi_busy &= ~target_id;
9408 AscWriteLramByte(iop_base,
9409 (ushort)ASCV_SCSIBUSY_B,
9410 scsi_busy);
9411 asc_dvc->queue_full_or_busy &= ~target_id;
9412 }
9413 }
9414 if (asc_dvc->cur_total_qng >= n_q_used) {
9415 asc_dvc->cur_total_qng -= n_q_used;
9416 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
9417 asc_dvc->cur_dvc_qng[tid_no]--;
9418 }
9419 } else {
9420 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
9421 scsiq->d3.done_stat = QD_WITH_ERROR;
9422 goto FATAL_ERR_QDONE;
9423 }
9424 if ((scsiq->d2.srb_ptr == 0UL) ||
9425 ((scsiq->q_status & QS_ABORTED) != 0)) {
9426 return (0x11);
9427 } else if (scsiq->q_status == QS_DONE) {
9428 false_overrun = FALSE;
9429 if (scsiq->extra_bytes != 0) {
9430 scsiq->remain_bytes +=
9431 (ADV_DCNT)scsiq->extra_bytes;
9432 }
9433 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
9434 if (scsiq->d3.host_stat ==
9435 QHSTA_M_DATA_OVER_RUN) {
9436 if ((scsiq->
9437 cntl & (QC_DATA_IN | QC_DATA_OUT))
9438 == 0) {
9439 scsiq->d3.done_stat =
9440 QD_NO_ERROR;
9441 scsiq->d3.host_stat =
9442 QHSTA_NO_ERROR;
9443 } else if (false_overrun) {
9444 scsiq->d3.done_stat =
9445 QD_NO_ERROR;
9446 scsiq->d3.host_stat =
9447 QHSTA_NO_ERROR;
9448 }
9449 } else if (scsiq->d3.host_stat ==
9450 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
9451 AscStopChip(iop_base);
9452 AscSetChipControl(iop_base,
9453 (uchar)(CC_SCSI_RESET
9454 | CC_HALT));
9455 udelay(60);
9456 AscSetChipControl(iop_base, CC_HALT);
9457 AscSetChipStatus(iop_base,
9458 CIW_CLR_SCSI_RESET_INT);
9459 AscSetChipStatus(iop_base, 0);
9460 AscSetChipControl(iop_base, 0);
9461 }
9462 }
9463 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9464 asc_isr_callback(asc_dvc, scsiq);
9465 } else {
9466 if ((AscReadLramByte(iop_base,
9467 (ushort)(q_addr + (ushort)
9468 ASC_SCSIQ_CDB_BEG))
9469 == START_STOP)) {
9470 asc_dvc->unit_not_ready &= ~target_id;
9471 if (scsiq->d3.done_stat != QD_NO_ERROR) {
9472 asc_dvc->start_motor &=
9473 ~target_id;
9474 }
9475 }
9476 }
9477 return (1);
9478 } else {
9479 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
9480 FATAL_ERR_QDONE:
9481 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9482 asc_isr_callback(asc_dvc, scsiq);
9483 }
9484 return (0x80);
9485 }
9486 }
9487 return (0);
9488}
9489
9490static int AscISR(ASC_DVC_VAR *asc_dvc)
9491{
9492 ASC_CS_TYPE chipstat;
9493 PortAddr iop_base;
9494 ushort saved_ram_addr;
9495 uchar ctrl_reg;
9496 uchar saved_ctrl_reg;
9497 int int_pending;
9498 int status;
9499 uchar host_flag;
9500
9501 iop_base = asc_dvc->iop_base;
9502 int_pending = FALSE;
9503
9504 if (AscIsIntPending(iop_base) == 0)
9505 return int_pending;
9506
9507 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
9508 return ERR;
9509 }
9510 if (asc_dvc->in_critical_cnt != 0) {
9511 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
9512 return ERR;
9513 }
9514 if (asc_dvc->is_in_int) {
9515 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
9516 return ERR;
9517 }
9518 asc_dvc->is_in_int = TRUE;
9519 ctrl_reg = AscGetChipControl(iop_base);
9520 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
9521 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
9522 chipstat = AscGetChipStatus(iop_base);
9523 if (chipstat & CSW_SCSI_RESET_LATCH) {
9524 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
9525 int i = 10;
9526 int_pending = TRUE;
9527 asc_dvc->sdtr_done = 0;
9528 saved_ctrl_reg &= (uchar)(~CC_HALT);
9529 while ((AscGetChipStatus(iop_base) &
9530 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
9531 mdelay(100);
9532 }
9533 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
9534 AscSetChipControl(iop_base, CC_HALT);
9535 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9536 AscSetChipStatus(iop_base, 0);
9537 chipstat = AscGetChipStatus(iop_base);
9538 }
9539 }
9540 saved_ram_addr = AscGetChipLramAddr(iop_base);
9541 host_flag = AscReadLramByte(iop_base,
9542 ASCV_HOST_FLAG_B) &
9543 (uchar)(~ASC_HOST_FLAG_IN_ISR);
9544 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
9545 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
9546 if ((chipstat & CSW_INT_PENDING) || (int_pending)) {
9547 AscAckInterrupt(iop_base);
9548 int_pending = TRUE;
9549 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
9550 if (AscIsrChipHalted(asc_dvc) == ERR) {
9551 goto ISR_REPORT_QDONE_FATAL_ERROR;
9552 } else {
9553 saved_ctrl_reg &= (uchar)(~CC_HALT);
9554 }
9555 } else {
9556 ISR_REPORT_QDONE_FATAL_ERROR:
9557 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
9558 while (((status =
9559 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
9560 }
9561 } else {
9562 do {
9563 if ((status =
9564 AscIsrQDone(asc_dvc)) == 1) {
9565 break;
9566 }
9567 } while (status == 0x11);
9568 }
9569 if ((status & 0x80) != 0)
9570 int_pending = ERR;
9571 }
9572 }
9573 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9574 AscSetChipLramAddr(iop_base, saved_ram_addr);
9575 AscSetChipControl(iop_base, saved_ctrl_reg);
9576 asc_dvc->is_in_int = FALSE;
9577 return int_pending;
9578}
9579
9580/*
9581 * advansys_reset()
9582 *
9583 * Reset the bus associated with the command 'scp'.
9584 *
9585 * This function runs its own thread. Interrupts must be blocked but
9586 * sleeping is allowed and no locking other than for host structures is
9587 * required. Returns SUCCESS or FAILED.
9588 */
9589static int advansys_reset(struct scsi_cmnd *scp)
9590{
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009591 struct Scsi_Host *shost = scp->device->host;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009592 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009593 unsigned long flags;
Matthew Wilcox51219352007-10-02 21:55:22 -04009594 int status;
9595 int ret = SUCCESS;
9596
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009597 ASC_DBG(1, "0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009598
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009599 ASC_STATS(shost, reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04009600
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009601 scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009602
9603 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009604 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009605
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009606 /* Reset the chip and SCSI bus. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009607 ASC_DBG(1, "before AscInitAsc1000Driver()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009608 status = AscInitAsc1000Driver(asc_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009609
9610 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009611 if (asc_dvc->err_code) {
9612 scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
9613 "0x%x\n", asc_dvc->err_code);
Matthew Wilcox51219352007-10-02 21:55:22 -04009614 ret = FAILED;
9615 } else if (status) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009616 scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
9617 "0x%x\n", status);
Matthew Wilcox51219352007-10-02 21:55:22 -04009618 } else {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009619 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9620 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009621 }
9622
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009623 ASC_DBG(1, "after AscInitAsc1000Driver()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009624 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009625 } else {
9626 /*
Matthew Wilcox51219352007-10-02 21:55:22 -04009627 * If the suggest reset bus flags are set, then reset the bus.
9628 * Otherwise only reset the device.
9629 */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009630 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009631
9632 /*
9633 * Reset the target's SCSI bus.
9634 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009635 ASC_DBG(1, "before AdvResetChipAndSB()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009636 switch (AdvResetChipAndSB(adv_dvc)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04009637 case ASC_TRUE:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009638 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9639 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009640 break;
9641 case ASC_FALSE:
9642 default:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009643 scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009644 ret = FAILED;
9645 break;
9646 }
9647 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009648 AdvISR(adv_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009649 }
Matthew Wilcox51219352007-10-02 21:55:22 -04009650
9651 /* Save the time of the most recently completed reset. */
9652 boardp->last_reset = jiffies;
Matthew Wilcox51219352007-10-02 21:55:22 -04009653 spin_unlock_irqrestore(&boardp->lock, flags);
9654
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009655 ASC_DBG(1, "ret %d\n", ret);
Matthew Wilcox51219352007-10-02 21:55:22 -04009656
9657 return ret;
9658}
9659
9660/*
9661 * advansys_biosparam()
9662 *
9663 * Translate disk drive geometry if the "BIOS greater than 1 GB"
9664 * support is enabled for a drive.
9665 *
9666 * ip (information pointer) is an int array with the following definition:
9667 * ip[0]: heads
9668 * ip[1]: sectors
9669 * ip[2]: cylinders
9670 */
9671static int
9672advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
9673 sector_t capacity, int ip[])
9674{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009675 struct asc_board *boardp = shost_priv(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04009676
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009677 ASC_DBG(1, "begin\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009678 ASC_STATS(sdev->host, biosparam);
Matthew Wilcox51219352007-10-02 21:55:22 -04009679 if (ASC_NARROW_BOARD(boardp)) {
9680 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
9681 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
9682 ip[0] = 255;
9683 ip[1] = 63;
9684 } else {
9685 ip[0] = 64;
9686 ip[1] = 32;
9687 }
9688 } else {
9689 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
9690 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
9691 ip[0] = 255;
9692 ip[1] = 63;
9693 } else {
9694 ip[0] = 64;
9695 ip[1] = 32;
9696 }
9697 }
9698 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009699 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009700 return 0;
9701}
9702
9703/*
9704 * First-level interrupt handler.
9705 *
9706 * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host.
9707 */
9708static irqreturn_t advansys_interrupt(int irq, void *dev_id)
9709{
9710 unsigned long flags;
9711 struct Scsi_Host *shost = dev_id;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009712 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009713 irqreturn_t result = IRQ_NONE;
9714
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009715 ASC_DBG(2, "boardp 0x%p\n", boardp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009716 spin_lock_irqsave(&boardp->lock, flags);
9717 if (ASC_NARROW_BOARD(boardp)) {
9718 if (AscIsIntPending(shost->io_port)) {
9719 result = IRQ_HANDLED;
9720 ASC_STATS(shost, interrupt);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009721 ASC_DBG(1, "before AscISR()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009722 AscISR(&boardp->dvc_var.asc_dvc_var);
9723 }
9724 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009725 ASC_DBG(1, "before AdvISR()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009726 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
9727 result = IRQ_HANDLED;
9728 ASC_STATS(shost, interrupt);
9729 }
9730 }
9731 spin_unlock_irqrestore(&boardp->lock, flags);
9732
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009733 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009734 return result;
9735}
9736
9737static int AscHostReqRiscHalt(PortAddr iop_base)
9738{
9739 int count = 0;
9740 int sta = 0;
9741 uchar saved_stop_code;
9742
9743 if (AscIsChipHalted(iop_base))
9744 return (1);
9745 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
9746 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9747 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
9748 do {
9749 if (AscIsChipHalted(iop_base)) {
9750 sta = 1;
9751 break;
9752 }
9753 mdelay(100);
9754 } while (count++ < 20);
9755 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
9756 return (sta);
9757}
9758
9759static int
9760AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
9761{
9762 int sta = FALSE;
9763
9764 if (AscHostReqRiscHalt(iop_base)) {
9765 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9766 AscStartChip(iop_base);
9767 }
9768 return sta;
9769}
9770
9771static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
9772{
9773 char type = sdev->type;
9774 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
9775
9776 if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN))
9777 return;
9778 if (asc_dvc->init_sdtr & tid_bits)
9779 return;
9780
9781 if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0))
9782 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9783
9784 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
9785 if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) ||
9786 (type == TYPE_ROM) || (type == TYPE_TAPE))
9787 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9788
9789 if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
9790 AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id,
9791 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
9792}
9793
9794static void
9795advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
9796{
9797 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
9798 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
9799
9800 if (sdev->lun == 0) {
9801 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
9802 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
9803 asc_dvc->init_sdtr |= tid_bit;
9804 } else {
9805 asc_dvc->init_sdtr &= ~tid_bit;
9806 }
9807
9808 if (orig_init_sdtr != asc_dvc->init_sdtr)
9809 AscAsyncFix(asc_dvc, sdev);
9810 }
9811
9812 if (sdev->tagged_supported) {
9813 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
9814 if (sdev->lun == 0) {
9815 asc_dvc->cfg->can_tagged_qng |= tid_bit;
9816 asc_dvc->use_tagged_qng |= tid_bit;
9817 }
9818 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9819 asc_dvc->max_dvc_qng[sdev->id]);
9820 }
9821 } else {
9822 if (sdev->lun == 0) {
9823 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
9824 asc_dvc->use_tagged_qng &= ~tid_bit;
9825 }
9826 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9827 }
9828
9829 if ((sdev->lun == 0) &&
9830 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
9831 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
9832 asc_dvc->cfg->disc_enable);
9833 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
9834 asc_dvc->use_tagged_qng);
9835 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
9836 asc_dvc->cfg->can_tagged_qng);
9837
9838 asc_dvc->max_dvc_qng[sdev->id] =
9839 asc_dvc->cfg->max_tag_qng[sdev->id];
9840 AscWriteLramByte(asc_dvc->iop_base,
9841 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
9842 asc_dvc->max_dvc_qng[sdev->id]);
9843 }
9844}
9845
9846/*
9847 * Wide Transfers
9848 *
9849 * If the EEPROM enabled WDTR for the device and the device supports wide
9850 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
9851 * write the new value to the microcode.
9852 */
9853static void
9854advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
9855{
9856 unsigned short cfg_word;
9857 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9858 if ((cfg_word & tidmask) != 0)
9859 return;
9860
9861 cfg_word |= tidmask;
9862 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9863
9864 /*
9865 * Clear the microcode SDTR and WDTR negotiation done indicators for
9866 * the target to cause it to negotiate with the new setting set above.
9867 * WDTR when accepted causes the target to enter asynchronous mode, so
9868 * SDTR must be negotiated.
9869 */
9870 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9871 cfg_word &= ~tidmask;
9872 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9873 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
9874 cfg_word &= ~tidmask;
9875 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
9876}
9877
9878/*
9879 * Synchronous Transfers
9880 *
9881 * If the EEPROM enabled SDTR for the device and the device
9882 * supports synchronous transfers, then turn on the device's
9883 * 'sdtr_able' bit. Write the new value to the microcode.
9884 */
9885static void
9886advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
9887{
9888 unsigned short cfg_word;
9889 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
9890 if ((cfg_word & tidmask) != 0)
9891 return;
9892
9893 cfg_word |= tidmask;
9894 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
9895
9896 /*
9897 * Clear the microcode "SDTR negotiation" done indicator for the
9898 * target to cause it to negotiate with the new setting set above.
9899 */
9900 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9901 cfg_word &= ~tidmask;
9902 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9903}
9904
9905/*
9906 * PPR (Parallel Protocol Request) Capable
9907 *
9908 * If the device supports DT mode, then it must be PPR capable.
9909 * The PPR message will be used in place of the SDTR and WDTR
9910 * messages to negotiate synchronous speed and offset, transfer
9911 * width, and protocol options.
9912 */
9913static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
9914 AdvPortAddr iop_base, unsigned short tidmask)
9915{
9916 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
9917 adv_dvc->ppr_able |= tidmask;
9918 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
9919}
9920
9921static void
9922advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
9923{
9924 AdvPortAddr iop_base = adv_dvc->iop_base;
9925 unsigned short tidmask = 1 << sdev->id;
9926
9927 if (sdev->lun == 0) {
9928 /*
9929 * Handle WDTR, SDTR, and Tag Queuing. If the feature
9930 * is enabled in the EEPROM and the device supports the
9931 * feature, then enable it in the microcode.
9932 */
9933
9934 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
9935 advansys_wide_enable_wdtr(iop_base, tidmask);
9936 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
9937 advansys_wide_enable_sdtr(iop_base, tidmask);
9938 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
9939 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
9940
9941 /*
9942 * Tag Queuing is disabled for the BIOS which runs in polled
9943 * mode and would see no benefit from Tag Queuing. Also by
9944 * disabling Tag Queuing in the BIOS devices with Tag Queuing
9945 * bugs will at least work with the BIOS.
9946 */
9947 if ((adv_dvc->tagqng_able & tidmask) &&
9948 sdev->tagged_supported) {
9949 unsigned short cfg_word;
9950 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
9951 cfg_word |= tidmask;
9952 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
9953 cfg_word);
9954 AdvWriteByteLram(iop_base,
9955 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
9956 adv_dvc->max_dvc_qng);
9957 }
9958 }
9959
9960 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
9961 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9962 adv_dvc->max_dvc_qng);
9963 } else {
9964 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9965 }
9966}
9967
9968/*
9969 * Set the number of commands to queue per device for the
9970 * specified host adapter.
9971 */
9972static int advansys_slave_configure(struct scsi_device *sdev)
9973{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009974 struct asc_board *boardp = shost_priv(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04009975
Matthew Wilcox51219352007-10-02 21:55:22 -04009976 if (ASC_NARROW_BOARD(boardp))
9977 advansys_narrow_slave_configure(sdev,
9978 &boardp->dvc_var.asc_dvc_var);
9979 else
9980 advansys_wide_slave_configure(sdev,
9981 &boardp->dvc_var.adv_dvc_var);
9982
9983 return 0;
9984}
9985
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009986static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
Matthew Wilcox05848b62007-10-02 21:55:25 -04009987 struct asc_scsi_q *asc_scsi_q)
Matthew Wilcox51219352007-10-02 21:55:22 -04009988{
Matthew Wilcox05848b62007-10-02 21:55:25 -04009989 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
Matthew Wilcox51219352007-10-02 21:55:22 -04009990
9991 /*
9992 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
9993 */
Matthew Wilcox05848b62007-10-02 21:55:25 -04009994 asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009995
9996 /*
9997 * Build the ASC_SCSI_Q request.
9998 */
Matthew Wilcox05848b62007-10-02 21:55:25 -04009999 asc_scsi_q->cdbptr = &scp->cmnd[0];
10000 asc_scsi_q->q2.cdb_len = scp->cmd_len;
10001 asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
10002 asc_scsi_q->q1.target_lun = scp->device->lun;
10003 asc_scsi_q->q2.target_ix =
Matthew Wilcox51219352007-10-02 21:55:22 -040010004 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
Matthew Wilcox05848b62007-10-02 21:55:25 -040010005 asc_scsi_q->q1.sense_addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010006 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010007 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
Matthew Wilcox51219352007-10-02 21:55:22 -040010008
10009 /*
10010 * If there are any outstanding requests for the current target,
10011 * then every 255th request send an ORDERED request. This heuristic
10012 * tries to retain the benefit of request sorting while preventing
10013 * request starvation. 255 is the max number of tags or pending commands
10014 * a device may have outstanding.
10015 *
10016 * The request count is incremented below for every successfully
10017 * started request.
10018 *
10019 */
10020 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
10021 (boardp->reqcnt[scp->device->id] % 255) == 0) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010022 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010023 } else {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010024 asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010025 }
10026
10027 /*
10028 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
10029 * buffer command.
10030 */
10031 if (scp->use_sg == 0) {
10032 /*
10033 * CDB request of single contiguous buffer.
10034 */
10035 ASC_STATS(scp->device->host, cont_cnt);
10036 scp->SCp.dma_handle = scp->request_bufflen ?
10037 dma_map_single(boardp->dev, scp->request_buffer,
10038 scp->request_bufflen,
10039 scp->sc_data_direction) : 0;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010040 asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
10041 asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen);
Matthew Wilcox51219352007-10-02 21:55:22 -040010042 ASC_STATS_ADD(scp->device->host, cont_xfer,
10043 ASC_CEILING(scp->request_bufflen, 512));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010044 asc_scsi_q->q1.sg_queue_cnt = 0;
10045 asc_scsi_q->sg_head = NULL;
Matthew Wilcox51219352007-10-02 21:55:22 -040010046 } else {
10047 /*
10048 * CDB scatter-gather request list.
10049 */
10050 int sgcnt;
10051 int use_sg;
10052 struct scatterlist *slp;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010053 struct asc_sg_head *asc_sg_head;
Matthew Wilcox51219352007-10-02 21:55:22 -040010054
10055 slp = (struct scatterlist *)scp->request_buffer;
10056 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10057 scp->sc_data_direction);
10058
10059 if (use_sg > scp->device->host->sg_tablesize) {
10060 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
10061 "sg_tablesize %d\n", boardp->id, use_sg,
10062 scp->device->host->sg_tablesize);
10063 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10064 scp->sc_data_direction);
10065 scp->result = HOST_BYTE(DID_ERROR);
10066 return ASC_ERROR;
10067 }
10068
10069 ASC_STATS(scp->device->host, sg_cnt);
10070
Matthew Wilcox05848b62007-10-02 21:55:25 -040010071 asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
10072 use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
10073 if (!asc_sg_head) {
10074 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10075 scp->sc_data_direction);
10076 scp->result = HOST_BYTE(DID_SOFT_ERROR);
10077 return ASC_ERROR;
10078 }
Matthew Wilcox51219352007-10-02 21:55:22 -040010079
Matthew Wilcox05848b62007-10-02 21:55:25 -040010080 asc_scsi_q->q1.cntl |= QC_SG_HEAD;
10081 asc_scsi_q->sg_head = asc_sg_head;
10082 asc_scsi_q->q1.data_cnt = 0;
10083 asc_scsi_q->q1.data_addr = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040010084 /* This is a byte value, otherwise it would need to be swapped. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010085 asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
Matthew Wilcox51219352007-10-02 21:55:22 -040010086 ASC_STATS_ADD(scp->device->host, sg_elem,
Matthew Wilcox05848b62007-10-02 21:55:25 -040010087 asc_sg_head->entry_cnt);
Matthew Wilcox51219352007-10-02 21:55:22 -040010088
10089 /*
10090 * Convert scatter-gather list into ASC_SG_HEAD list.
10091 */
10092 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010093 asc_sg_head->sg_list[sgcnt].addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010094 cpu_to_le32(sg_dma_address(slp));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010095 asc_sg_head->sg_list[sgcnt].bytes =
Matthew Wilcox51219352007-10-02 21:55:22 -040010096 cpu_to_le32(sg_dma_len(slp));
10097 ASC_STATS_ADD(scp->device->host, sg_xfer,
10098 ASC_CEILING(sg_dma_len(slp), 512));
10099 }
10100 }
10101
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010102 ASC_DBG_PRT_ASC_SCSI_Q(2, asc_scsi_q);
Matthew Wilcox51219352007-10-02 21:55:22 -040010103 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10104
10105 return ASC_NOERROR;
10106}
10107
10108/*
10109 * Build scatter-gather list for Adv Library (Wide Board).
10110 *
10111 * Additional ADV_SG_BLOCK structures will need to be allocated
10112 * if the total number of scatter-gather elements exceeds
10113 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
10114 * assumed to be physically contiguous.
10115 *
10116 * Return:
10117 * ADV_SUCCESS(1) - SG List successfully created
10118 * ADV_ERROR(-1) - SG List creation failed
10119 */
10120static int
Matthew Wilcoxd2411492007-10-02 21:55:31 -040010121adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
Matthew Wilcox51219352007-10-02 21:55:22 -040010122 int use_sg)
10123{
10124 adv_sgblk_t *sgblkp;
10125 ADV_SCSI_REQ_Q *scsiqp;
10126 struct scatterlist *slp;
10127 int sg_elem_cnt;
10128 ADV_SG_BLOCK *sg_block, *prev_sg_block;
10129 ADV_PADDR sg_block_paddr;
10130 int i;
10131
10132 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10133 slp = (struct scatterlist *)scp->request_buffer;
10134 sg_elem_cnt = use_sg;
10135 prev_sg_block = NULL;
10136 reqp->sgblkp = NULL;
10137
10138 for (;;) {
10139 /*
10140 * Allocate a 'adv_sgblk_t' structure from the board free
10141 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
10142 * (15) scatter-gather elements.
10143 */
10144 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010145 ASC_DBG(1, "no free adv_sgblk_t\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040010146 ASC_STATS(scp->device->host, adv_build_nosg);
10147
10148 /*
10149 * Allocation failed. Free 'adv_sgblk_t' structures
10150 * already allocated for the request.
10151 */
10152 while ((sgblkp = reqp->sgblkp) != NULL) {
10153 /* Remove 'sgblkp' from the request list. */
10154 reqp->sgblkp = sgblkp->next_sgblkp;
10155
10156 /* Add 'sgblkp' to the board free list. */
10157 sgblkp->next_sgblkp = boardp->adv_sgblkp;
10158 boardp->adv_sgblkp = sgblkp;
10159 }
10160 return ASC_BUSY;
10161 }
10162
10163 /* Complete 'adv_sgblk_t' board allocation. */
10164 boardp->adv_sgblkp = sgblkp->next_sgblkp;
10165 sgblkp->next_sgblkp = NULL;
10166
10167 /*
10168 * Get 8 byte aligned virtual and physical addresses
10169 * for the allocated ADV_SG_BLOCK structure.
10170 */
10171 sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
10172 sg_block_paddr = virt_to_bus(sg_block);
10173
10174 /*
10175 * Check if this is the first 'adv_sgblk_t' for the
10176 * request.
10177 */
10178 if (reqp->sgblkp == NULL) {
10179 /* Request's first scatter-gather block. */
10180 reqp->sgblkp = sgblkp;
10181
10182 /*
10183 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
10184 * address pointers.
10185 */
10186 scsiqp->sg_list_ptr = sg_block;
10187 scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
10188 } else {
10189 /* Request's second or later scatter-gather block. */
10190 sgblkp->next_sgblkp = reqp->sgblkp;
10191 reqp->sgblkp = sgblkp;
10192
10193 /*
10194 * Point the previous ADV_SG_BLOCK structure to
10195 * the newly allocated ADV_SG_BLOCK structure.
10196 */
10197 prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
10198 }
10199
10200 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
10201 sg_block->sg_list[i].sg_addr =
10202 cpu_to_le32(sg_dma_address(slp));
10203 sg_block->sg_list[i].sg_count =
10204 cpu_to_le32(sg_dma_len(slp));
10205 ASC_STATS_ADD(scp->device->host, sg_xfer,
10206 ASC_CEILING(sg_dma_len(slp), 512));
10207
10208 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
10209 sg_block->sg_cnt = i + 1;
10210 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
10211 return ADV_SUCCESS;
10212 }
10213 slp++;
10214 }
10215 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
10216 prev_sg_block = sg_block;
10217 }
10218}
10219
10220/*
10221 * Build a request structure for the Adv Library (Wide Board).
10222 *
10223 * If an adv_req_t can not be allocated to issue the request,
10224 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
10225 *
10226 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
10227 * microcode for DMA addresses or math operations are byte swapped
10228 * to little-endian order.
10229 */
10230static int
Matthew Wilcoxd2411492007-10-02 21:55:31 -040010231adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
Matthew Wilcox51219352007-10-02 21:55:22 -040010232 ADV_SCSI_REQ_Q **adv_scsiqpp)
10233{
10234 adv_req_t *reqp;
10235 ADV_SCSI_REQ_Q *scsiqp;
10236 int i;
10237 int ret;
10238
10239 /*
10240 * Allocate an adv_req_t structure from the board to execute
10241 * the command.
10242 */
10243 if (boardp->adv_reqp == NULL) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010244 ASC_DBG(1, "no free adv_req_t\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040010245 ASC_STATS(scp->device->host, adv_build_noreq);
10246 return ASC_BUSY;
10247 } else {
10248 reqp = boardp->adv_reqp;
10249 boardp->adv_reqp = reqp->next_reqp;
10250 reqp->next_reqp = NULL;
10251 }
10252
10253 /*
10254 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
10255 */
10256 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10257
10258 /*
10259 * Initialize the structure.
10260 */
10261 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
10262
10263 /*
10264 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
10265 */
10266 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
10267
10268 /*
10269 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
10270 */
10271 reqp->cmndp = scp;
10272
10273 /*
10274 * Build the ADV_SCSI_REQ_Q request.
10275 */
10276
10277 /* Set CDB length and copy it to the request structure. */
10278 scsiqp->cdb_len = scp->cmd_len;
10279 /* Copy first 12 CDB bytes to cdb[]. */
10280 for (i = 0; i < scp->cmd_len && i < 12; i++) {
10281 scsiqp->cdb[i] = scp->cmnd[i];
10282 }
10283 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
10284 for (; i < scp->cmd_len; i++) {
10285 scsiqp->cdb16[i - 12] = scp->cmnd[i];
10286 }
10287
10288 scsiqp->target_id = scp->device->id;
10289 scsiqp->target_lun = scp->device->lun;
10290
10291 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
10292 scsiqp->sense_len = sizeof(scp->sense_buffer);
10293
10294 /*
10295 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
10296 * buffer command.
10297 */
10298
10299 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10300 scsiqp->vdata_addr = scp->request_buffer;
10301 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
10302
10303 if (scp->use_sg == 0) {
10304 /*
10305 * CDB request of single contiguous buffer.
10306 */
10307 reqp->sgblkp = NULL;
10308 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10309 if (scp->request_bufflen) {
10310 scsiqp->vdata_addr = scp->request_buffer;
10311 scp->SCp.dma_handle =
10312 dma_map_single(boardp->dev, scp->request_buffer,
10313 scp->request_bufflen,
10314 scp->sc_data_direction);
10315 } else {
10316 scsiqp->vdata_addr = NULL;
10317 scp->SCp.dma_handle = 0;
10318 }
10319 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
10320 scsiqp->sg_list_ptr = NULL;
10321 scsiqp->sg_real_addr = 0;
10322 ASC_STATS(scp->device->host, cont_cnt);
10323 ASC_STATS_ADD(scp->device->host, cont_xfer,
10324 ASC_CEILING(scp->request_bufflen, 512));
10325 } else {
10326 /*
10327 * CDB scatter-gather request list.
10328 */
10329 struct scatterlist *slp;
10330 int use_sg;
10331
10332 slp = (struct scatterlist *)scp->request_buffer;
10333 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10334 scp->sc_data_direction);
10335
10336 if (use_sg > ADV_MAX_SG_LIST) {
10337 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
10338 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
10339 scp->device->host->sg_tablesize);
10340 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10341 scp->sc_data_direction);
10342 scp->result = HOST_BYTE(DID_ERROR);
10343
10344 /*
10345 * Free the 'adv_req_t' structure by adding it back
10346 * to the board free list.
10347 */
10348 reqp->next_reqp = boardp->adv_reqp;
10349 boardp->adv_reqp = reqp;
10350
10351 return ASC_ERROR;
10352 }
10353
10354 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
10355 if (ret != ADV_SUCCESS) {
10356 /*
10357 * Free the adv_req_t structure by adding it back to
10358 * the board free list.
10359 */
10360 reqp->next_reqp = boardp->adv_reqp;
10361 boardp->adv_reqp = reqp;
10362
10363 return ret;
10364 }
10365
10366 ASC_STATS(scp->device->host, sg_cnt);
10367 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
10368 }
10369
10370 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
10371 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10372
10373 *adv_scsiqpp = scsiqp;
10374
10375 return ASC_NOERROR;
10376}
10377
10378static int AscSgListToQueue(int sg_list)
10379{
10380 int n_sg_list_qs;
10381
10382 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
10383 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
10384 n_sg_list_qs++;
10385 return n_sg_list_qs + 1;
10386}
10387
10388static uint
10389AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
10390{
10391 uint cur_used_qs;
10392 uint cur_free_qs;
10393 ASC_SCSI_BIT_ID_TYPE target_id;
10394 uchar tid_no;
10395
10396 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
10397 tid_no = ASC_TIX_TO_TID(target_ix);
10398 if ((asc_dvc->unit_not_ready & target_id) ||
10399 (asc_dvc->queue_full_or_busy & target_id)) {
10400 return 0;
10401 }
10402 if (n_qs == 1) {
10403 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10404 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
10405 } else {
10406 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10407 (uint) ASC_MIN_FREE_Q;
10408 }
10409 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
10410 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
10411 if (asc_dvc->cur_dvc_qng[tid_no] >=
10412 asc_dvc->max_dvc_qng[tid_no]) {
10413 return 0;
10414 }
10415 return cur_free_qs;
10416 }
10417 if (n_qs > 1) {
10418 if ((n_qs > asc_dvc->last_q_shortage)
10419 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
10420 asc_dvc->last_q_shortage = n_qs;
10421 }
10422 }
10423 return 0;
10424}
10425
10426static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
10427{
10428 ushort q_addr;
10429 uchar next_qp;
10430 uchar q_status;
10431
10432 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10433 q_status = (uchar)AscReadLramByte(iop_base,
10434 (ushort)(q_addr +
10435 ASC_SCSIQ_B_STATUS));
10436 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10437 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END))
10438 return next_qp;
10439 return ASC_QLINK_END;
10440}
10441
10442static uchar
10443AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
10444{
10445 uchar i;
10446
10447 for (i = 0; i < n_free_q; i++) {
10448 free_q_head = AscAllocFreeQueue(iop_base, free_q_head);
10449 if (free_q_head == ASC_QLINK_END)
10450 break;
10451 }
10452 return free_q_head;
10453}
10454
10455/*
10456 * void
10457 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10458 *
10459 * Calling/Exit State:
10460 * none
10461 *
10462 * Description:
10463 * Output an ASC_SCSI_Q structure to the chip
10464 */
10465static void
10466DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10467{
10468 int i;
10469
10470 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
10471 AscSetChipLramAddr(iop_base, s_addr);
10472 for (i = 0; i < 2 * words; i += 2) {
10473 if (i == 4 || i == 20) {
10474 continue;
10475 }
10476 outpw(iop_base + IOP_RAM_DATA,
10477 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
10478 }
10479}
10480
10481static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10482{
10483 ushort q_addr;
10484 uchar tid_no;
10485 uchar sdtr_data;
10486 uchar syn_period_ix;
10487 uchar syn_offset;
10488 PortAddr iop_base;
10489
10490 iop_base = asc_dvc->iop_base;
10491 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
10492 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
10493 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
10494 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10495 syn_period_ix =
10496 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
10497 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
10498 AscMsgOutSDTR(asc_dvc,
10499 asc_dvc->sdtr_period_tbl[syn_period_ix],
10500 syn_offset);
10501 scsiq->q1.cntl |= QC_MSG_OUT;
10502 }
10503 q_addr = ASC_QNO_TO_QADDR(q_no);
10504 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
10505 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10506 }
10507 scsiq->q1.status = QS_FREE;
10508 AscMemWordCopyPtrToLram(iop_base,
10509 q_addr + ASC_SCSIQ_CDB_BEG,
10510 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
10511
10512 DvcPutScsiQ(iop_base,
10513 q_addr + ASC_SCSIQ_CPY_BEG,
10514 (uchar *)&scsiq->q1.cntl,
10515 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
10516 AscWriteLramWord(iop_base,
10517 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
10518 (ushort)(((ushort)scsiq->q1.
10519 q_no << 8) | (ushort)QS_READY));
10520 return 1;
10521}
10522
10523static int
10524AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10525{
10526 int sta;
10527 int i;
10528 ASC_SG_HEAD *sg_head;
10529 ASC_SG_LIST_Q scsi_sg_q;
10530 ASC_DCNT saved_data_addr;
10531 ASC_DCNT saved_data_cnt;
10532 PortAddr iop_base;
10533 ushort sg_list_dwords;
10534 ushort sg_index;
10535 ushort sg_entry_cnt;
10536 ushort q_addr;
10537 uchar next_qp;
10538
10539 iop_base = asc_dvc->iop_base;
10540 sg_head = scsiq->sg_head;
10541 saved_data_addr = scsiq->q1.data_addr;
10542 saved_data_cnt = scsiq->q1.data_cnt;
10543 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
10544 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
10545#if CC_VERY_LONG_SG_LIST
10546 /*
10547 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
10548 * then not all SG elements will fit in the allocated queues.
10549 * The rest of the SG elements will be copied when the RISC
10550 * completes the SG elements that fit and halts.
10551 */
10552 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10553 /*
10554 * Set sg_entry_cnt to be the number of SG elements that
10555 * will fit in the allocated SG queues. It is minus 1, because
10556 * the first SG element is handled above. ASC_MAX_SG_LIST is
10557 * already inflated by 1 to account for this. For example it
10558 * may be 50 which is 1 + 7 queues * 7 SG elements.
10559 */
10560 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
10561
10562 /*
10563 * Keep track of remaining number of SG elements that will
10564 * need to be handled from a_isr.c.
10565 */
10566 scsiq->remain_sg_entry_cnt =
10567 sg_head->entry_cnt - ASC_MAX_SG_LIST;
10568 } else {
10569#endif /* CC_VERY_LONG_SG_LIST */
10570 /*
10571 * Set sg_entry_cnt to be the number of SG elements that
10572 * will fit in the allocated SG queues. It is minus 1, because
10573 * the first SG element is handled above.
10574 */
10575 sg_entry_cnt = sg_head->entry_cnt - 1;
10576#if CC_VERY_LONG_SG_LIST
10577 }
10578#endif /* CC_VERY_LONG_SG_LIST */
10579 if (sg_entry_cnt != 0) {
10580 scsiq->q1.cntl |= QC_SG_HEAD;
10581 q_addr = ASC_QNO_TO_QADDR(q_no);
10582 sg_index = 1;
10583 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
10584 scsi_sg_q.sg_head_qp = q_no;
10585 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
10586 for (i = 0; i < sg_head->queue_cnt; i++) {
10587 scsi_sg_q.seq_no = i + 1;
10588 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
10589 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
10590 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
10591 if (i == 0) {
10592 scsi_sg_q.sg_list_cnt =
10593 ASC_SG_LIST_PER_Q;
10594 scsi_sg_q.sg_cur_list_cnt =
10595 ASC_SG_LIST_PER_Q;
10596 } else {
10597 scsi_sg_q.sg_list_cnt =
10598 ASC_SG_LIST_PER_Q - 1;
10599 scsi_sg_q.sg_cur_list_cnt =
10600 ASC_SG_LIST_PER_Q - 1;
10601 }
10602 } else {
10603#if CC_VERY_LONG_SG_LIST
10604 /*
10605 * This is the last SG queue in the list of
10606 * allocated SG queues. If there are more
10607 * SG elements than will fit in the allocated
10608 * queues, then set the QCSG_SG_XFER_MORE flag.
10609 */
10610 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10611 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
10612 } else {
10613#endif /* CC_VERY_LONG_SG_LIST */
10614 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
10615#if CC_VERY_LONG_SG_LIST
10616 }
10617#endif /* CC_VERY_LONG_SG_LIST */
10618 sg_list_dwords = sg_entry_cnt << 1;
10619 if (i == 0) {
10620 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
10621 scsi_sg_q.sg_cur_list_cnt =
10622 sg_entry_cnt;
10623 } else {
10624 scsi_sg_q.sg_list_cnt =
10625 sg_entry_cnt - 1;
10626 scsi_sg_q.sg_cur_list_cnt =
10627 sg_entry_cnt - 1;
10628 }
10629 sg_entry_cnt = 0;
10630 }
10631 next_qp = AscReadLramByte(iop_base,
10632 (ushort)(q_addr +
10633 ASC_SCSIQ_B_FWD));
10634 scsi_sg_q.q_no = next_qp;
10635 q_addr = ASC_QNO_TO_QADDR(next_qp);
10636 AscMemWordCopyPtrToLram(iop_base,
10637 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
10638 (uchar *)&scsi_sg_q,
10639 sizeof(ASC_SG_LIST_Q) >> 1);
10640 AscMemDWordCopyPtrToLram(iop_base,
10641 q_addr + ASC_SGQ_LIST_BEG,
10642 (uchar *)&sg_head->
10643 sg_list[sg_index],
10644 sg_list_dwords);
10645 sg_index += ASC_SG_LIST_PER_Q;
10646 scsiq->next_sg_index = sg_index;
10647 }
10648 } else {
10649 scsiq->q1.cntl &= ~QC_SG_HEAD;
10650 }
10651 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
10652 scsiq->q1.data_addr = saved_data_addr;
10653 scsiq->q1.data_cnt = saved_data_cnt;
10654 return (sta);
10655}
10656
10657static int
10658AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
10659{
10660 PortAddr iop_base;
10661 uchar free_q_head;
10662 uchar next_qp;
10663 uchar tid_no;
10664 uchar target_ix;
10665 int sta;
10666
10667 iop_base = asc_dvc->iop_base;
10668 target_ix = scsiq->q2.target_ix;
10669 tid_no = ASC_TIX_TO_TID(target_ix);
10670 sta = 0;
10671 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
10672 if (n_q_required > 1) {
10673 next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head,
10674 (uchar)n_q_required);
10675 if (next_qp != ASC_QLINK_END) {
10676 asc_dvc->last_q_shortage = 0;
10677 scsiq->sg_head->queue_cnt = n_q_required - 1;
10678 scsiq->q1.q_no = free_q_head;
10679 sta = AscPutReadySgListQueue(asc_dvc, scsiq,
10680 free_q_head);
10681 }
10682 } else if (n_q_required == 1) {
10683 next_qp = AscAllocFreeQueue(iop_base, free_q_head);
10684 if (next_qp != ASC_QLINK_END) {
10685 scsiq->q1.q_no = free_q_head;
10686 sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head);
10687 }
10688 }
10689 if (sta == 1) {
10690 AscPutVarFreeQHead(iop_base, next_qp);
10691 asc_dvc->cur_total_qng += n_q_required;
10692 asc_dvc->cur_dvc_qng[tid_no]++;
10693 }
10694 return sta;
10695}
10696
10697#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
10698static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
10699 INQUIRY,
10700 REQUEST_SENSE,
10701 READ_CAPACITY,
10702 READ_TOC,
10703 MODE_SELECT,
10704 MODE_SENSE,
10705 MODE_SELECT_10,
10706 MODE_SENSE_10,
10707 0xFF,
10708 0xFF,
10709 0xFF,
10710 0xFF,
10711 0xFF,
10712 0xFF,
10713 0xFF,
10714 0xFF
10715};
10716
10717static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
10718{
10719 PortAddr iop_base;
10720 int sta;
10721 int n_q_required;
10722 int disable_syn_offset_one_fix;
10723 int i;
10724 ASC_PADDR addr;
10725 ushort sg_entry_cnt = 0;
10726 ushort sg_entry_cnt_minus_one = 0;
10727 uchar target_ix;
10728 uchar tid_no;
10729 uchar sdtr_data;
10730 uchar extra_bytes;
10731 uchar scsi_cmd;
10732 uchar disable_cmd;
10733 ASC_SG_HEAD *sg_head;
10734 ASC_DCNT data_cnt;
10735
10736 iop_base = asc_dvc->iop_base;
10737 sg_head = scsiq->sg_head;
10738 if (asc_dvc->err_code != 0)
10739 return (ERR);
10740 scsiq->q1.q_no = 0;
10741 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
10742 scsiq->q1.extra_bytes = 0;
10743 }
10744 sta = 0;
10745 target_ix = scsiq->q2.target_ix;
10746 tid_no = ASC_TIX_TO_TID(target_ix);
10747 n_q_required = 1;
10748 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
10749 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
10750 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
10751 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10752 AscMsgOutSDTR(asc_dvc,
10753 asc_dvc->
10754 sdtr_period_tbl[(sdtr_data >> 4) &
10755 (uchar)(asc_dvc->
10756 max_sdtr_index -
10757 1)],
10758 (uchar)(sdtr_data & (uchar)
10759 ASC_SYN_MAX_OFFSET));
10760 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
10761 }
10762 }
10763 if (asc_dvc->in_critical_cnt != 0) {
10764 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
10765 return (ERR);
10766 }
10767 asc_dvc->in_critical_cnt++;
10768 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10769 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
10770 asc_dvc->in_critical_cnt--;
10771 return (ERR);
10772 }
10773#if !CC_VERY_LONG_SG_LIST
10774 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10775 asc_dvc->in_critical_cnt--;
10776 return (ERR);
10777 }
10778#endif /* !CC_VERY_LONG_SG_LIST */
10779 if (sg_entry_cnt == 1) {
10780 scsiq->q1.data_addr =
10781 (ADV_PADDR)sg_head->sg_list[0].addr;
10782 scsiq->q1.data_cnt =
10783 (ADV_DCNT)sg_head->sg_list[0].bytes;
10784 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
10785 }
10786 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
10787 }
10788 scsi_cmd = scsiq->cdbptr[0];
10789 disable_syn_offset_one_fix = FALSE;
10790 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
10791 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
10792 if (scsiq->q1.cntl & QC_SG_HEAD) {
10793 data_cnt = 0;
10794 for (i = 0; i < sg_entry_cnt; i++) {
10795 data_cnt +=
10796 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
10797 bytes);
10798 }
10799 } else {
10800 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
10801 }
10802 if (data_cnt != 0UL) {
10803 if (data_cnt < 512UL) {
10804 disable_syn_offset_one_fix = TRUE;
10805 } else {
10806 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
10807 i++) {
10808 disable_cmd =
10809 _syn_offset_one_disable_cmd[i];
10810 if (disable_cmd == 0xFF) {
10811 break;
10812 }
10813 if (scsi_cmd == disable_cmd) {
10814 disable_syn_offset_one_fix =
10815 TRUE;
10816 break;
10817 }
10818 }
10819 }
10820 }
10821 }
10822 if (disable_syn_offset_one_fix) {
10823 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10824 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
10825 ASC_TAG_FLAG_DISABLE_DISCONNECT);
10826 } else {
10827 scsiq->q2.tag_code &= 0x27;
10828 }
10829 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10830 if (asc_dvc->bug_fix_cntl) {
10831 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10832 if ((scsi_cmd == READ_6) ||
10833 (scsi_cmd == READ_10)) {
10834 addr =
10835 (ADV_PADDR)le32_to_cpu(sg_head->
10836 sg_list
10837 [sg_entry_cnt_minus_one].
10838 addr) +
10839 (ADV_DCNT)le32_to_cpu(sg_head->
10840 sg_list
10841 [sg_entry_cnt_minus_one].
10842 bytes);
10843 extra_bytes =
10844 (uchar)((ushort)addr & 0x0003);
10845 if ((extra_bytes != 0)
10846 &&
10847 ((scsiq->q2.
10848 tag_code &
10849 ASC_TAG_FLAG_EXTRA_BYTES)
10850 == 0)) {
10851 scsiq->q2.tag_code |=
10852 ASC_TAG_FLAG_EXTRA_BYTES;
10853 scsiq->q1.extra_bytes =
10854 extra_bytes;
10855 data_cnt =
10856 le32_to_cpu(sg_head->
10857 sg_list
10858 [sg_entry_cnt_minus_one].
10859 bytes);
10860 data_cnt -=
10861 (ASC_DCNT) extra_bytes;
10862 sg_head->
10863 sg_list
10864 [sg_entry_cnt_minus_one].
10865 bytes =
10866 cpu_to_le32(data_cnt);
10867 }
10868 }
10869 }
10870 }
10871 sg_head->entry_to_copy = sg_head->entry_cnt;
10872#if CC_VERY_LONG_SG_LIST
10873 /*
10874 * Set the sg_entry_cnt to the maximum possible. The rest of
10875 * the SG elements will be copied when the RISC completes the
10876 * SG elements that fit and halts.
10877 */
10878 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10879 sg_entry_cnt = ASC_MAX_SG_LIST;
10880 }
10881#endif /* CC_VERY_LONG_SG_LIST */
10882 n_q_required = AscSgListToQueue(sg_entry_cnt);
10883 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
10884 (uint) n_q_required)
10885 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
10886 if ((sta =
10887 AscSendScsiQueue(asc_dvc, scsiq,
10888 n_q_required)) == 1) {
10889 asc_dvc->in_critical_cnt--;
10890 return (sta);
10891 }
10892 }
10893 } else {
10894 if (asc_dvc->bug_fix_cntl) {
10895 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10896 if ((scsi_cmd == READ_6) ||
10897 (scsi_cmd == READ_10)) {
10898 addr =
10899 le32_to_cpu(scsiq->q1.data_addr) +
10900 le32_to_cpu(scsiq->q1.data_cnt);
10901 extra_bytes =
10902 (uchar)((ushort)addr & 0x0003);
10903 if ((extra_bytes != 0)
10904 &&
10905 ((scsiq->q2.
10906 tag_code &
10907 ASC_TAG_FLAG_EXTRA_BYTES)
10908 == 0)) {
10909 data_cnt =
10910 le32_to_cpu(scsiq->q1.
10911 data_cnt);
10912 if (((ushort)data_cnt & 0x01FF)
10913 == 0) {
10914 scsiq->q2.tag_code |=
10915 ASC_TAG_FLAG_EXTRA_BYTES;
10916 data_cnt -= (ASC_DCNT)
10917 extra_bytes;
10918 scsiq->q1.data_cnt =
10919 cpu_to_le32
10920 (data_cnt);
10921 scsiq->q1.extra_bytes =
10922 extra_bytes;
10923 }
10924 }
10925 }
10926 }
10927 }
10928 n_q_required = 1;
10929 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
10930 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
10931 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
10932 n_q_required)) == 1) {
10933 asc_dvc->in_critical_cnt--;
10934 return (sta);
10935 }
10936 }
10937 }
10938 asc_dvc->in_critical_cnt--;
10939 return (sta);
10940}
10941
10942/*
10943 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
10944 *
10945 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
10946 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
10947 * RISC to notify it a new command is ready to be executed.
10948 *
10949 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
10950 * set to SCSI_MAX_RETRY.
10951 *
10952 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
10953 * for DMA addresses or math operations are byte swapped to little-endian
10954 * order.
10955 *
10956 * Return:
10957 * ADV_SUCCESS(1) - The request was successfully queued.
10958 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
10959 * request completes.
10960 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
10961 * host IC error.
10962 */
10963static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
10964{
10965 AdvPortAddr iop_base;
10966 ADV_DCNT req_size;
10967 ADV_PADDR req_paddr;
10968 ADV_CARR_T *new_carrp;
10969
10970 /*
10971 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
10972 */
10973 if (scsiq->target_id > ADV_MAX_TID) {
10974 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
10975 scsiq->done_status = QD_WITH_ERROR;
10976 return ADV_ERROR;
10977 }
10978
10979 iop_base = asc_dvc->iop_base;
10980
10981 /*
10982 * Allocate a carrier ensuring at least one carrier always
10983 * remains on the freelist and initialize fields.
10984 */
10985 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
10986 return ADV_BUSY;
10987 }
10988 asc_dvc->carr_freelist = (ADV_CARR_T *)
10989 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
10990 asc_dvc->carr_pending_cnt++;
10991
10992 /*
10993 * Set the carrier to be a stopper by setting 'next_vpa'
10994 * to the stopper value. The current stopper will be changed
10995 * below to point to the new stopper.
10996 */
10997 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
10998
10999 /*
11000 * Clear the ADV_SCSI_REQ_Q done flag.
11001 */
11002 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
11003
11004 req_size = sizeof(ADV_SCSI_REQ_Q);
11005 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
11006 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
11007
11008 BUG_ON(req_paddr & 31);
11009 BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q));
11010
11011 /* Wait for assertion before making little-endian */
11012 req_paddr = cpu_to_le32(req_paddr);
11013
11014 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
11015 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
11016 scsiq->scsiq_rptr = req_paddr;
11017
11018 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
11019 /*
11020 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
11021 * order during initialization.
11022 */
11023 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
11024
11025 /*
11026 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
11027 * the microcode. The newly allocated stopper will become the new
11028 * stopper.
11029 */
11030 asc_dvc->icq_sp->areq_vpa = req_paddr;
11031
11032 /*
11033 * Set the 'next_vpa' pointer for the old stopper to be the
11034 * physical address of the new stopper. The RISC can only
11035 * follow physical addresses.
11036 */
11037 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
11038
11039 /*
11040 * Set the host adapter stopper pointer to point to the new carrier.
11041 */
11042 asc_dvc->icq_sp = new_carrp;
11043
11044 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
11045 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
11046 /*
11047 * Tickle the RISC to tell it to read its Command Queue Head pointer.
11048 */
11049 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
11050 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
11051 /*
11052 * Clear the tickle value. In the ASC-3550 the RISC flag
11053 * command 'clr_tickle_a' does not work unless the host
11054 * value is cleared.
11055 */
11056 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
11057 ADV_TICKLE_NOP);
11058 }
11059 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
11060 /*
11061 * Notify the RISC a carrier is ready by writing the physical
11062 * address of the new carrier stopper to the COMMA register.
11063 */
11064 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
11065 le32_to_cpu(new_carrp->carr_pa));
11066 }
11067
11068 return ADV_SUCCESS;
11069}
11070
11071/*
11072 * Execute a single 'Scsi_Cmnd'.
11073 *
11074 * The function 'done' is called when the request has been completed.
11075 *
11076 * Scsi_Cmnd:
11077 *
11078 * host - board controlling device
11079 * device - device to send command
11080 * target - target of device
11081 * lun - lun of device
11082 * cmd_len - length of SCSI CDB
11083 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
11084 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
11085 *
11086 * if (use_sg == 0) {
11087 * request_buffer - buffer address for request
11088 * request_bufflen - length of request buffer
11089 * } else {
11090 * request_buffer - pointer to scatterlist structure
11091 * }
11092 *
11093 * sense_buffer - sense command buffer
11094 *
11095 * result (4 bytes of an int):
11096 * Byte Meaning
11097 * 0 SCSI Status Byte Code
11098 * 1 SCSI One Byte Message Code
11099 * 2 Host Error Code
11100 * 3 Mid-Level Error Code
11101 *
11102 * host driver fields:
11103 * SCp - Scsi_Pointer used for command processing status
11104 * scsi_done - used to save caller's done function
11105 * host_scribble - used for pointer to another struct scsi_cmnd
11106 *
11107 * If this function returns ASC_NOERROR the request will be completed
11108 * from the interrupt handler.
11109 *
11110 * If this function returns ASC_ERROR the host error code has been set,
11111 * and the called must call asc_scsi_done.
11112 *
11113 * If ASC_BUSY is returned the request will be returned to the midlayer
11114 * and re-tried later.
11115 */
11116static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
11117{
Matthew Wilcox41d24932007-10-02 21:55:24 -040011118 int ret, err_code;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011119 struct asc_board *boardp = shost_priv(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040011120
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011121 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011122
11123 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011124 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox05848b62007-10-02 21:55:25 -040011125 struct asc_scsi_q asc_scsi_q;
Matthew Wilcox51219352007-10-02 21:55:22 -040011126
Matthew Wilcox41d24932007-10-02 21:55:24 -040011127 /* asc_build_req() can not return ASC_BUSY. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040011128 ret = asc_build_req(boardp, scp, &asc_scsi_q);
11129 if (ret == ASC_ERROR) {
Matthew Wilcox51219352007-10-02 21:55:22 -040011130 ASC_STATS(scp->device->host, build_error);
11131 return ASC_ERROR;
11132 }
11133
Matthew Wilcox41d24932007-10-02 21:55:24 -040011134 ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
Matthew Wilcox05848b62007-10-02 21:55:25 -040011135 kfree(asc_scsi_q.sg_head);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011136 err_code = asc_dvc->err_code;
Matthew Wilcox51219352007-10-02 21:55:22 -040011137 } else {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011138 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
11139 ADV_SCSI_REQ_Q *adv_scsiqp;
Matthew Wilcox51219352007-10-02 21:55:22 -040011140
Matthew Wilcox51219352007-10-02 21:55:22 -040011141 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
11142 case ASC_NOERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011143 ASC_DBG(3, "adv_build_req ASC_NOERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011144 break;
11145 case ASC_BUSY:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011146 ASC_DBG(1, "adv_build_req ASC_BUSY\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011147 /*
11148 * The asc_stats fields 'adv_build_noreq' and
11149 * 'adv_build_nosg' count wide board busy conditions.
11150 * They are updated in adv_build_req and
11151 * adv_get_sglist, respectively.
11152 */
11153 return ASC_BUSY;
11154 case ASC_ERROR:
11155 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011156 ASC_DBG(1, "adv_build_req ASC_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011157 ASC_STATS(scp->device->host, build_error);
11158 return ASC_ERROR;
11159 }
11160
Matthew Wilcox41d24932007-10-02 21:55:24 -040011161 ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp);
11162 err_code = adv_dvc->err_code;
11163 }
11164
11165 switch (ret) {
11166 case ASC_NOERROR:
11167 ASC_STATS(scp->device->host, exe_noerror);
11168 /*
11169 * Increment monotonically increasing per device
11170 * successful request counter. Wrapping doesn't matter.
11171 */
11172 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011173 ASC_DBG(1, "ExeScsiQueue() ASC_NOERROR\n");
Matthew Wilcox41d24932007-10-02 21:55:24 -040011174 break;
11175 case ASC_BUSY:
11176 ASC_STATS(scp->device->host, exe_busy);
11177 break;
11178 case ASC_ERROR:
11179 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11180 "ASC_ERROR, err_code 0x%x\n", boardp->id, err_code);
11181 ASC_STATS(scp->device->host, exe_error);
11182 scp->result = HOST_BYTE(DID_ERROR);
11183 break;
11184 default:
11185 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11186 "unknown, err_code 0x%x\n", boardp->id, err_code);
11187 ASC_STATS(scp->device->host, exe_unknown);
11188 scp->result = HOST_BYTE(DID_ERROR);
11189 break;
Matthew Wilcox51219352007-10-02 21:55:22 -040011190 }
11191
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011192 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011193 return ret;
11194}
11195
11196/*
11197 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
11198 *
11199 * This function always returns 0. Command return status is saved
11200 * in the 'scp' result field.
11201 */
11202static int
11203advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
11204{
11205 struct Scsi_Host *shost = scp->device->host;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011206 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -040011207 unsigned long flags;
11208 int asc_res, result = 0;
11209
11210 ASC_STATS(shost, queuecommand);
11211 scp->scsi_done = done;
11212
11213 /*
11214 * host_lock taken by mid-level prior to call, but need
11215 * to protect against own ISR
11216 */
11217 spin_lock_irqsave(&boardp->lock, flags);
11218 asc_res = asc_execute_scsi_cmnd(scp);
11219 spin_unlock_irqrestore(&boardp->lock, flags);
11220
11221 switch (asc_res) {
11222 case ASC_NOERROR:
11223 break;
11224 case ASC_BUSY:
11225 result = SCSI_MLQUEUE_HOST_BUSY;
11226 break;
11227 case ASC_ERROR:
11228 default:
11229 asc_scsi_done(scp);
11230 break;
11231 }
11232
11233 return result;
11234}
11235
11236static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
11237{
11238 PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11239 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
11240 return inpw(eisa_cfg_iop);
11241}
11242
11243/*
11244 * Return the BIOS address of the adapter at the specified
11245 * I/O port and with the specified bus type.
11246 */
11247static unsigned short __devinit
11248AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
11249{
11250 unsigned short cfg_lsw;
11251 unsigned short bios_addr;
11252
11253 /*
11254 * The PCI BIOS is re-located by the motherboard BIOS. Because
11255 * of this the driver can not determine where a PCI BIOS is
11256 * loaded and executes.
11257 */
11258 if (bus_type & ASC_IS_PCI)
11259 return 0;
11260
11261 if ((bus_type & ASC_IS_EISA) != 0) {
11262 cfg_lsw = AscGetEisaChipCfg(iop_base);
11263 cfg_lsw &= 0x000F;
11264 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
11265 return bios_addr;
11266 }
11267
11268 cfg_lsw = AscGetChipCfgLsw(iop_base);
11269
11270 /*
11271 * ISA PnP uses the top bit as the 32K BIOS flag
11272 */
11273 if (bus_type == ASC_IS_ISAPNP)
11274 cfg_lsw &= 0x7FFF;
11275 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
11276 return bios_addr;
11277}
11278
11279static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
11280{
11281 ushort cfg_lsw;
11282
11283 if (AscGetChipScsiID(iop_base) == new_host_id) {
11284 return (new_host_id);
11285 }
11286 cfg_lsw = AscGetChipCfgLsw(iop_base);
11287 cfg_lsw &= 0xF8FF;
11288 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
11289 AscSetChipCfgLsw(iop_base, cfg_lsw);
11290 return (AscGetChipScsiID(iop_base));
11291}
11292
11293static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
11294{
11295 unsigned char sc;
11296
11297 AscSetBank(iop_base, 1);
11298 sc = inp(iop_base + IOP_REG_SC);
11299 AscSetBank(iop_base, 0);
11300 return sc;
11301}
11302
11303static unsigned char __devinit
11304AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
11305{
11306 if (bus_type & ASC_IS_EISA) {
11307 PortAddr eisa_iop;
11308 unsigned char revision;
11309 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11310 (PortAddr) ASC_EISA_REV_IOP_MASK;
11311 revision = inp(eisa_iop);
11312 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
11313 }
11314 return AscGetChipVerNo(iop_base);
11315}
11316
Matthew Wilcox51219352007-10-02 21:55:22 -040011317#ifdef CONFIG_ISA
11318static void __devinit AscEnableIsaDma(uchar dma_channel)
11319{
11320 if (dma_channel < 4) {
11321 outp(0x000B, (ushort)(0xC0 | dma_channel));
11322 outp(0x000A, dma_channel);
11323 } else if (dma_channel < 8) {
11324 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
11325 outp(0x00D4, (ushort)(dma_channel - 4));
11326 }
11327 return;
11328}
11329#endif /* CONFIG_ISA */
11330
11331static int AscStopQueueExe(PortAddr iop_base)
11332{
11333 int count = 0;
11334
11335 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
11336 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
11337 ASC_STOP_REQ_RISC_STOP);
11338 do {
11339 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
11340 ASC_STOP_ACK_RISC_STOP) {
11341 return (1);
11342 }
11343 mdelay(100);
11344 } while (count++ < 20);
11345 }
11346 return (0);
11347}
11348
11349static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
11350{
11351 if (bus_type & ASC_IS_ISA)
11352 return ASC_MAX_ISA_DMA_COUNT;
11353 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
11354 return ASC_MAX_VL_DMA_COUNT;
11355 return ASC_MAX_PCI_DMA_COUNT;
11356}
11357
11358#ifdef CONFIG_ISA
11359static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
11360{
11361 ushort channel;
11362
11363 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
11364 if (channel == 0x03)
11365 return (0);
11366 else if (channel == 0x00)
11367 return (7);
11368 return (channel + 4);
11369}
11370
11371static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
11372{
11373 ushort cfg_lsw;
11374 uchar value;
11375
11376 if ((dma_channel >= 5) && (dma_channel <= 7)) {
11377 if (dma_channel == 7)
11378 value = 0x00;
11379 else
11380 value = dma_channel - 4;
11381 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
11382 cfg_lsw |= value;
11383 AscSetChipCfgLsw(iop_base, cfg_lsw);
11384 return (AscGetIsaDmaChannel(iop_base));
11385 }
11386 return 0;
11387}
11388
11389static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
11390{
11391 uchar speed_value;
11392
11393 AscSetBank(iop_base, 1);
11394 speed_value = AscReadChipDmaSpeed(iop_base);
11395 speed_value &= 0x07;
11396 AscSetBank(iop_base, 0);
11397 return speed_value;
11398}
11399
11400static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
11401{
11402 speed_value &= 0x07;
11403 AscSetBank(iop_base, 1);
11404 AscWriteChipDmaSpeed(iop_base, speed_value);
11405 AscSetBank(iop_base, 0);
11406 return AscGetIsaDmaSpeed(iop_base);
11407}
11408#endif /* CONFIG_ISA */
11409
11410static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
11411{
11412 int i;
11413 PortAddr iop_base;
11414 ushort warn_code;
11415 uchar chip_version;
11416
11417 iop_base = asc_dvc->iop_base;
11418 warn_code = 0;
11419 asc_dvc->err_code = 0;
11420 if ((asc_dvc->bus_type &
11421 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
11422 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
11423 }
11424 AscSetChipControl(iop_base, CC_HALT);
11425 AscSetChipStatus(iop_base, 0);
11426 asc_dvc->bug_fix_cntl = 0;
11427 asc_dvc->pci_fix_asyn_xfer = 0;
11428 asc_dvc->pci_fix_asyn_xfer_always = 0;
11429 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
11430 asc_dvc->sdtr_done = 0;
11431 asc_dvc->cur_total_qng = 0;
11432 asc_dvc->is_in_int = 0;
11433 asc_dvc->in_critical_cnt = 0;
11434 asc_dvc->last_q_shortage = 0;
11435 asc_dvc->use_tagged_qng = 0;
11436 asc_dvc->no_scam = 0;
11437 asc_dvc->unit_not_ready = 0;
11438 asc_dvc->queue_full_or_busy = 0;
11439 asc_dvc->redo_scam = 0;
11440 asc_dvc->res2 = 0;
11441 asc_dvc->host_init_sdtr_index = 0;
11442 asc_dvc->cfg->can_tagged_qng = 0;
11443 asc_dvc->cfg->cmd_qng_enabled = 0;
11444 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
11445 asc_dvc->init_sdtr = 0;
11446 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
11447 asc_dvc->scsi_reset_wait = 3;
11448 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
11449 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
11450 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
11451 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
11452 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
Matthew Wilcox51219352007-10-02 21:55:22 -040011453 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
11454 asc_dvc->cfg->chip_version = chip_version;
11455 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
11456 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
11457 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
11458 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
11459 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
11460 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
11461 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
11462 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
11463 asc_dvc->max_sdtr_index = 7;
11464 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
11465 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
11466 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
11467 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
11468 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
11469 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
11470 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
11471 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
11472 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
11473 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
11474 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
11475 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
11476 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
11477 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
11478 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
11479 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
11480 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
11481 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
11482 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
11483 asc_dvc->max_sdtr_index = 15;
11484 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
11485 AscSetExtraControl(iop_base,
11486 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11487 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
11488 AscSetExtraControl(iop_base,
11489 (SEC_ACTIVE_NEGATE |
11490 SEC_ENABLE_FILTER));
11491 }
11492 }
11493 if (asc_dvc->bus_type == ASC_IS_PCI) {
11494 AscSetExtraControl(iop_base,
11495 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11496 }
11497
11498 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
11499#ifdef CONFIG_ISA
11500 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
11501 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
11502 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
11503 asc_dvc->bus_type = ASC_IS_ISAPNP;
11504 }
11505 asc_dvc->cfg->isa_dma_channel =
11506 (uchar)AscGetIsaDmaChannel(iop_base);
11507 }
11508#endif /* CONFIG_ISA */
11509 for (i = 0; i <= ASC_MAX_TID; i++) {
11510 asc_dvc->cur_dvc_qng[i] = 0;
11511 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
11512 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
11513 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
11514 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
11515 }
11516 return warn_code;
11517}
11518
11519static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
11520{
11521 int retry;
11522
11523 for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) {
11524 unsigned char read_back;
11525 AscSetChipEEPCmd(iop_base, cmd_reg);
11526 mdelay(1);
11527 read_back = AscGetChipEEPCmd(iop_base);
11528 if (read_back == cmd_reg)
11529 return 1;
11530 }
11531 return 0;
11532}
11533
11534static void __devinit AscWaitEEPRead(void)
11535{
11536 mdelay(1);
11537}
11538
11539static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
11540{
11541 ushort read_wval;
11542 uchar cmd_reg;
11543
11544 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11545 AscWaitEEPRead();
11546 cmd_reg = addr | ASC_EEP_CMD_READ;
11547 AscWriteEEPCmdReg(iop_base, cmd_reg);
11548 AscWaitEEPRead();
11549 read_wval = AscGetChipEEPData(iop_base);
11550 AscWaitEEPRead();
11551 return read_wval;
11552}
11553
11554static ushort __devinit
11555AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11556{
11557 ushort wval;
11558 ushort sum;
11559 ushort *wbuf;
11560 int cfg_beg;
11561 int cfg_end;
11562 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11563 int s_addr;
11564
11565 wbuf = (ushort *)cfg_buf;
11566 sum = 0;
11567 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
11568 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11569 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11570 sum += *wbuf;
11571 }
11572 if (bus_type & ASC_IS_VL) {
11573 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11574 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11575 } else {
11576 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11577 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11578 }
11579 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11580 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11581 if (s_addr <= uchar_end_in_config) {
11582 /*
11583 * Swap all char fields - must unswap bytes already swapped
11584 * by AscReadEEPWord().
11585 */
11586 *wbuf = le16_to_cpu(wval);
11587 } else {
11588 /* Don't swap word field at the end - cntl field. */
11589 *wbuf = wval;
11590 }
11591 sum += wval; /* Checksum treats all EEPROM data as words. */
11592 }
11593 /*
11594 * Read the checksum word which will be compared against 'sum'
11595 * by the caller. Word field already swapped.
11596 */
11597 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11598 return sum;
11599}
11600
11601static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
11602{
11603 PortAddr iop_base;
11604 ushort q_addr;
11605 ushort saved_word;
11606 int sta;
11607
11608 iop_base = asc_dvc->iop_base;
11609 sta = 0;
11610 q_addr = ASC_QNO_TO_QADDR(241);
11611 saved_word = AscReadLramWord(iop_base, q_addr);
11612 AscSetChipLramAddr(iop_base, q_addr);
11613 AscSetChipLramData(iop_base, 0x55AA);
11614 mdelay(10);
11615 AscSetChipLramAddr(iop_base, q_addr);
11616 if (AscGetChipLramData(iop_base) == 0x55AA) {
11617 sta = 1;
11618 AscWriteLramWord(iop_base, q_addr, saved_word);
11619 }
11620 return (sta);
11621}
11622
11623static void __devinit AscWaitEEPWrite(void)
11624{
11625 mdelay(20);
11626 return;
11627}
11628
11629static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
11630{
11631 ushort read_back;
11632 int retry;
11633
11634 retry = 0;
11635 while (TRUE) {
11636 AscSetChipEEPData(iop_base, data_reg);
11637 mdelay(1);
11638 read_back = AscGetChipEEPData(iop_base);
11639 if (read_back == data_reg) {
11640 return (1);
11641 }
11642 if (retry++ > ASC_EEP_MAX_RETRY) {
11643 return (0);
11644 }
11645 }
11646}
11647
11648static ushort __devinit
11649AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
11650{
11651 ushort read_wval;
11652
11653 read_wval = AscReadEEPWord(iop_base, addr);
11654 if (read_wval != word_val) {
11655 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
11656 AscWaitEEPRead();
11657 AscWriteEEPDataReg(iop_base, word_val);
11658 AscWaitEEPRead();
11659 AscWriteEEPCmdReg(iop_base,
11660 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
11661 AscWaitEEPWrite();
11662 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11663 AscWaitEEPRead();
11664 return (AscReadEEPWord(iop_base, addr));
11665 }
11666 return (read_wval);
11667}
11668
11669static int __devinit
11670AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11671{
11672 int n_error;
11673 ushort *wbuf;
11674 ushort word;
11675 ushort sum;
11676 int s_addr;
11677 int cfg_beg;
11678 int cfg_end;
11679 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11680
11681 wbuf = (ushort *)cfg_buf;
11682 n_error = 0;
11683 sum = 0;
11684 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11685 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11686 sum += *wbuf;
11687 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11688 n_error++;
11689 }
11690 }
11691 if (bus_type & ASC_IS_VL) {
11692 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11693 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11694 } else {
11695 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11696 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11697 }
11698 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11699 if (s_addr <= uchar_end_in_config) {
11700 /*
11701 * This is a char field. Swap char fields before they are
11702 * swapped again by AscWriteEEPWord().
11703 */
11704 word = cpu_to_le16(*wbuf);
11705 if (word !=
11706 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11707 n_error++;
11708 }
11709 } else {
11710 /* Don't swap word field at the end - cntl field. */
11711 if (*wbuf !=
11712 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11713 n_error++;
11714 }
11715 }
11716 sum += *wbuf; /* Checksum calculated from word values. */
11717 }
11718 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11719 *wbuf = sum;
11720 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11721 n_error++;
11722 }
11723
11724 /* Read EEPROM back again. */
11725 wbuf = (ushort *)cfg_buf;
11726 /*
11727 * Read two config words; Byte-swapping done by AscReadEEPWord().
11728 */
11729 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11730 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11731 n_error++;
11732 }
11733 }
11734 if (bus_type & ASC_IS_VL) {
11735 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11736 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11737 } else {
11738 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11739 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11740 }
11741 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11742 if (s_addr <= uchar_end_in_config) {
11743 /*
11744 * Swap all char fields. Must unswap bytes already swapped
11745 * by AscReadEEPWord().
11746 */
11747 word =
11748 le16_to_cpu(AscReadEEPWord
11749 (iop_base, (uchar)s_addr));
11750 } else {
11751 /* Don't swap word field at the end - cntl field. */
11752 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11753 }
11754 if (*wbuf != word) {
11755 n_error++;
11756 }
11757 }
11758 /* Read checksum; Byte swapping not needed. */
11759 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11760 n_error++;
11761 }
11762 return n_error;
11763}
11764
11765static int __devinit
11766AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11767{
11768 int retry;
11769 int n_error;
11770
11771 retry = 0;
11772 while (TRUE) {
11773 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
11774 bus_type)) == 0) {
11775 break;
11776 }
11777 if (++retry > ASC_EEP_MAX_RETRY) {
11778 break;
11779 }
11780 }
11781 return n_error;
11782}
11783
11784static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
11785{
11786 ASCEEP_CONFIG eep_config_buf;
11787 ASCEEP_CONFIG *eep_config;
11788 PortAddr iop_base;
11789 ushort chksum;
11790 ushort warn_code;
11791 ushort cfg_msw, cfg_lsw;
11792 int i;
11793 int write_eep = 0;
11794
11795 iop_base = asc_dvc->iop_base;
11796 warn_code = 0;
11797 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
11798 AscStopQueueExe(iop_base);
11799 if ((AscStopChip(iop_base) == FALSE) ||
11800 (AscGetChipScsiCtrl(iop_base) != 0)) {
11801 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
11802 AscResetChipAndScsiBus(asc_dvc);
11803 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
11804 }
11805 if (AscIsChipHalted(iop_base) == FALSE) {
11806 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
11807 return (warn_code);
11808 }
11809 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11810 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11811 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
11812 return (warn_code);
11813 }
11814 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
11815 cfg_msw = AscGetChipCfgMsw(iop_base);
11816 cfg_lsw = AscGetChipCfgLsw(iop_base);
11817 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
11818 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11819 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
11820 AscSetChipCfgMsw(iop_base, cfg_msw);
11821 }
11822 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011823 ASC_DBG(1, "chksum 0x%x\n", chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -040011824 if (chksum == 0) {
11825 chksum = 0xaa55;
11826 }
11827 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
11828 warn_code |= ASC_WARN_AUTO_CONFIG;
11829 if (asc_dvc->cfg->chip_version == 3) {
11830 if (eep_config->cfg_lsw != cfg_lsw) {
11831 warn_code |= ASC_WARN_EEPROM_RECOVER;
11832 eep_config->cfg_lsw =
11833 AscGetChipCfgLsw(iop_base);
11834 }
11835 if (eep_config->cfg_msw != cfg_msw) {
11836 warn_code |= ASC_WARN_EEPROM_RECOVER;
11837 eep_config->cfg_msw =
11838 AscGetChipCfgMsw(iop_base);
11839 }
11840 }
11841 }
11842 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11843 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011844 ASC_DBG(1, "eep_config->chksum 0x%x\n", eep_config->chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -040011845 if (chksum != eep_config->chksum) {
11846 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
11847 ASC_CHIP_VER_PCI_ULTRA_3050) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011848 ASC_DBG(1, "chksum error ignored; EEPROM-less board\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011849 eep_config->init_sdtr = 0xFF;
11850 eep_config->disc_enable = 0xFF;
11851 eep_config->start_motor = 0xFF;
11852 eep_config->use_cmd_qng = 0;
11853 eep_config->max_total_qng = 0xF0;
11854 eep_config->max_tag_qng = 0x20;
11855 eep_config->cntl = 0xBFFF;
11856 ASC_EEP_SET_CHIP_ID(eep_config, 7);
11857 eep_config->no_scam = 0;
11858 eep_config->adapter_info[0] = 0;
11859 eep_config->adapter_info[1] = 0;
11860 eep_config->adapter_info[2] = 0;
11861 eep_config->adapter_info[3] = 0;
11862 eep_config->adapter_info[4] = 0;
11863 /* Indicate EEPROM-less board. */
11864 eep_config->adapter_info[5] = 0xBB;
11865 } else {
11866 ASC_PRINT
11867 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
11868 write_eep = 1;
11869 warn_code |= ASC_WARN_EEPROM_CHKSUM;
11870 }
11871 }
11872 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
11873 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
11874 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
11875 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
11876 asc_dvc->start_motor = eep_config->start_motor;
11877 asc_dvc->dvc_cntl = eep_config->cntl;
11878 asc_dvc->no_scam = eep_config->no_scam;
11879 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
11880 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
11881 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
11882 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
11883 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
11884 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
11885 if (!AscTestExternalLram(asc_dvc)) {
11886 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
11887 ASC_IS_PCI_ULTRA)) {
11888 eep_config->max_total_qng =
11889 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
11890 eep_config->max_tag_qng =
11891 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
11892 } else {
11893 eep_config->cfg_msw |= 0x0800;
11894 cfg_msw |= 0x0800;
11895 AscSetChipCfgMsw(iop_base, cfg_msw);
11896 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
11897 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
11898 }
11899 } else {
11900 }
11901 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
11902 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
11903 }
11904 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
11905 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
11906 }
11907 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
11908 eep_config->max_tag_qng = eep_config->max_total_qng;
11909 }
11910 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
11911 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
11912 }
11913 asc_dvc->max_total_qng = eep_config->max_total_qng;
11914 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
11915 eep_config->use_cmd_qng) {
11916 eep_config->disc_enable = eep_config->use_cmd_qng;
11917 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
11918 }
Matthew Wilcox51219352007-10-02 21:55:22 -040011919 ASC_EEP_SET_CHIP_ID(eep_config,
11920 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
11921 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
11922 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
11923 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
11924 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
11925 }
11926
11927 for (i = 0; i <= ASC_MAX_TID; i++) {
11928 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
11929 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
11930 asc_dvc->cfg->sdtr_period_offset[i] =
11931 (uchar)(ASC_DEF_SDTR_OFFSET |
11932 (asc_dvc->host_init_sdtr_index << 4));
11933 }
11934 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
11935 if (write_eep) {
11936 if ((i = AscSetEEPConfig(iop_base, eep_config,
11937 asc_dvc->bus_type)) != 0) {
11938 ASC_PRINT1
11939 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
11940 i);
11941 } else {
11942 ASC_PRINT
11943 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
11944 }
11945 }
11946 return (warn_code);
11947}
11948
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011949static int __devinit AscInitGetConfig(struct asc_board *boardp)
Matthew Wilcox51219352007-10-02 21:55:22 -040011950{
11951 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
11952 unsigned short warn_code = 0;
11953
11954 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
11955 if (asc_dvc->err_code != 0)
11956 return asc_dvc->err_code;
11957
11958 if (AscFindSignature(asc_dvc->iop_base)) {
11959 warn_code |= AscInitAscDvcVar(asc_dvc);
11960 warn_code |= AscInitFromEEP(asc_dvc);
11961 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
11962 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
11963 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
11964 } else {
11965 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11966 }
11967
11968 switch (warn_code) {
11969 case 0: /* No error */
11970 break;
11971 case ASC_WARN_IO_PORT_ROTATE:
11972 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
11973 "modified\n", boardp->id);
11974 break;
11975 case ASC_WARN_AUTO_CONFIG:
11976 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
11977 "switch enabled\n", boardp->id);
11978 break;
11979 case ASC_WARN_EEPROM_CHKSUM:
11980 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
11981 "error\n", boardp->id);
11982 break;
11983 case ASC_WARN_IRQ_MODIFIED:
11984 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
11985 boardp->id);
11986 break;
11987 case ASC_WARN_CMD_QNG_CONFLICT:
11988 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
11989 "w/o disconnects\n", boardp->id);
11990 break;
11991 default:
11992 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
11993 "0x%x\n", boardp->id, warn_code);
11994 break;
11995 }
11996
11997 if (asc_dvc->err_code != 0) {
11998 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
11999 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12000 asc_dvc->err_code);
12001 }
12002
12003 return asc_dvc->err_code;
12004}
12005
Matthew Wilcoxd2411492007-10-02 21:55:31 -040012006static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct asc_board *boardp)
Matthew Wilcox51219352007-10-02 21:55:22 -040012007{
12008 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
12009 PortAddr iop_base = asc_dvc->iop_base;
12010 unsigned short cfg_msw;
12011 unsigned short warn_code = 0;
12012
12013 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12014 if (asc_dvc->err_code != 0)
12015 return asc_dvc->err_code;
12016 if (!AscFindSignature(asc_dvc->iop_base)) {
12017 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12018 return asc_dvc->err_code;
12019 }
12020
12021 cfg_msw = AscGetChipCfgMsw(iop_base);
12022 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12023 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
12024 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12025 AscSetChipCfgMsw(iop_base, cfg_msw);
12026 }
12027 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12028 asc_dvc->cfg->cmd_qng_enabled) {
12029 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12030 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12031 }
12032 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12033 warn_code |= ASC_WARN_AUTO_CONFIG;
12034 }
Matthew Wilcox51219352007-10-02 21:55:22 -040012035#ifdef CONFIG_PCI
12036 if (asc_dvc->bus_type & ASC_IS_PCI) {
12037 cfg_msw &= 0xFFC0;
12038 AscSetChipCfgMsw(iop_base, cfg_msw);
12039 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12040 } else {
12041 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
12042 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
12043 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12044 asc_dvc->bug_fix_cntl |=
12045 ASC_BUG_FIX_ASYN_USE_SYN;
12046 }
12047 }
12048 } else
12049#endif /* CONFIG_PCI */
12050 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12051 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12052 == ASC_CHIP_VER_ASYN_BUG) {
12053 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12054 }
12055 }
12056 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12057 asc_dvc->cfg->chip_scsi_id) {
12058 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12059 }
12060#ifdef CONFIG_ISA
12061 if (asc_dvc->bus_type & ASC_IS_ISA) {
12062 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12063 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12064 }
12065#endif /* CONFIG_ISA */
12066
12067 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12068
12069 switch (warn_code) {
12070 case 0: /* No error. */
12071 break;
12072 case ASC_WARN_IO_PORT_ROTATE:
12073 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
12074 "modified\n", boardp->id);
12075 break;
12076 case ASC_WARN_AUTO_CONFIG:
12077 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
12078 "switch enabled\n", boardp->id);
12079 break;
12080 case ASC_WARN_EEPROM_CHKSUM:
12081 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
12082 "error\n", boardp->id);
12083 break;
12084 case ASC_WARN_IRQ_MODIFIED:
12085 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
12086 boardp->id);
12087 break;
12088 case ASC_WARN_CMD_QNG_CONFLICT:
12089 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
12090 "disconnects\n",
12091 boardp->id);
12092 break;
12093 default:
12094 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
12095 "0x%x\n", boardp->id, warn_code);
12096 break;
12097 }
12098
12099 if (asc_dvc->err_code != 0) {
12100 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
12101 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12102 asc_dvc->err_code);
12103 }
12104
12105 return asc_dvc->err_code;
12106}
12107
12108/*
12109 * EEPROM Configuration.
12110 *
12111 * All drivers should use this structure to set the default EEPROM
12112 * configuration. The BIOS now uses this structure when it is built.
12113 * Additional structure information can be found in a_condor.h where
12114 * the structure is defined.
12115 *
12116 * The *_Field_IsChar structs are needed to correct for endianness.
12117 * These values are read from the board 16 bits at a time directly
12118 * into the structs. Because some fields are char, the values will be
12119 * in the wrong order. The *_Field_IsChar tells when to flip the
12120 * bytes. Data read and written to PCI memory is automatically swapped
12121 * on big-endian platforms so char fields read as words are actually being
12122 * unswapped on big-endian platforms.
12123 */
12124static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
12125 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
12126 0x0000, /* cfg_msw */
12127 0xFFFF, /* disc_enable */
12128 0xFFFF, /* wdtr_able */
12129 0xFFFF, /* sdtr_able */
12130 0xFFFF, /* start_motor */
12131 0xFFFF, /* tagqng_able */
12132 0xFFFF, /* bios_scan */
12133 0, /* scam_tolerant */
12134 7, /* adapter_scsi_id */
12135 0, /* bios_boot_delay */
12136 3, /* scsi_reset_delay */
12137 0, /* bios_id_lun */
12138 0, /* termination */
12139 0, /* reserved1 */
12140 0xFFE7, /* bios_ctrl */
12141 0xFFFF, /* ultra_able */
12142 0, /* reserved2 */
12143 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
12144 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12145 0, /* dvc_cntl */
12146 0, /* bug_fix */
12147 0, /* serial_number_word1 */
12148 0, /* serial_number_word2 */
12149 0, /* serial_number_word3 */
12150 0, /* check_sum */
12151 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12152 , /* oem_name[16] */
12153 0, /* dvc_err_code */
12154 0, /* adv_err_code */
12155 0, /* adv_err_addr */
12156 0, /* saved_dvc_err_code */
12157 0, /* saved_adv_err_code */
12158 0, /* saved_adv_err_addr */
12159 0 /* num_of_err */
12160};
12161
12162static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
12163 0, /* cfg_lsw */
12164 0, /* cfg_msw */
12165 0, /* -disc_enable */
12166 0, /* wdtr_able */
12167 0, /* sdtr_able */
12168 0, /* start_motor */
12169 0, /* tagqng_able */
12170 0, /* bios_scan */
12171 0, /* scam_tolerant */
12172 1, /* adapter_scsi_id */
12173 1, /* bios_boot_delay */
12174 1, /* scsi_reset_delay */
12175 1, /* bios_id_lun */
12176 1, /* termination */
12177 1, /* reserved1 */
12178 0, /* bios_ctrl */
12179 0, /* ultra_able */
12180 0, /* reserved2 */
12181 1, /* max_host_qng */
12182 1, /* max_dvc_qng */
12183 0, /* dvc_cntl */
12184 0, /* bug_fix */
12185 0, /* serial_number_word1 */
12186 0, /* serial_number_word2 */
12187 0, /* serial_number_word3 */
12188 0, /* check_sum */
12189 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12190 , /* oem_name[16] */
12191 0, /* dvc_err_code */
12192 0, /* adv_err_code */
12193 0, /* adv_err_addr */
12194 0, /* saved_dvc_err_code */
12195 0, /* saved_adv_err_code */
12196 0, /* saved_adv_err_addr */
12197 0 /* num_of_err */
12198};
12199
12200static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
12201 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12202 0x0000, /* 01 cfg_msw */
12203 0xFFFF, /* 02 disc_enable */
12204 0xFFFF, /* 03 wdtr_able */
12205 0x4444, /* 04 sdtr_speed1 */
12206 0xFFFF, /* 05 start_motor */
12207 0xFFFF, /* 06 tagqng_able */
12208 0xFFFF, /* 07 bios_scan */
12209 0, /* 08 scam_tolerant */
12210 7, /* 09 adapter_scsi_id */
12211 0, /* bios_boot_delay */
12212 3, /* 10 scsi_reset_delay */
12213 0, /* bios_id_lun */
12214 0, /* 11 termination_se */
12215 0, /* termination_lvd */
12216 0xFFE7, /* 12 bios_ctrl */
12217 0x4444, /* 13 sdtr_speed2 */
12218 0x4444, /* 14 sdtr_speed3 */
12219 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12220 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12221 0, /* 16 dvc_cntl */
12222 0x4444, /* 17 sdtr_speed4 */
12223 0, /* 18 serial_number_word1 */
12224 0, /* 19 serial_number_word2 */
12225 0, /* 20 serial_number_word3 */
12226 0, /* 21 check_sum */
12227 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12228 , /* 22-29 oem_name[16] */
12229 0, /* 30 dvc_err_code */
12230 0, /* 31 adv_err_code */
12231 0, /* 32 adv_err_addr */
12232 0, /* 33 saved_dvc_err_code */
12233 0, /* 34 saved_adv_err_code */
12234 0, /* 35 saved_adv_err_addr */
12235 0, /* 36 reserved */
12236 0, /* 37 reserved */
12237 0, /* 38 reserved */
12238 0, /* 39 reserved */
12239 0, /* 40 reserved */
12240 0, /* 41 reserved */
12241 0, /* 42 reserved */
12242 0, /* 43 reserved */
12243 0, /* 44 reserved */
12244 0, /* 45 reserved */
12245 0, /* 46 reserved */
12246 0, /* 47 reserved */
12247 0, /* 48 reserved */
12248 0, /* 49 reserved */
12249 0, /* 50 reserved */
12250 0, /* 51 reserved */
12251 0, /* 52 reserved */
12252 0, /* 53 reserved */
12253 0, /* 54 reserved */
12254 0, /* 55 reserved */
12255 0, /* 56 cisptr_lsw */
12256 0, /* 57 cisprt_msw */
12257 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12258 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
12259 0, /* 60 reserved */
12260 0, /* 61 reserved */
12261 0, /* 62 reserved */
12262 0 /* 63 reserved */
12263};
12264
12265static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
12266 0, /* 00 cfg_lsw */
12267 0, /* 01 cfg_msw */
12268 0, /* 02 disc_enable */
12269 0, /* 03 wdtr_able */
12270 0, /* 04 sdtr_speed1 */
12271 0, /* 05 start_motor */
12272 0, /* 06 tagqng_able */
12273 0, /* 07 bios_scan */
12274 0, /* 08 scam_tolerant */
12275 1, /* 09 adapter_scsi_id */
12276 1, /* bios_boot_delay */
12277 1, /* 10 scsi_reset_delay */
12278 1, /* bios_id_lun */
12279 1, /* 11 termination_se */
12280 1, /* termination_lvd */
12281 0, /* 12 bios_ctrl */
12282 0, /* 13 sdtr_speed2 */
12283 0, /* 14 sdtr_speed3 */
12284 1, /* 15 max_host_qng */
12285 1, /* max_dvc_qng */
12286 0, /* 16 dvc_cntl */
12287 0, /* 17 sdtr_speed4 */
12288 0, /* 18 serial_number_word1 */
12289 0, /* 19 serial_number_word2 */
12290 0, /* 20 serial_number_word3 */
12291 0, /* 21 check_sum */
12292 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12293 , /* 22-29 oem_name[16] */
12294 0, /* 30 dvc_err_code */
12295 0, /* 31 adv_err_code */
12296 0, /* 32 adv_err_addr */
12297 0, /* 33 saved_dvc_err_code */
12298 0, /* 34 saved_adv_err_code */
12299 0, /* 35 saved_adv_err_addr */
12300 0, /* 36 reserved */
12301 0, /* 37 reserved */
12302 0, /* 38 reserved */
12303 0, /* 39 reserved */
12304 0, /* 40 reserved */
12305 0, /* 41 reserved */
12306 0, /* 42 reserved */
12307 0, /* 43 reserved */
12308 0, /* 44 reserved */
12309 0, /* 45 reserved */
12310 0, /* 46 reserved */
12311 0, /* 47 reserved */
12312 0, /* 48 reserved */
12313 0, /* 49 reserved */
12314 0, /* 50 reserved */
12315 0, /* 51 reserved */
12316 0, /* 52 reserved */
12317 0, /* 53 reserved */
12318 0, /* 54 reserved */
12319 0, /* 55 reserved */
12320 0, /* 56 cisptr_lsw */
12321 0, /* 57 cisprt_msw */
12322 0, /* 58 subsysvid */
12323 0, /* 59 subsysid */
12324 0, /* 60 reserved */
12325 0, /* 61 reserved */
12326 0, /* 62 reserved */
12327 0 /* 63 reserved */
12328};
12329
12330static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
12331 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12332 0x0000, /* 01 cfg_msw */
12333 0xFFFF, /* 02 disc_enable */
12334 0xFFFF, /* 03 wdtr_able */
12335 0x5555, /* 04 sdtr_speed1 */
12336 0xFFFF, /* 05 start_motor */
12337 0xFFFF, /* 06 tagqng_able */
12338 0xFFFF, /* 07 bios_scan */
12339 0, /* 08 scam_tolerant */
12340 7, /* 09 adapter_scsi_id */
12341 0, /* bios_boot_delay */
12342 3, /* 10 scsi_reset_delay */
12343 0, /* bios_id_lun */
12344 0, /* 11 termination_se */
12345 0, /* termination_lvd */
12346 0xFFE7, /* 12 bios_ctrl */
12347 0x5555, /* 13 sdtr_speed2 */
12348 0x5555, /* 14 sdtr_speed3 */
12349 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12350 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12351 0, /* 16 dvc_cntl */
12352 0x5555, /* 17 sdtr_speed4 */
12353 0, /* 18 serial_number_word1 */
12354 0, /* 19 serial_number_word2 */
12355 0, /* 20 serial_number_word3 */
12356 0, /* 21 check_sum */
12357 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12358 , /* 22-29 oem_name[16] */
12359 0, /* 30 dvc_err_code */
12360 0, /* 31 adv_err_code */
12361 0, /* 32 adv_err_addr */
12362 0, /* 33 saved_dvc_err_code */
12363 0, /* 34 saved_adv_err_code */
12364 0, /* 35 saved_adv_err_addr */
12365 0, /* 36 reserved */
12366 0, /* 37 reserved */
12367 0, /* 38 reserved */
12368 0, /* 39 reserved */
12369 0, /* 40 reserved */
12370 0, /* 41 reserved */
12371 0, /* 42 reserved */
12372 0, /* 43 reserved */
12373 0, /* 44 reserved */
12374 0, /* 45 reserved */
12375 0, /* 46 reserved */
12376 0, /* 47 reserved */
12377 0, /* 48 reserved */
12378 0, /* 49 reserved */
12379 0, /* 50 reserved */
12380 0, /* 51 reserved */
12381 0, /* 52 reserved */
12382 0, /* 53 reserved */
12383 0, /* 54 reserved */
12384 0, /* 55 reserved */
12385 0, /* 56 cisptr_lsw */
12386 0, /* 57 cisprt_msw */
12387 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12388 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
12389 0, /* 60 reserved */
12390 0, /* 61 reserved */
12391 0, /* 62 reserved */
12392 0 /* 63 reserved */
12393};
12394
12395static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
12396 0, /* 00 cfg_lsw */
12397 0, /* 01 cfg_msw */
12398 0, /* 02 disc_enable */
12399 0, /* 03 wdtr_able */
12400 0, /* 04 sdtr_speed1 */
12401 0, /* 05 start_motor */
12402 0, /* 06 tagqng_able */
12403 0, /* 07 bios_scan */
12404 0, /* 08 scam_tolerant */
12405 1, /* 09 adapter_scsi_id */
12406 1, /* bios_boot_delay */
12407 1, /* 10 scsi_reset_delay */
12408 1, /* bios_id_lun */
12409 1, /* 11 termination_se */
12410 1, /* termination_lvd */
12411 0, /* 12 bios_ctrl */
12412 0, /* 13 sdtr_speed2 */
12413 0, /* 14 sdtr_speed3 */
12414 1, /* 15 max_host_qng */
12415 1, /* max_dvc_qng */
12416 0, /* 16 dvc_cntl */
12417 0, /* 17 sdtr_speed4 */
12418 0, /* 18 serial_number_word1 */
12419 0, /* 19 serial_number_word2 */
12420 0, /* 20 serial_number_word3 */
12421 0, /* 21 check_sum */
12422 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12423 , /* 22-29 oem_name[16] */
12424 0, /* 30 dvc_err_code */
12425 0, /* 31 adv_err_code */
12426 0, /* 32 adv_err_addr */
12427 0, /* 33 saved_dvc_err_code */
12428 0, /* 34 saved_adv_err_code */
12429 0, /* 35 saved_adv_err_addr */
12430 0, /* 36 reserved */
12431 0, /* 37 reserved */
12432 0, /* 38 reserved */
12433 0, /* 39 reserved */
12434 0, /* 40 reserved */
12435 0, /* 41 reserved */
12436 0, /* 42 reserved */
12437 0, /* 43 reserved */
12438 0, /* 44 reserved */
12439 0, /* 45 reserved */
12440 0, /* 46 reserved */
12441 0, /* 47 reserved */
12442 0, /* 48 reserved */
12443 0, /* 49 reserved */
12444 0, /* 50 reserved */
12445 0, /* 51 reserved */
12446 0, /* 52 reserved */
12447 0, /* 53 reserved */
12448 0, /* 54 reserved */
12449 0, /* 55 reserved */
12450 0, /* 56 cisptr_lsw */
12451 0, /* 57 cisprt_msw */
12452 0, /* 58 subsysvid */
12453 0, /* 59 subsysid */
12454 0, /* 60 reserved */
12455 0, /* 61 reserved */
12456 0, /* 62 reserved */
12457 0 /* 63 reserved */
12458};
12459
12460#ifdef CONFIG_PCI
12461/*
12462 * Wait for EEPROM command to complete
12463 */
12464static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
12465{
12466 int eep_delay_ms;
12467
12468 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
12469 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
12470 ASC_EEP_CMD_DONE) {
12471 break;
12472 }
12473 mdelay(1);
12474 }
12475 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
12476 0)
12477 BUG();
12478}
12479
12480/*
12481 * Read the EEPROM from specified location
12482 */
12483static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
12484{
12485 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12486 ASC_EEP_CMD_READ | eep_word_addr);
12487 AdvWaitEEPCmd(iop_base);
12488 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
12489}
12490
12491/*
12492 * Write the EEPROM from 'cfg_buf'.
12493 */
12494void __devinit
12495AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12496{
12497 ushort *wbuf;
12498 ushort addr, chksum;
12499 ushort *charfields;
12500
12501 wbuf = (ushort *)cfg_buf;
12502 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12503 chksum = 0;
12504
12505 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12506 AdvWaitEEPCmd(iop_base);
12507
12508 /*
12509 * Write EEPROM from word 0 to word 20.
12510 */
12511 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12512 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12513 ushort word;
12514
12515 if (*charfields++) {
12516 word = cpu_to_le16(*wbuf);
12517 } else {
12518 word = *wbuf;
12519 }
12520 chksum += *wbuf; /* Checksum is calculated from word values. */
12521 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12522 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12523 ASC_EEP_CMD_WRITE | addr);
12524 AdvWaitEEPCmd(iop_base);
12525 mdelay(ADV_EEP_DELAY_MS);
12526 }
12527
12528 /*
12529 * Write EEPROM checksum at word 21.
12530 */
12531 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12532 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12533 AdvWaitEEPCmd(iop_base);
12534 wbuf++;
12535 charfields++;
12536
12537 /*
12538 * Write EEPROM OEM name at words 22 to 29.
12539 */
12540 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12541 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12542 ushort word;
12543
12544 if (*charfields++) {
12545 word = cpu_to_le16(*wbuf);
12546 } else {
12547 word = *wbuf;
12548 }
12549 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12550 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12551 ASC_EEP_CMD_WRITE | addr);
12552 AdvWaitEEPCmd(iop_base);
12553 }
12554 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12555 AdvWaitEEPCmd(iop_base);
12556}
12557
12558/*
12559 * Write the EEPROM from 'cfg_buf'.
12560 */
12561void __devinit
12562AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12563{
12564 ushort *wbuf;
12565 ushort *charfields;
12566 ushort addr, chksum;
12567
12568 wbuf = (ushort *)cfg_buf;
12569 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12570 chksum = 0;
12571
12572 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12573 AdvWaitEEPCmd(iop_base);
12574
12575 /*
12576 * Write EEPROM from word 0 to word 20.
12577 */
12578 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12579 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12580 ushort word;
12581
12582 if (*charfields++) {
12583 word = cpu_to_le16(*wbuf);
12584 } else {
12585 word = *wbuf;
12586 }
12587 chksum += *wbuf; /* Checksum is calculated from word values. */
12588 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12589 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12590 ASC_EEP_CMD_WRITE | addr);
12591 AdvWaitEEPCmd(iop_base);
12592 mdelay(ADV_EEP_DELAY_MS);
12593 }
12594
12595 /*
12596 * Write EEPROM checksum at word 21.
12597 */
12598 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12599 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12600 AdvWaitEEPCmd(iop_base);
12601 wbuf++;
12602 charfields++;
12603
12604 /*
12605 * Write EEPROM OEM name at words 22 to 29.
12606 */
12607 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12608 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12609 ushort word;
12610
12611 if (*charfields++) {
12612 word = cpu_to_le16(*wbuf);
12613 } else {
12614 word = *wbuf;
12615 }
12616 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12617 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12618 ASC_EEP_CMD_WRITE | addr);
12619 AdvWaitEEPCmd(iop_base);
12620 }
12621 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12622 AdvWaitEEPCmd(iop_base);
12623}
12624
12625/*
12626 * Write the EEPROM from 'cfg_buf'.
12627 */
12628void __devinit
12629AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12630{
12631 ushort *wbuf;
12632 ushort *charfields;
12633 ushort addr, chksum;
12634
12635 wbuf = (ushort *)cfg_buf;
12636 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12637 chksum = 0;
12638
12639 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12640 AdvWaitEEPCmd(iop_base);
12641
12642 /*
12643 * Write EEPROM from word 0 to word 20.
12644 */
12645 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12646 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12647 ushort word;
12648
12649 if (*charfields++) {
12650 word = cpu_to_le16(*wbuf);
12651 } else {
12652 word = *wbuf;
12653 }
12654 chksum += *wbuf; /* Checksum is calculated from word values. */
12655 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12656 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12657 ASC_EEP_CMD_WRITE | addr);
12658 AdvWaitEEPCmd(iop_base);
12659 mdelay(ADV_EEP_DELAY_MS);
12660 }
12661
12662 /*
12663 * Write EEPROM checksum at word 21.
12664 */
12665 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12666 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12667 AdvWaitEEPCmd(iop_base);
12668 wbuf++;
12669 charfields++;
12670
12671 /*
12672 * Write EEPROM OEM name at words 22 to 29.
12673 */
12674 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12675 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12676 ushort word;
12677
12678 if (*charfields++) {
12679 word = cpu_to_le16(*wbuf);
12680 } else {
12681 word = *wbuf;
12682 }
12683 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12684 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12685 ASC_EEP_CMD_WRITE | addr);
12686 AdvWaitEEPCmd(iop_base);
12687 }
12688 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12689 AdvWaitEEPCmd(iop_base);
12690}
12691
12692/*
12693 * Read EEPROM configuration into the specified buffer.
12694 *
12695 * Return a checksum based on the EEPROM configuration read.
12696 */
12697static ushort __devinit
12698AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12699{
12700 ushort wval, chksum;
12701 ushort *wbuf;
12702 int eep_addr;
12703 ushort *charfields;
12704
12705 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12706 wbuf = (ushort *)cfg_buf;
12707 chksum = 0;
12708
12709 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12710 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12711 wval = AdvReadEEPWord(iop_base, eep_addr);
12712 chksum += wval; /* Checksum is calculated from word values. */
12713 if (*charfields++) {
12714 *wbuf = le16_to_cpu(wval);
12715 } else {
12716 *wbuf = wval;
12717 }
12718 }
12719 /* Read checksum word. */
12720 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12721 wbuf++;
12722 charfields++;
12723
12724 /* Read rest of EEPROM not covered by the checksum. */
12725 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12726 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12727 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12728 if (*charfields++) {
12729 *wbuf = le16_to_cpu(*wbuf);
12730 }
12731 }
12732 return chksum;
12733}
12734
12735/*
12736 * Read EEPROM configuration into the specified buffer.
12737 *
12738 * Return a checksum based on the EEPROM configuration read.
12739 */
12740static ushort __devinit
12741AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12742{
12743 ushort wval, chksum;
12744 ushort *wbuf;
12745 int eep_addr;
12746 ushort *charfields;
12747
12748 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12749 wbuf = (ushort *)cfg_buf;
12750 chksum = 0;
12751
12752 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12753 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12754 wval = AdvReadEEPWord(iop_base, eep_addr);
12755 chksum += wval; /* Checksum is calculated from word values. */
12756 if (*charfields++) {
12757 *wbuf = le16_to_cpu(wval);
12758 } else {
12759 *wbuf = wval;
12760 }
12761 }
12762 /* Read checksum word. */
12763 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12764 wbuf++;
12765 charfields++;
12766
12767 /* Read rest of EEPROM not covered by the checksum. */
12768 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12769 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12770 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12771 if (*charfields++) {
12772 *wbuf = le16_to_cpu(*wbuf);
12773 }
12774 }
12775 return chksum;
12776}
12777
12778/*
12779 * Read EEPROM configuration into the specified buffer.
12780 *
12781 * Return a checksum based on the EEPROM configuration read.
12782 */
12783static ushort __devinit
12784AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12785{
12786 ushort wval, chksum;
12787 ushort *wbuf;
12788 int eep_addr;
12789 ushort *charfields;
12790
12791 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12792 wbuf = (ushort *)cfg_buf;
12793 chksum = 0;
12794
12795 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12796 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12797 wval = AdvReadEEPWord(iop_base, eep_addr);
12798 chksum += wval; /* Checksum is calculated from word values. */
12799 if (*charfields++) {
12800 *wbuf = le16_to_cpu(wval);
12801 } else {
12802 *wbuf = wval;
12803 }
12804 }
12805 /* Read checksum word. */
12806 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12807 wbuf++;
12808 charfields++;
12809
12810 /* Read rest of EEPROM not covered by the checksum. */
12811 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12812 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12813 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12814 if (*charfields++) {
12815 *wbuf = le16_to_cpu(*wbuf);
12816 }
12817 }
12818 return chksum;
12819}
12820
12821/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070012822 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12823 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12824 * all of this is done.
12825 *
12826 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12827 *
12828 * For a non-fatal error return a warning code. If there are no warnings
12829 * then 0 is returned.
12830 *
12831 * Note: Chip is stopped on entry.
12832 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012833static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012834{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012835 AdvPortAddr iop_base;
12836 ushort warn_code;
12837 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012838
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012839 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012841 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012842
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012843 /*
12844 * Read the board's EEPROM configuration.
12845 *
12846 * Set default values if a bad checksum is found.
12847 */
12848 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12849 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012850
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012851 /*
12852 * Set EEPROM default values.
12853 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012854 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12855 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012857 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012858 * Assume the 6 byte board serial number that was read from
12859 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012860 */
12861 eep_config.serial_number_word3 =
12862 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012863
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012864 eep_config.serial_number_word2 =
12865 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012866
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012867 eep_config.serial_number_word1 =
12868 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012869
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012870 AdvSet3550EEPConfig(iop_base, &eep_config);
12871 }
12872 /*
12873 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
12874 * EEPROM configuration that was read.
12875 *
12876 * This is the mapping of EEPROM fields to Adv Library fields.
12877 */
12878 asc_dvc->wdtr_able = eep_config.wdtr_able;
12879 asc_dvc->sdtr_able = eep_config.sdtr_able;
12880 asc_dvc->ultra_able = eep_config.ultra_able;
12881 asc_dvc->tagqng_able = eep_config.tagqng_able;
12882 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
12883 asc_dvc->max_host_qng = eep_config.max_host_qng;
12884 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
12885 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
12886 asc_dvc->start_motor = eep_config.start_motor;
12887 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
12888 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
12889 asc_dvc->no_scam = eep_config.scam_tolerant;
12890 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
12891 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
12892 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012893
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012894 /*
12895 * Set the host maximum queuing (max. 253, min. 16) and the per device
12896 * maximum queuing (max. 63, min. 4).
12897 */
12898 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
12899 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12900 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
12901 /* If the value is zero, assume it is uninitialized. */
12902 if (eep_config.max_host_qng == 0) {
12903 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12904 } else {
12905 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
12906 }
12907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012908
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012909 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
12910 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12911 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
12912 /* If the value is zero, assume it is uninitialized. */
12913 if (eep_config.max_dvc_qng == 0) {
12914 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12915 } else {
12916 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
12917 }
12918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012919
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012920 /*
12921 * If 'max_dvc_qng' is greater than 'max_host_qng', then
12922 * set 'max_dvc_qng' to 'max_host_qng'.
12923 */
12924 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
12925 eep_config.max_dvc_qng = eep_config.max_host_qng;
12926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012927
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012928 /*
12929 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
12930 * values based on possibly adjusted EEPROM values.
12931 */
12932 asc_dvc->max_host_qng = eep_config.max_host_qng;
12933 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012934
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012935 /*
12936 * If the EEPROM 'termination' field is set to automatic (0), then set
12937 * the ADV_DVC_CFG 'termination' field to automatic also.
12938 *
12939 * If the termination is specified with a non-zero 'termination'
12940 * value check that a legal value is set and set the ADV_DVC_CFG
12941 * 'termination' field appropriately.
12942 */
12943 if (eep_config.termination == 0) {
12944 asc_dvc->cfg->termination = 0; /* auto termination */
12945 } else {
12946 /* Enable manual control with low off / high off. */
12947 if (eep_config.termination == 1) {
12948 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012949
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012950 /* Enable manual control with low off / high on. */
12951 } else if (eep_config.termination == 2) {
12952 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012953
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012954 /* Enable manual control with low on / high on. */
12955 } else if (eep_config.termination == 3) {
12956 asc_dvc->cfg->termination =
12957 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
12958 } else {
12959 /*
12960 * The EEPROM 'termination' field contains a bad value. Use
12961 * automatic termination instead.
12962 */
12963 asc_dvc->cfg->termination = 0;
12964 warn_code |= ASC_WARN_EEPROM_TERMINATION;
12965 }
12966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012967
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012968 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012969}
12970
12971/*
12972 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12973 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12974 * all of this is done.
12975 *
12976 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12977 *
12978 * For a non-fatal error return a warning code. If there are no warnings
12979 * then 0 is returned.
12980 *
12981 * Note: Chip is stopped on entry.
12982 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012983static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012984{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012985 AdvPortAddr iop_base;
12986 ushort warn_code;
12987 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012988 uchar tid, termination;
12989 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012991 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012992
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012993 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012994
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012995 /*
12996 * Read the board's EEPROM configuration.
12997 *
12998 * Set default values if a bad checksum is found.
12999 */
13000 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13001 eep_config.check_sum) {
13002 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013003
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013004 /*
13005 * Set EEPROM default values.
13006 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013007 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13008 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013009
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013010 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013011 * Assume the 6 byte board serial number that was read from
13012 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013013 */
13014 eep_config.serial_number_word3 =
13015 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013016
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013017 eep_config.serial_number_word2 =
13018 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013019
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013020 eep_config.serial_number_word1 =
13021 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013022
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013023 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13024 }
13025 /*
13026 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13027 * EEPROM configuration that was read.
13028 *
13029 * This is the mapping of EEPROM fields to Adv Library fields.
13030 */
13031 asc_dvc->wdtr_able = eep_config.wdtr_able;
13032 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13033 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13034 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13035 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13036 asc_dvc->tagqng_able = eep_config.tagqng_able;
13037 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13038 asc_dvc->max_host_qng = eep_config.max_host_qng;
13039 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13040 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13041 asc_dvc->start_motor = eep_config.start_motor;
13042 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13043 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13044 asc_dvc->no_scam = eep_config.scam_tolerant;
13045 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13046 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13047 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013049 /*
13050 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13051 * are set, then set an 'sdtr_able' bit for it.
13052 */
13053 asc_dvc->sdtr_able = 0;
13054 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13055 if (tid == 0) {
13056 sdtr_speed = asc_dvc->sdtr_speed1;
13057 } else if (tid == 4) {
13058 sdtr_speed = asc_dvc->sdtr_speed2;
13059 } else if (tid == 8) {
13060 sdtr_speed = asc_dvc->sdtr_speed3;
13061 } else if (tid == 12) {
13062 sdtr_speed = asc_dvc->sdtr_speed4;
13063 }
13064 if (sdtr_speed & ADV_MAX_TID) {
13065 asc_dvc->sdtr_able |= (1 << tid);
13066 }
13067 sdtr_speed >>= 4;
13068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013069
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013070 /*
13071 * Set the host maximum queuing (max. 253, min. 16) and the per device
13072 * maximum queuing (max. 63, min. 4).
13073 */
13074 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13075 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13076 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13077 /* If the value is zero, assume it is uninitialized. */
13078 if (eep_config.max_host_qng == 0) {
13079 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13080 } else {
13081 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13082 }
13083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013084
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013085 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13086 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13087 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13088 /* If the value is zero, assume it is uninitialized. */
13089 if (eep_config.max_dvc_qng == 0) {
13090 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13091 } else {
13092 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13093 }
13094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013095
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013096 /*
13097 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13098 * set 'max_dvc_qng' to 'max_host_qng'.
13099 */
13100 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13101 eep_config.max_dvc_qng = eep_config.max_host_qng;
13102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013103
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013104 /*
13105 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13106 * values based on possibly adjusted EEPROM values.
13107 */
13108 asc_dvc->max_host_qng = eep_config.max_host_qng;
13109 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013110
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013111 /*
13112 * If the EEPROM 'termination' field is set to automatic (0), then set
13113 * the ADV_DVC_CFG 'termination' field to automatic also.
13114 *
13115 * If the termination is specified with a non-zero 'termination'
13116 * value check that a legal value is set and set the ADV_DVC_CFG
13117 * 'termination' field appropriately.
13118 */
13119 if (eep_config.termination_se == 0) {
13120 termination = 0; /* auto termination for SE */
13121 } else {
13122 /* Enable manual control with low off / high off. */
13123 if (eep_config.termination_se == 1) {
13124 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013125
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013126 /* Enable manual control with low off / high on. */
13127 } else if (eep_config.termination_se == 2) {
13128 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013129
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013130 /* Enable manual control with low on / high on. */
13131 } else if (eep_config.termination_se == 3) {
13132 termination = TERM_SE;
13133 } else {
13134 /*
13135 * The EEPROM 'termination_se' field contains a bad value.
13136 * Use automatic termination instead.
13137 */
13138 termination = 0;
13139 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13140 }
13141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013142
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013143 if (eep_config.termination_lvd == 0) {
13144 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13145 } else {
13146 /* Enable manual control with low off / high off. */
13147 if (eep_config.termination_lvd == 1) {
13148 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013149
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013150 /* Enable manual control with low off / high on. */
13151 } else if (eep_config.termination_lvd == 2) {
13152 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013153
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013154 /* Enable manual control with low on / high on. */
13155 } else if (eep_config.termination_lvd == 3) {
13156 asc_dvc->cfg->termination = termination | TERM_LVD;
13157 } else {
13158 /*
13159 * The EEPROM 'termination_lvd' field contains a bad value.
13160 * Use automatic termination instead.
13161 */
13162 asc_dvc->cfg->termination = termination;
13163 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13164 }
13165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013166
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013167 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013168}
13169
13170/*
13171 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13172 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13173 * all of this is done.
13174 *
13175 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13176 *
13177 * For a non-fatal error return a warning code. If there are no warnings
13178 * then 0 is returned.
13179 *
13180 * Note: Chip is stopped on entry.
13181 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013182static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013183{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013184 AdvPortAddr iop_base;
13185 ushort warn_code;
13186 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013187 uchar tid, termination;
13188 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013189
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013190 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013191
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013192 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013193
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013194 /*
13195 * Read the board's EEPROM configuration.
13196 *
13197 * Set default values if a bad checksum is found.
13198 */
13199 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13200 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013201 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013202 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013203
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013204 /*
13205 * Set EEPROM default values.
13206 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013207 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13208 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013209
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013210 if (PCI_FUNC(pdev->devfn) != 0) {
13211 u8 ints;
13212 /*
13213 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13214 * and old Mac system booting problem. The Expansion
13215 * ROM must be disabled in Function 1 for these systems
13216 */
13217 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13218 /*
13219 * Clear the INTAB (bit 11) if the GPIO 0 input
13220 * indicates the Function 1 interrupt line is wired
13221 * to INTB.
13222 *
13223 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13224 * 1 - Function 1 interrupt line wired to INT A.
13225 * 0 - Function 1 interrupt line wired to INT B.
13226 *
13227 * Note: Function 0 is always wired to INTA.
13228 * Put all 5 GPIO bits in input mode and then read
13229 * their input values.
13230 */
13231 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13232 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13233 if ((ints & 0x01) == 0)
13234 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013235 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013236
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013237 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013238 * Assume the 6 byte board serial number that was read from
13239 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013240 */
13241 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013242 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013243 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013244 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013245 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013246 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013247
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013248 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013250
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013251 /*
13252 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13253 * EEPROM configuration that was read.
13254 *
13255 * This is the mapping of EEPROM fields to Adv Library fields.
13256 */
13257 asc_dvc->wdtr_able = eep_config.wdtr_able;
13258 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13259 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13260 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13261 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13262 asc_dvc->ppr_able = 0;
13263 asc_dvc->tagqng_able = eep_config.tagqng_able;
13264 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13265 asc_dvc->max_host_qng = eep_config.max_host_qng;
13266 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13267 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13268 asc_dvc->start_motor = eep_config.start_motor;
13269 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13270 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13271 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013272
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013273 /*
13274 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13275 * are set, then set an 'sdtr_able' bit for it.
13276 */
13277 asc_dvc->sdtr_able = 0;
13278 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13279 if (tid == 0) {
13280 sdtr_speed = asc_dvc->sdtr_speed1;
13281 } else if (tid == 4) {
13282 sdtr_speed = asc_dvc->sdtr_speed2;
13283 } else if (tid == 8) {
13284 sdtr_speed = asc_dvc->sdtr_speed3;
13285 } else if (tid == 12) {
13286 sdtr_speed = asc_dvc->sdtr_speed4;
13287 }
13288 if (sdtr_speed & ASC_MAX_TID) {
13289 asc_dvc->sdtr_able |= (1 << tid);
13290 }
13291 sdtr_speed >>= 4;
13292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013293
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013294 /*
13295 * Set the host maximum queuing (max. 253, min. 16) and the per device
13296 * maximum queuing (max. 63, min. 4).
13297 */
13298 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13299 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13300 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13301 /* If the value is zero, assume it is uninitialized. */
13302 if (eep_config.max_host_qng == 0) {
13303 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13304 } else {
13305 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13306 }
13307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013308
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013309 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13310 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13311 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13312 /* If the value is zero, assume it is uninitialized. */
13313 if (eep_config.max_dvc_qng == 0) {
13314 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13315 } else {
13316 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13317 }
13318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013319
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013320 /*
13321 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13322 * set 'max_dvc_qng' to 'max_host_qng'.
13323 */
13324 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13325 eep_config.max_dvc_qng = eep_config.max_host_qng;
13326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013327
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013328 /*
13329 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13330 * values based on possibly adjusted EEPROM values.
13331 */
13332 asc_dvc->max_host_qng = eep_config.max_host_qng;
13333 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013334
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013335 /*
13336 * If the EEPROM 'termination' field is set to automatic (0), then set
13337 * the ASC_DVC_CFG 'termination' field to automatic also.
13338 *
13339 * If the termination is specified with a non-zero 'termination'
13340 * value check that a legal value is set and set the ASC_DVC_CFG
13341 * 'termination' field appropriately.
13342 */
13343 if (eep_config.termination_se == 0) {
13344 termination = 0; /* auto termination for SE */
13345 } else {
13346 /* Enable manual control with low off / high off. */
13347 if (eep_config.termination_se == 1) {
13348 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013349
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013350 /* Enable manual control with low off / high on. */
13351 } else if (eep_config.termination_se == 2) {
13352 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013353
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013354 /* Enable manual control with low on / high on. */
13355 } else if (eep_config.termination_se == 3) {
13356 termination = TERM_SE;
13357 } else {
13358 /*
13359 * The EEPROM 'termination_se' field contains a bad value.
13360 * Use automatic termination instead.
13361 */
13362 termination = 0;
13363 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13364 }
13365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013366
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013367 if (eep_config.termination_lvd == 0) {
13368 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13369 } else {
13370 /* Enable manual control with low off / high off. */
13371 if (eep_config.termination_lvd == 1) {
13372 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013373
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013374 /* Enable manual control with low off / high on. */
13375 } else if (eep_config.termination_lvd == 2) {
13376 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013377
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013378 /* Enable manual control with low on / high on. */
13379 } else if (eep_config.termination_lvd == 3) {
13380 asc_dvc->cfg->termination = termination | TERM_LVD;
13381 } else {
13382 /*
13383 * The EEPROM 'termination_lvd' field contains a bad value.
13384 * Use automatic termination instead.
13385 */
13386 asc_dvc->cfg->termination = termination;
13387 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13388 }
13389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013390
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013391 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013392}
13393
13394/*
Matthew Wilcox51219352007-10-02 21:55:22 -040013395 * Initialize the ADV_DVC_VAR structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013396 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013397 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013398 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013399 * For a non-fatal error return a warning code. If there are no warnings
13400 * then 0 is returned.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013401 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013402static int __devinit
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013403AdvInitGetConfig(struct pci_dev *pdev, struct asc_board *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013404{
Matthew Wilcox51219352007-10-02 21:55:22 -040013405 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
13406 unsigned short warn_code = 0;
13407 AdvPortAddr iop_base = asc_dvc->iop_base;
13408 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013409 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013410
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013411 asc_dvc->err_code = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040013412
13413 /*
13414 * Save the state of the PCI Configuration Command Register
13415 * "Parity Error Response Control" Bit. If the bit is clear (0),
13416 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13417 * DMA parity errors.
13418 */
13419 asc_dvc->cfg->control_flag = 0;
13420 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
13421 if ((cmd & PCI_COMMAND_PARITY) == 0)
13422 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
13423
Matthew Wilcox51219352007-10-02 21:55:22 -040013424 asc_dvc->cfg->chip_version =
13425 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
13426
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013427 ASC_DBG(1, "iopb_chip_id_1: 0x%x 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -040013428 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13429 (ushort)ADV_CHIP_ID_BYTE);
13430
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013431 ASC_DBG(1, "iopw_chip_id_0: 0x%x 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -040013432 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13433 (ushort)ADV_CHIP_ID_WORD);
13434
13435 /*
13436 * Reset the chip to start and allow register writes.
13437 */
13438 if (AdvFindSignature(iop_base) == 0) {
13439 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13440 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013441 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013442 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013443 * The caller must set 'chip_type' to a valid setting.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013444 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013445 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13446 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13447 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13448 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13449 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013451
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013452 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013453 * Reset Chip.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013454 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013455 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13456 ADV_CTRL_REG_CMD_RESET);
13457 mdelay(100);
13458 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13459 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013460
Matthew Wilcox51219352007-10-02 21:55:22 -040013461 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13462 status = AdvInitFrom38C1600EEP(asc_dvc);
13463 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13464 status = AdvInitFrom38C0800EEP(asc_dvc);
13465 } else {
13466 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013467 }
Matthew Wilcox51219352007-10-02 21:55:22 -040013468 warn_code |= status;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013470
Matthew Wilcox51219352007-10-02 21:55:22 -040013471 if (warn_code != 0) {
13472 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
13473 boardp->id, warn_code);
13474 }
13475
13476 if (asc_dvc->err_code) {
13477 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
13478 boardp->id, asc_dvc->err_code);
13479 }
13480
13481 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013482}
Matthew Wilcox51219352007-10-02 21:55:22 -040013483#endif
13484
13485static struct scsi_host_template advansys_template = {
13486 .proc_name = DRV_NAME,
13487#ifdef CONFIG_PROC_FS
13488 .proc_info = advansys_proc_info,
13489#endif
13490 .name = DRV_NAME,
13491 .info = advansys_info,
13492 .queuecommand = advansys_queuecommand,
13493 .eh_bus_reset_handler = advansys_reset,
13494 .bios_param = advansys_biosparam,
13495 .slave_configure = advansys_slave_configure,
13496 /*
13497 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
13498 * must be set. The flag will be cleared in advansys_board_found
13499 * for non-ISA adapters.
13500 */
13501 .unchecked_isa_dma = 1,
13502 /*
13503 * All adapters controlled by this driver are capable of large
13504 * scatter-gather lists. According to the mid-level SCSI documentation
13505 * this obviates any performance gain provided by setting
13506 * 'use_clustering'. But empirically while CPU utilization is increased
13507 * by enabling clustering, I/O throughput increases as well.
13508 */
13509 .use_clustering = ENABLE_CLUSTERING,
13510};
Linus Torvalds1da177e2005-04-16 15:20:36 -070013511
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013512static int __devinit
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013513advansys_wide_init_chip(struct asc_board *boardp, ADV_DVC_VAR *adv_dvc_varp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013514{
13515 int req_cnt = 0;
13516 adv_req_t *reqp = NULL;
13517 int sg_cnt = 0;
13518 adv_sgblk_t *sgp;
13519 int warn_code, err_code;
13520
13521 /*
13522 * Allocate buffer carrier structures. The total size
13523 * is about 4 KB, so allocate all at once.
13524 */
13525 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013526 ASC_DBG(1, "carrp 0x%p\n", boardp->carrp);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013527
13528 if (!boardp->carrp)
13529 goto kmalloc_failed;
13530
13531 /*
13532 * Allocate up to 'max_host_qng' request structures for the Wide
13533 * board. The total size is about 16 KB, so allocate all at once.
13534 * If the allocation fails decrement and try again.
13535 */
13536 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
13537 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
13538
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013539 ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt,
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013540 (ulong)sizeof(adv_req_t) * req_cnt);
13541
13542 if (reqp)
13543 break;
13544 }
13545
13546 if (!reqp)
13547 goto kmalloc_failed;
13548
13549 boardp->orig_reqp = reqp;
13550
13551 /*
13552 * Allocate up to ADV_TOT_SG_BLOCK request structures for
13553 * the Wide board. Each structure is about 136 bytes.
13554 */
13555 boardp->adv_sgblkp = NULL;
13556 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
13557 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
13558
13559 if (!sgp)
13560 break;
13561
13562 sgp->next_sgblkp = boardp->adv_sgblkp;
13563 boardp->adv_sgblkp = sgp;
13564
13565 }
13566
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013567 ASC_DBG(1, "sg_cnt %d * %u = %u bytes\n", sg_cnt, sizeof(adv_sgblk_t),
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013568 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
13569
13570 if (!boardp->adv_sgblkp)
13571 goto kmalloc_failed;
13572
13573 adv_dvc_varp->carrier_buf = boardp->carrp;
13574
13575 /*
13576 * Point 'adv_reqp' to the request structures and
13577 * link them together.
13578 */
13579 req_cnt--;
13580 reqp[req_cnt].next_reqp = NULL;
13581 for (; req_cnt > 0; req_cnt--) {
13582 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
13583 }
13584 boardp->adv_reqp = &reqp[0];
13585
13586 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013587 ASC_DBG(2, "AdvInitAsc3550Driver()\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013588 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
13589 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013590 ASC_DBG(2, "AdvInitAsc38C0800Driver()\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013591 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
13592 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013593 ASC_DBG(2, "AdvInitAsc38C1600Driver()\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013594 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
13595 }
13596 err_code = adv_dvc_varp->err_code;
13597
13598 if (warn_code || err_code) {
13599 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
13600 " error 0x%x\n", boardp->id, warn_code, err_code);
13601 }
13602
13603 goto exit;
13604
13605 kmalloc_failed:
13606 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
13607 "failed\n", boardp->id);
13608 err_code = ADV_ERROR;
13609 exit:
13610 return err_code;
13611}
13612
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013613static void advansys_wide_free_mem(struct asc_board *boardp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013614{
13615 kfree(boardp->carrp);
13616 boardp->carrp = NULL;
13617 kfree(boardp->orig_reqp);
13618 boardp->orig_reqp = boardp->adv_reqp = NULL;
13619 while (boardp->adv_sgblkp) {
13620 adv_sgblk_t *sgp = boardp->adv_sgblkp;
13621 boardp->adv_sgblkp = sgp->next_sgblkp;
13622 kfree(sgp);
13623 }
13624}
13625
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013626static int __devinit advansys_board_found(struct Scsi_Host *shost,
13627 unsigned int iop, int bus_type)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013628{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013629 struct pci_dev *pdev;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013630 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013631 ASC_DVC_VAR *asc_dvc_varp = NULL;
13632 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013633 int share_irq, warn_code, ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013634
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013635 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013636 spin_lock_init(&boardp->lock);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013637 pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013638
13639 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013640 ASC_DBG(1, "narrow board\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013641 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
13642 asc_dvc_varp->bus_type = bus_type;
13643 asc_dvc_varp->drv_ptr = boardp;
13644 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
13645 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
13646 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013647 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013648#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013649 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
13650 adv_dvc_varp->drv_ptr = boardp;
13651 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013652 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013653 ASC_DBG(1, "wide board ASC-3550\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013654 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
13655 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013656 ASC_DBG(1, "wide board ASC-38C0800\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013657 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
13658 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013659 ASC_DBG(1, "wide board ASC-38C1600\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013660 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
13661 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013662
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013663 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
13664 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
13665 boardp->asc_n_io_port);
13666 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013667 ASC_PRINT3
13668 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013669 boardp->id, pci_resource_start(pdev, 1),
13670 boardp->asc_n_io_port);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013671 ret = -ENODEV;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013672 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013673 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013674 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr;
13675 ASC_DBG(1, "iop_base: 0x%p\n", adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013676
13677 /*
13678 * Even though it isn't used to access wide boards, other
13679 * than for the debug line below, save I/O Port address so
13680 * that it can be reported.
13681 */
13682 boardp->ioport = iop;
13683
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013684 ASC_DBG(1, "iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
13685 (ushort)inp(iop + 1), (ushort)inpw(iop));
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013686#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013687 }
13688
13689#ifdef CONFIG_PROC_FS
13690 /*
13691 * Allocate buffer for printing information from
13692 * /proc/scsi/advansys/[0...].
13693 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013694 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
13695 if (!boardp->prtbuf) {
13696 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
13697 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013698 ret = -ENOMEM;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013699 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013700 }
13701#endif /* CONFIG_PROC_FS */
13702
13703 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013704 /*
13705 * Set the board bus type and PCI IRQ before
13706 * calling AscInitGetConfig().
13707 */
13708 switch (asc_dvc_varp->bus_type) {
13709#ifdef CONFIG_ISA
13710 case ASC_IS_ISA:
13711 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013712 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013713 break;
13714 case ASC_IS_VL:
13715 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013716 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013717 break;
13718 case ASC_IS_EISA:
13719 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013720 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013721 break;
13722#endif /* CONFIG_ISA */
13723#ifdef CONFIG_PCI
13724 case ASC_IS_PCI:
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013725 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013726 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013727 break;
13728#endif /* CONFIG_PCI */
13729 default:
13730 ASC_PRINT2
13731 ("advansys_board_found: board %d: unknown adapter type: %d\n",
13732 boardp->id, asc_dvc_varp->bus_type);
13733 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013734 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013735 break;
13736 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013737
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013738 /*
13739 * NOTE: AscInitGetConfig() may change the board's
13740 * bus_type value. The bus_type value should no
13741 * longer be used. If the bus_type field must be
13742 * referenced only use the bit-wise AND operator "&".
13743 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013744 ASC_DBG(2, "AscInitGetConfig()\n");
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013745 ret = AscInitGetConfig(boardp) ? -ENODEV : 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013746 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013747#ifdef CONFIG_PCI
13748 /*
13749 * For Wide boards set PCI information before calling
13750 * AdvInitGetConfig().
13751 */
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013752 shost->unchecked_isa_dma = FALSE;
13753 share_irq = IRQF_SHARED;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013754 ASC_DBG(2, "AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040013755
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013756 ret = AdvInitGetConfig(pdev, boardp) ? -ENODEV : 0;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013757#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013758 }
13759
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013760 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013761 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013762
13763 /*
13764 * Save the EEPROM configuration so that it can be displayed
13765 * from /proc/scsi/advansys/[0...].
13766 */
13767 if (ASC_NARROW_BOARD(boardp)) {
13768
13769 ASCEEP_CONFIG *ep;
13770
13771 /*
13772 * Set the adapter's target id bit in the 'init_tidmask' field.
13773 */
13774 boardp->init_tidmask |=
13775 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
13776
13777 /*
13778 * Save EEPROM settings for the board.
13779 */
13780 ep = &boardp->eep_config.asc_eep;
13781
13782 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
13783 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
13784 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
13785 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
13786 ep->start_motor = asc_dvc_varp->start_motor;
13787 ep->cntl = asc_dvc_varp->dvc_cntl;
13788 ep->no_scam = asc_dvc_varp->no_scam;
13789 ep->max_total_qng = asc_dvc_varp->max_total_qng;
13790 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
13791 /* 'max_tag_qng' is set to the same value for every device. */
13792 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
13793 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
13794 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
13795 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
13796 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
13797 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
13798 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
13799
13800 /*
13801 * Modify board configuration.
13802 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013803 ASC_DBG(2, "AscInitSetConfig()\n");
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013804 ret = AscInitSetConfig(pdev, boardp) ? -ENODEV : 0;
13805 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013806 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013807 } else {
13808 ADVEEP_3550_CONFIG *ep_3550;
13809 ADVEEP_38C0800_CONFIG *ep_38C0800;
13810 ADVEEP_38C1600_CONFIG *ep_38C1600;
13811
13812 /*
13813 * Save Wide EEP Configuration Information.
13814 */
13815 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
13816 ep_3550 = &boardp->eep_config.adv_3550_eep;
13817
13818 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
13819 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
13820 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13821 ep_3550->termination = adv_dvc_varp->cfg->termination;
13822 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
13823 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
13824 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
13825 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
13826 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
13827 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
13828 ep_3550->start_motor = adv_dvc_varp->start_motor;
13829 ep_3550->scsi_reset_delay =
13830 adv_dvc_varp->scsi_reset_wait;
13831 ep_3550->serial_number_word1 =
13832 adv_dvc_varp->cfg->serial1;
13833 ep_3550->serial_number_word2 =
13834 adv_dvc_varp->cfg->serial2;
13835 ep_3550->serial_number_word3 =
13836 adv_dvc_varp->cfg->serial3;
13837 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
13838 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
13839
13840 ep_38C0800->adapter_scsi_id =
13841 adv_dvc_varp->chip_scsi_id;
13842 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
13843 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13844 ep_38C0800->termination_lvd =
13845 adv_dvc_varp->cfg->termination;
13846 ep_38C0800->disc_enable =
13847 adv_dvc_varp->cfg->disc_enable;
13848 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
13849 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
13850 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
13851 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
13852 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
13853 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
13854 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
13855 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
13856 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
13857 ep_38C0800->scsi_reset_delay =
13858 adv_dvc_varp->scsi_reset_wait;
13859 ep_38C0800->serial_number_word1 =
13860 adv_dvc_varp->cfg->serial1;
13861 ep_38C0800->serial_number_word2 =
13862 adv_dvc_varp->cfg->serial2;
13863 ep_38C0800->serial_number_word3 =
13864 adv_dvc_varp->cfg->serial3;
13865 } else {
13866 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
13867
13868 ep_38C1600->adapter_scsi_id =
13869 adv_dvc_varp->chip_scsi_id;
13870 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
13871 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13872 ep_38C1600->termination_lvd =
13873 adv_dvc_varp->cfg->termination;
13874 ep_38C1600->disc_enable =
13875 adv_dvc_varp->cfg->disc_enable;
13876 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
13877 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
13878 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
13879 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
13880 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
13881 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
13882 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
13883 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
13884 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
13885 ep_38C1600->scsi_reset_delay =
13886 adv_dvc_varp->scsi_reset_wait;
13887 ep_38C1600->serial_number_word1 =
13888 adv_dvc_varp->cfg->serial1;
13889 ep_38C1600->serial_number_word2 =
13890 adv_dvc_varp->cfg->serial2;
13891 ep_38C1600->serial_number_word3 =
13892 adv_dvc_varp->cfg->serial3;
13893 }
13894
13895 /*
13896 * Set the adapter's target id bit in the 'init_tidmask' field.
13897 */
13898 boardp->init_tidmask |=
13899 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013900 }
13901
13902 /*
13903 * Channels are numbered beginning with 0. For AdvanSys one host
13904 * structure supports one channel. Multi-channel boards have a
13905 * separate host structure for each channel.
13906 */
13907 shost->max_channel = 0;
13908 if (ASC_NARROW_BOARD(boardp)) {
13909 shost->max_id = ASC_MAX_TID + 1;
13910 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060013911 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013912
13913 shost->io_port = asc_dvc_varp->iop_base;
13914 boardp->asc_n_io_port = ASC_IOADR_GAP;
13915 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
13916
13917 /* Set maximum number of queues the adapter can handle. */
13918 shost->can_queue = asc_dvc_varp->max_total_qng;
13919 } else {
13920 shost->max_id = ADV_MAX_TID + 1;
13921 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060013922 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013923
13924 /*
13925 * Save the I/O Port address and length even though
13926 * I/O ports are not used to access Wide boards.
13927 * Instead the Wide boards are accessed with
13928 * PCI Memory Mapped I/O.
13929 */
13930 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013931
13932 shost->this_id = adv_dvc_varp->chip_scsi_id;
13933
13934 /* Set maximum number of queues the adapter can handle. */
13935 shost->can_queue = adv_dvc_varp->max_host_qng;
13936 }
13937
13938 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013939 * Following v1.3.89, 'cmd_per_lun' is no longer needed
13940 * and should be set to zero.
13941 *
13942 * But because of a bug introduced in v1.3.89 if the driver is
13943 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
13944 * SCSI function 'allocate_device' will panic. To allow the driver
13945 * to work as a module in these kernels set 'cmd_per_lun' to 1.
13946 *
13947 * Note: This is wrong. cmd_per_lun should be set to the depth
13948 * you want on untagged devices always.
13949 #ifdef MODULE
13950 */
13951 shost->cmd_per_lun = 1;
13952/* #else
13953 shost->cmd_per_lun = 0;
13954#endif */
13955
13956 /*
13957 * Set the maximum number of scatter-gather elements the
13958 * adapter can handle.
13959 */
13960 if (ASC_NARROW_BOARD(boardp)) {
13961 /*
13962 * Allow two commands with 'sg_tablesize' scatter-gather
13963 * elements to be executed simultaneously. This value is
13964 * the theoretical hardware limit. It may be decreased
13965 * below.
13966 */
13967 shost->sg_tablesize =
13968 (((asc_dvc_varp->max_total_qng - 2) / 2) *
13969 ASC_SG_LIST_PER_Q) + 1;
13970 } else {
13971 shost->sg_tablesize = ADV_MAX_SG_LIST;
13972 }
13973
13974 /*
13975 * The value of 'sg_tablesize' can not exceed the SCSI
13976 * mid-level driver definition of SG_ALL. SG_ALL also
13977 * must not be exceeded, because it is used to define the
13978 * size of the scatter-gather table in 'struct asc_sg_head'.
13979 */
13980 if (shost->sg_tablesize > SG_ALL) {
13981 shost->sg_tablesize = SG_ALL;
13982 }
13983
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013984 ASC_DBG(1, "sg_tablesize: %d\n", shost->sg_tablesize);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013985
13986 /* BIOS start address. */
13987 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013988 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
13989 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013990 } else {
13991 /*
13992 * Fill-in BIOS board variables. The Wide BIOS saves
13993 * information in LRAM that is used by the driver.
13994 */
13995 AdvReadWordLram(adv_dvc_varp->iop_base,
13996 BIOS_SIGNATURE, boardp->bios_signature);
13997 AdvReadWordLram(adv_dvc_varp->iop_base,
13998 BIOS_VERSION, boardp->bios_version);
13999 AdvReadWordLram(adv_dvc_varp->iop_base,
14000 BIOS_CODESEG, boardp->bios_codeseg);
14001 AdvReadWordLram(adv_dvc_varp->iop_base,
14002 BIOS_CODELEN, boardp->bios_codelen);
14003
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014004 ASC_DBG(1, "bios_signature 0x%x, bios_version 0x%x\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014005 boardp->bios_signature, boardp->bios_version);
14006
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014007 ASC_DBG(1, "bios_codeseg 0x%x, bios_codelen 0x%x\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014008 boardp->bios_codeseg, boardp->bios_codelen);
14009
14010 /*
14011 * If the BIOS saved a valid signature, then fill in
14012 * the BIOS code segment base address.
14013 */
14014 if (boardp->bios_signature == 0x55AA) {
14015 /*
14016 * Convert x86 realmode code segment to a linear
14017 * address by shifting left 4.
14018 */
14019 shost->base = ((ulong)boardp->bios_codeseg << 4);
14020 } else {
14021 shost->base = 0;
14022 }
14023 }
14024
14025 /*
14026 * Register Board Resources - I/O Port, DMA, IRQ
14027 */
14028
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014029 /* Register DMA Channel for Narrow boards. */
14030 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14031#ifdef CONFIG_ISA
14032 if (ASC_NARROW_BOARD(boardp)) {
14033 /* Register DMA channel for ISA bus. */
14034 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14035 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014036 ret = request_dma(shost->dma_channel, DRV_NAME);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014037 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014038 ASC_PRINT3
14039 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14040 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014041 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014042 }
14043 AscEnableIsaDma(shost->dma_channel);
14044 }
14045 }
14046#endif /* CONFIG_ISA */
14047
14048 /* Register IRQ Number. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014049 ASC_DBG(2, "request_irq(%d, %p)\n", boardp->irq, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014050
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014051 ret = request_irq(boardp->irq, advansys_interrupt, share_irq,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014052 DRV_NAME, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014053
14054 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014055 if (ret == -EBUSY) {
14056 ASC_PRINT2
14057 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014058 boardp->id, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014059 } else if (ret == -EINVAL) {
14060 ASC_PRINT2
14061 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014062 boardp->id, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014063 } else {
14064 ASC_PRINT3
14065 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014066 boardp->id, boardp->irq, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014067 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014068 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014069 }
14070
14071 /*
14072 * Initialize board RISC chip and enable interrupts.
14073 */
14074 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014075 ASC_DBG(2, "AscInitAsc1000Driver()\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014076 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014077
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014078 if (warn_code || asc_dvc_varp->err_code) {
14079 ASC_PRINT4("advansys_board_found: board %d error: "
14080 "init_state 0x%x, warn 0x%x, error 0x%x\n",
14081 boardp->id, asc_dvc_varp->init_state,
14082 warn_code, asc_dvc_varp->err_code);
14083 if (asc_dvc_varp->err_code)
14084 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014085 }
14086 } else {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014087 if (advansys_wide_init_chip(boardp, adv_dvc_varp))
14088 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014089 }
14090
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014091 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014092 goto err_free_wide_mem;
14093
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014094 ASC_DBG_PRT_SCSI_HOST(2, shost);
14095
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014096 ret = scsi_add_host(shost, boardp->dev);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014097 if (ret)
14098 goto err_free_wide_mem;
14099
14100 scsi_scan_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014101 return 0;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014102
14103 err_free_wide_mem:
14104 advansys_wide_free_mem(boardp);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014105 free_irq(boardp->irq, shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014106 err_free_dma:
14107 if (shost->dma_channel != NO_ISA_DMA)
14108 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014109 err_free_proc:
14110 kfree(boardp->prtbuf);
14111 err_unmap:
14112 if (boardp->ioremap_addr)
14113 iounmap(boardp->ioremap_addr);
14114 err_shost:
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014115 return ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014116}
14117
14118/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014119 * advansys_release()
14120 *
14121 * Release resources allocated for a single AdvanSys adapter.
14122 */
14123static int advansys_release(struct Scsi_Host *shost)
14124{
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014125 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014126 ASC_DBG(1, "begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014127 scsi_remove_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014128 free_irq(boardp->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014129 if (shost->dma_channel != NO_ISA_DMA) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014130 ASC_DBG(1, "free_dma()\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014131 free_dma(shost->dma_channel);
14132 }
Matthew Wilcox9a256fa2007-10-02 21:55:28 -040014133 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014134 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014135 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014136 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014137 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014138 scsi_host_put(shost);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014139 ASC_DBG(1, "end\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014140 return 0;
14141}
14142
Matthew Wilcox95c9f162007-09-09 08:56:39 -060014143#define ASC_IOADR_TABLE_MAX_IX 11
14144
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014145static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
14146 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
14147 0x0210, 0x0230, 0x0250, 0x0330
14148};
14149
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014150/*
14151 * The ISA IRQ number is found in bits 2 and 3 of the CfgLsw. It decodes as:
14152 * 00: 10
14153 * 01: 11
14154 * 10: 12
14155 * 11: 15
14156 */
14157static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
14158{
14159 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14160 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
14161 if (chip_irq == 13)
14162 chip_irq = 15;
14163 return chip_irq;
14164}
14165
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014166static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
14167{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014168 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014169 PortAddr iop_base = _asc_def_iop_base[id];
14170 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014171 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014172
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014173 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014174 ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014175 return -ENODEV;
14176 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014177 ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014178 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014179 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014180 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014181 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014182
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014183 err = -ENOMEM;
14184 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014185 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014186 goto release_region;
14187
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014188 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014189 board->irq = advansys_isa_irq_no(iop_base);
14190 board->dev = dev;
14191
14192 err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
14193 if (err)
14194 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014195
14196 dev_set_drvdata(dev, shost);
14197 return 0;
14198
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014199 free_host:
14200 scsi_host_put(shost);
14201 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014202 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014203 return err;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014204}
14205
14206static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
14207{
Matthew Wilcox71f36112007-07-30 08:04:53 -060014208 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014209 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014210 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014211 return 0;
14212}
14213
14214static struct isa_driver advansys_isa_driver = {
14215 .probe = advansys_isa_probe,
14216 .remove = __devexit_p(advansys_isa_remove),
14217 .driver = {
14218 .owner = THIS_MODULE,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014219 .name = DRV_NAME,
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014220 },
14221};
14222
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014223/*
14224 * The VLB IRQ number is found in bits 2 to 4 of the CfgLsw. It decodes as:
14225 * 000: invalid
14226 * 001: 10
14227 * 010: 11
14228 * 011: 12
14229 * 100: invalid
14230 * 101: 14
14231 * 110: 15
14232 * 111: invalid
14233 */
14234static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
14235{
14236 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14237 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
14238 if ((chip_irq < 10) || (chip_irq == 13) || (chip_irq > 15))
14239 return 0;
14240 return chip_irq;
14241}
14242
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014243static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
14244{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014245 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014246 PortAddr iop_base = _asc_def_iop_base[id];
14247 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014248 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014249
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014250 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014251 ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014252 return -ENODEV;
14253 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014254 ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014255 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014256 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014257 /*
14258 * I don't think this condition can actually happen, but the old
14259 * driver did it, and the chances of finding a VLB setup in 2007
14260 * to do testing with is slight to none.
14261 */
14262 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014263 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014264
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014265 err = -ENOMEM;
14266 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014267 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014268 goto release_region;
14269
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014270 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014271 board->irq = advansys_vlb_irq_no(iop_base);
14272 board->dev = dev;
14273
14274 err = advansys_board_found(shost, iop_base, ASC_IS_VL);
14275 if (err)
14276 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014277
14278 dev_set_drvdata(dev, shost);
14279 return 0;
14280
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014281 free_host:
14282 scsi_host_put(shost);
14283 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014284 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014285 return -ENODEV;
14286}
14287
14288static struct isa_driver advansys_vlb_driver = {
14289 .probe = advansys_vlb_probe,
14290 .remove = __devexit_p(advansys_isa_remove),
14291 .driver = {
14292 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060014293 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014294 },
14295};
14296
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014297static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
14298 { "ABP7401" },
14299 { "ABP7501" },
14300 { "" }
14301};
14302
14303MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
14304
14305/*
14306 * EISA is a little more tricky than PCI; each EISA device may have two
14307 * channels, and this driver is written to make each channel its own Scsi_Host
14308 */
14309struct eisa_scsi_data {
14310 struct Scsi_Host *host[2];
14311};
14312
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014313/*
14314 * The EISA IRQ number is found in bits 8 to 10 of the CfgLsw. It decodes as:
14315 * 000: 10
14316 * 001: 11
14317 * 010: 12
14318 * 011: invalid
14319 * 100: 14
14320 * 101: 15
14321 * 110: invalid
14322 * 111: invalid
14323 */
14324static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
14325{
14326 unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
14327 unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
14328 if ((chip_irq == 13) || (chip_irq > 15))
14329 return 0;
14330 return chip_irq;
14331}
14332
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014333static int __devinit advansys_eisa_probe(struct device *dev)
14334{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014335 int i, ioport, irq = 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014336 int err;
14337 struct eisa_device *edev = to_eisa_device(dev);
14338 struct eisa_scsi_data *data;
14339
14340 err = -ENOMEM;
14341 data = kzalloc(sizeof(*data), GFP_KERNEL);
14342 if (!data)
14343 goto fail;
14344 ioport = edev->base_addr + 0xc30;
14345
14346 err = -ENODEV;
14347 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014348 struct asc_board *board;
14349 struct Scsi_Host *shost;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014350 if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014351 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
14352 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014353 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014354 }
14355 if (!AscFindSignature(ioport)) {
14356 release_region(ioport, ASC_IOADR_GAP);
14357 continue;
14358 }
14359
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014360 /*
14361 * I don't know why we need to do this for EISA chips, but
14362 * not for any others. It looks to be equivalent to
14363 * AscGetChipCfgMsw, but I may have overlooked something,
14364 * so I'm not converting it until I get an EISA board to
14365 * test with.
14366 */
14367 inw(ioport + 4);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014368
14369 if (!irq)
14370 irq = advansys_eisa_irq_no(edev);
14371
14372 err = -ENOMEM;
14373 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
14374 if (!shost)
14375 goto release_region;
14376
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014377 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014378 board->irq = irq;
14379 board->dev = dev;
14380
14381 err = advansys_board_found(shost, ioport, ASC_IS_EISA);
14382 if (!err) {
14383 data->host[i] = shost;
14384 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014385 }
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014386
14387 scsi_host_put(shost);
14388 release_region:
14389 release_region(ioport, ASC_IOADR_GAP);
14390 break;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014391 }
14392
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014393 if (err)
14394 goto free_data;
14395 dev_set_drvdata(dev, data);
14396 return 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014397
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014398 free_data:
14399 kfree(data->host[0]);
14400 kfree(data->host[1]);
14401 kfree(data);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014402 fail:
14403 return err;
14404}
14405
14406static __devexit int advansys_eisa_remove(struct device *dev)
14407{
14408 int i;
14409 struct eisa_scsi_data *data = dev_get_drvdata(dev);
14410
14411 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014412 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014413 struct Scsi_Host *shost = data->host[i];
14414 if (!shost)
14415 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014416 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014417 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014418 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014419 }
14420
14421 kfree(data);
14422 return 0;
14423}
14424
14425static struct eisa_driver advansys_eisa_driver = {
14426 .id_table = advansys_eisa_table,
14427 .driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014428 .name = DRV_NAME,
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014429 .probe = advansys_eisa_probe,
14430 .remove = __devexit_p(advansys_eisa_remove),
14431 }
14432};
14433
Dave Jones2672ea82006-08-02 17:11:49 -040014434/* PCI Devices supported by this driver */
14435static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014436 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
14437 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14438 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
14439 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14440 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
14441 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14442 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
14443 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14444 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
14445 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14446 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
14447 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14448 {}
Dave Jones2672ea82006-08-02 17:11:49 -040014449};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014450
Dave Jones2672ea82006-08-02 17:11:49 -040014451MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014452
Matthew Wilcox9649af32007-07-26 21:51:47 -060014453static void __devinit advansys_set_latency(struct pci_dev *pdev)
14454{
14455 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
14456 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
14457 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
14458 } else {
14459 u8 latency;
14460 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
14461 if (latency < 0x20)
14462 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
14463 }
14464}
14465
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014466static int __devinit
14467advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14468{
14469 int err, ioport;
14470 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014471 struct asc_board *board;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014472
14473 err = pci_enable_device(pdev);
14474 if (err)
14475 goto fail;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014476 err = pci_request_regions(pdev, DRV_NAME);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014477 if (err)
14478 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060014479 pci_set_master(pdev);
14480 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014481
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014482 err = -ENODEV;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014483 if (pci_resource_len(pdev, 0) == 0)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014484 goto release_region;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014485
14486 ioport = pci_resource_start(pdev, 0);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014487
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014488 err = -ENOMEM;
14489 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014490 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014491 goto release_region;
14492
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014493 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014494 board->irq = pdev->irq;
14495 board->dev = &pdev->dev;
14496
14497 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14498 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14499 pdev->device == PCI_DEVICE_ID_38C1600_REV1) {
14500 board->flags |= ASC_IS_WIDE_BOARD;
14501 }
14502
14503 err = advansys_board_found(shost, ioport, ASC_IS_PCI);
14504 if (err)
14505 goto free_host;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014506
14507 pci_set_drvdata(pdev, shost);
14508 return 0;
14509
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014510 free_host:
14511 scsi_host_put(shost);
14512 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014513 pci_release_regions(pdev);
14514 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014515 pci_disable_device(pdev);
14516 fail:
14517 return err;
14518}
14519
14520static void __devexit advansys_pci_remove(struct pci_dev *pdev)
14521{
14522 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014523 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014524 pci_disable_device(pdev);
14525}
14526
14527static struct pci_driver advansys_pci_driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014528 .name = DRV_NAME,
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014529 .id_table = advansys_pci_tbl,
14530 .probe = advansys_pci_probe,
14531 .remove = __devexit_p(advansys_pci_remove),
14532};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014533
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014534static int __init advansys_init(void)
14535{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014536 int error;
14537
14538 error = isa_register_driver(&advansys_isa_driver,
14539 ASC_IOADR_TABLE_MAX_IX);
14540 if (error)
14541 goto fail;
14542
14543 error = isa_register_driver(&advansys_vlb_driver,
14544 ASC_IOADR_TABLE_MAX_IX);
14545 if (error)
14546 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014547
14548 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014549 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014550 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014551
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014552 error = pci_register_driver(&advansys_pci_driver);
14553 if (error)
14554 goto unregister_eisa;
14555
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014556 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014557
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014558 unregister_eisa:
14559 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014560 unregister_vlb:
14561 isa_unregister_driver(&advansys_vlb_driver);
14562 unregister_isa:
14563 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014564 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014565 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014566}
14567
14568static void __exit advansys_exit(void)
14569{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014570 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014571 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014572 isa_unregister_driver(&advansys_vlb_driver);
14573 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014574}
14575
14576module_init(advansys_init);
14577module_exit(advansys_exit);
14578
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014579MODULE_LICENSE("GPL");