blob: a4091ab8d363d765519ff0efdb3c25adb39026fd [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 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002442 /* /proc/scsi/advansys/[0...] */
2443 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002445 struct asc_stats asc_stats; /* Board statistics */
2446#endif /* ADVANSYS_STATS */
2447 /*
2448 * The following fields are used only for Narrow Boards.
2449 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002450 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2451 /*
2452 * The following fields are used only for Wide Boards.
2453 */
2454 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2455 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002456 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002457 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2458 adv_req_t *adv_reqp; /* Request structures. */
2459 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2460 ushort bios_signature; /* BIOS Signature. */
2461 ushort bios_version; /* BIOS Version. */
2462 ushort bios_codeseg; /* BIOS Code Segment. */
2463 ushort bios_codelen; /* BIOS Code Segment Length. */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002464};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002466#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2467 dvc_var.adv_dvc_var)
2468#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2469
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002471static int asc_board_count;
2472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002474static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002477static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002480 * asc_prt_asc_dvc_var()
2481 */
2482static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
2483{
2484 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
2485
2486 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
2487 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
2488
2489 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
2490 (unsigned)h->init_sdtr);
2491
2492 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
2493 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
2494 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
2495 (unsigned)h->chip_no);
2496
2497 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
2498 "%u,\n", (unsigned)h->queue_full_or_busy,
2499 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
2500
2501 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
2502 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
2503 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
2504 (unsigned)h->in_critical_cnt);
2505
2506 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
2507 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
2508 (unsigned)h->init_state, (unsigned)h->no_scam,
2509 (unsigned)h->pci_fix_asyn_xfer);
2510
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002511 printk(" cfg 0x%lx\n", (ulong)h->cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002512}
2513
2514/*
2515 * asc_prt_asc_dvc_cfg()
2516 */
2517static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
2518{
2519 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
2520
2521 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
2522 h->can_tagged_qng, h->cmd_qng_enabled);
2523 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
2524 h->disc_enable, h->sdtr_enable);
2525
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04002526 printk(" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, "
2527 "chip_version %d,\n", h->chip_scsi_id, h->isa_dma_speed,
2528 h->isa_dma_channel, h->chip_version);
Matthew Wilcox51219352007-10-02 21:55:22 -04002529
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002530 printk(" mcode_date 0x%x, mcode_version %d, overrun_buf 0x%p\n",
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04002531 h->mcode_date, h->mcode_version, h->overrun_buf);
Matthew Wilcox51219352007-10-02 21:55:22 -04002532}
2533
2534/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002535 * asc_prt_adv_dvc_var()
2536 *
2537 * Display an ADV_DVC_VAR structure.
2538 */
2539static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
2540{
2541 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
2542
2543 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
2544 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
2545
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002546 printk(" sdtr_able 0x%x, wdtr_able 0x%x\n",
2547 (unsigned)h->sdtr_able, (unsigned)h->wdtr_able);
Matthew Wilcox51219352007-10-02 21:55:22 -04002548
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002549 printk(" start_motor 0x%x, scsi_reset_wait 0x%x\n",
2550 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Matthew Wilcox51219352007-10-02 21:55:22 -04002551
2552 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
2553 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
2554 (ulong)h->carr_freelist);
2555
2556 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
2557 (ulong)h->icq_sp, (ulong)h->irq_sp);
2558
2559 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
2560 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
2561
2562 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
2563 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
2564}
2565
2566/*
2567 * asc_prt_adv_dvc_cfg()
2568 *
2569 * Display an ADV_DVC_CFG structure.
2570 */
2571static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
2572{
2573 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
2574
2575 printk(" disc_enable 0x%x, termination 0x%x\n",
2576 h->disc_enable, h->termination);
2577
2578 printk(" chip_version 0x%x, mcode_date 0x%x\n",
2579 h->chip_version, h->mcode_date);
2580
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002581 printk(" mcode_version 0x%x, control_flag 0x%x\n",
2582 h->mcode_version, h->control_flag);
Matthew Wilcox51219352007-10-02 21:55:22 -04002583}
2584
2585/*
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002586 * asc_prt_scsi_host()
Matthew Wilcox51219352007-10-02 21:55:22 -04002587 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002588static void asc_prt_scsi_host(struct Scsi_Host *s)
Matthew Wilcox51219352007-10-02 21:55:22 -04002589{
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002590 struct asc_board *boardp = shost_priv(s);
Matthew Wilcox51219352007-10-02 21:55:22 -04002591
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002592 printk("Scsi_Host at addr 0x%p, device %s\n", s, boardp->dev->bus_id);
2593 printk(" host_busy %u, host_no %d, last_reset %d,\n",
2594 s->host_busy, s->host_no, (unsigned)s->last_reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04002595
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002596 printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
2597 (ulong)s->base, (ulong)s->io_port, boardp->irq);
Matthew Wilcox51219352007-10-02 21:55:22 -04002598
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002599 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
2600 s->dma_channel, s->this_id, s->can_queue);
Matthew Wilcox51219352007-10-02 21:55:22 -04002601
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002602 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
2603 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Matthew Wilcox51219352007-10-02 21:55:22 -04002604
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002605 if (ASC_NARROW_BOARD(boardp)) {
2606 asc_prt_asc_dvc_var(&boardp->dvc_var.asc_dvc_var);
2607 asc_prt_asc_dvc_cfg(&boardp->dvc_cfg.asc_dvc_cfg);
2608 } else {
2609 asc_prt_adv_dvc_var(&boardp->dvc_var.adv_dvc_var);
2610 asc_prt_adv_dvc_cfg(&boardp->dvc_cfg.adv_dvc_cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002611 }
2612}
2613
2614/*
2615 * asc_prt_hex()
2616 *
2617 * Print hexadecimal output in 4 byte groupings 32 bytes
2618 * or 8 double-words per line.
2619 */
2620static void asc_prt_hex(char *f, uchar *s, int l)
2621{
2622 int i;
2623 int j;
2624 int k;
2625 int m;
2626
2627 printk("%s: (%d bytes)\n", f, l);
2628
2629 for (i = 0; i < l; i += 32) {
2630
2631 /* Display a maximum of 8 double-words per line. */
2632 if ((k = (l - i) / 4) >= 8) {
2633 k = 8;
2634 m = 0;
2635 } else {
2636 m = (l - i) % 4;
2637 }
2638
2639 for (j = 0; j < k; j++) {
2640 printk(" %2.2X%2.2X%2.2X%2.2X",
2641 (unsigned)s[i + (j * 4)],
2642 (unsigned)s[i + (j * 4) + 1],
2643 (unsigned)s[i + (j * 4) + 2],
2644 (unsigned)s[i + (j * 4) + 3]);
2645 }
2646
2647 switch (m) {
2648 case 0:
2649 default:
2650 break;
2651 case 1:
2652 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
2653 break;
2654 case 2:
2655 printk(" %2.2X%2.2X",
2656 (unsigned)s[i + (j * 4)],
2657 (unsigned)s[i + (j * 4) + 1]);
2658 break;
2659 case 3:
2660 printk(" %2.2X%2.2X%2.2X",
2661 (unsigned)s[i + (j * 4) + 1],
2662 (unsigned)s[i + (j * 4) + 2],
2663 (unsigned)s[i + (j * 4) + 3]);
2664 break;
2665 }
2666
2667 printk("\n");
2668 }
2669}
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002670
2671/*
2672 * asc_prt_asc_scsi_q()
2673 */
2674static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
2675{
2676 ASC_SG_HEAD *sgp;
2677 int i;
2678
2679 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
2680
2681 printk
2682 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
2683 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
2684 q->q2.tag_code);
2685
2686 printk
2687 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2688 (ulong)le32_to_cpu(q->q1.data_addr),
2689 (ulong)le32_to_cpu(q->q1.data_cnt),
2690 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
2691
2692 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
2693 (ulong)q->cdbptr, q->q2.cdb_len,
2694 (ulong)q->sg_head, q->q1.sg_queue_cnt);
2695
2696 if (q->sg_head) {
2697 sgp = q->sg_head;
2698 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
2699 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
2700 sgp->queue_cnt);
2701 for (i = 0; i < sgp->entry_cnt; i++) {
2702 printk(" [%u]: addr 0x%lx, bytes %lu\n",
2703 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
2704 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
2705 }
2706
2707 }
2708}
2709
2710/*
2711 * asc_prt_asc_qdone_info()
2712 */
2713static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
2714{
2715 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
2716 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
2717 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
2718 q->d2.tag_code);
2719 printk
2720 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
2721 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
2722}
2723
2724/*
2725 * asc_prt_adv_sgblock()
2726 *
2727 * Display an ADV_SG_BLOCK structure.
2728 */
2729static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
2730{
2731 int i;
2732
2733 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
2734 (ulong)b, sgblockno);
2735 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
2736 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
2737 BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
2738 if (b->sg_ptr != 0)
2739 BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
2740 for (i = 0; i < b->sg_cnt; i++) {
2741 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
2742 i, (ulong)b->sg_list[i].sg_addr,
2743 (ulong)b->sg_list[i].sg_count);
2744 }
2745}
2746
2747/*
2748 * asc_prt_adv_scsi_req_q()
2749 *
2750 * Display an ADV_SCSI_REQ_Q structure.
2751 */
2752static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
2753{
2754 int sg_blk_cnt;
2755 struct asc_sg_block *sg_ptr;
2756
2757 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
2758
2759 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
2760 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
2761
2762 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
2763 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
2764
2765 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2766 (ulong)le32_to_cpu(q->data_cnt),
2767 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
2768
2769 printk
2770 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
2771 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
2772
2773 printk(" sg_working_ix 0x%x, target_cmd %u\n",
2774 q->sg_working_ix, q->target_cmd);
2775
2776 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
2777 (ulong)le32_to_cpu(q->scsiq_rptr),
2778 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
2779
2780 /* Display the request's ADV_SG_BLOCK structures. */
2781 if (q->sg_list_ptr != NULL) {
2782 sg_blk_cnt = 0;
2783 while (1) {
2784 /*
2785 * 'sg_ptr' is a physical address. Convert it to a virtual
2786 * address by indexing 'sg_blk_cnt' into the virtual address
2787 * array 'sg_list_ptr'.
2788 *
2789 * XXX - Assumes all SG physical blocks are virtually contiguous.
2790 */
2791 sg_ptr =
2792 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
2793 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
2794 if (sg_ptr->sg_ptr == 0) {
2795 break;
2796 }
2797 sg_blk_cnt++;
2798 }
2799 }
2800}
Matthew Wilcox51219352007-10-02 21:55:22 -04002801#endif /* ADVANSYS_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
2803/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 * advansys_info()
2805 *
2806 * Return suitable for printing on the console with the argument
2807 * adapter's configuration information.
2808 *
2809 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
2810 * otherwise the static 'info' array will be overrun.
2811 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002812static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002814 static char info[ASC_INFO_SIZE];
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002815 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002816 ASC_DVC_VAR *asc_dvc_varp;
2817 ADV_DVC_VAR *adv_dvc_varp;
2818 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002819 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002821 if (ASC_NARROW_BOARD(boardp)) {
2822 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002823 ASC_DBG(1, "begin\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002824 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
2825 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
2826 ASC_IS_ISAPNP) {
2827 busname = "ISA PnP";
2828 } else {
2829 busname = "ISA";
2830 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002831 sprintf(info,
2832 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
2833 ASC_VERSION, busname,
2834 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002835 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002836 boardp->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002837 } else {
2838 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
2839 busname = "VL";
2840 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
2841 busname = "EISA";
2842 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
2843 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
2844 == ASC_IS_PCI_ULTRA) {
2845 busname = "PCI Ultra";
2846 } else {
2847 busname = "PCI";
2848 }
2849 } else {
2850 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002851 ASC_PRINT2("advansys_info: board %d: unknown "
2852 "bus type %d\n", boardp->id,
2853 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002854 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002855 sprintf(info,
2856 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002857 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002858 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002859 boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002860 }
2861 } else {
2862 /*
2863 * Wide Adapter Information
2864 *
2865 * Memory-mapped I/O is used instead of I/O space to access
2866 * the adapter, but display the I/O Port range. The Memory
2867 * I/O address is displayed through the driver /proc file.
2868 */
2869 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
2870 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002871 widename = "Ultra-Wide";
2872 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002873 widename = "Ultra2-Wide";
2874 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002875 widename = "Ultra3-Wide";
2876 }
2877 sprintf(info,
2878 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
2879 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002880 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002881 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002882 BUG_ON(strlen(info) >= ASC_INFO_SIZE);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04002883 ASC_DBG(1, "end\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002884 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885}
2886
Matthew Wilcox51219352007-10-02 21:55:22 -04002887#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002889 * asc_prt_line()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 *
Matthew Wilcox51219352007-10-02 21:55:22 -04002891 * If 'cp' is NULL print to the console, otherwise print to a buffer.
2892 *
2893 * Return 0 if printing to the console, otherwise return the number of
2894 * bytes written to the buffer.
2895 *
2896 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
2897 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 */
Matthew Wilcox51219352007-10-02 21:55:22 -04002899static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900{
Matthew Wilcox51219352007-10-02 21:55:22 -04002901 va_list args;
2902 int ret;
2903 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
Matthew Wilcox51219352007-10-02 21:55:22 -04002905 va_start(args, fmt);
2906 ret = vsprintf(s, fmt, args);
2907 BUG_ON(ret >= ASC_PRTLINE_SIZE);
2908 if (buf == NULL) {
2909 (void)printk(s);
2910 ret = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002911 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04002912 ret = min(buflen, ret);
2913 memcpy(buf, s, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002914 }
Matthew Wilcox51219352007-10-02 21:55:22 -04002915 va_end(args);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002916 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917}
2918
2919/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 * asc_prt_board_devices()
2921 *
2922 * Print driver information for devices attached to the board.
2923 *
2924 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
2925 * cf. asc_prt_line().
2926 *
2927 * Return the number of characters copied into 'cp'. No more than
2928 * 'cplen' characters will be copied to 'cp'.
2929 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002930static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002932 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002933 int leftlen;
2934 int totlen;
2935 int len;
2936 int chip_scsi_id;
2937 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002939 leftlen = cplen;
2940 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002942 len = asc_prt_line(cp, leftlen,
2943 "\nDevice Information for AdvanSys SCSI Host %d:\n",
2944 shost->host_no);
2945 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002947 if (ASC_NARROW_BOARD(boardp)) {
2948 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
2949 } else {
2950 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
2951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002953 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
2954 ASC_PRT_NEXT();
2955 for (i = 0; i <= ADV_MAX_TID; i++) {
2956 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
2957 len = asc_prt_line(cp, leftlen, " %X,", i);
2958 ASC_PRT_NEXT();
2959 }
2960 }
2961 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
2962 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002964 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965}
2966
2967/*
2968 * Display Wide Board BIOS Information.
2969 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002970static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04002972 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002973 int leftlen;
2974 int totlen;
2975 int len;
2976 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002978 leftlen = cplen;
2979 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002981 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
2982 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002984 /*
2985 * If the BIOS saved a valid signature, then fill in
2986 * the BIOS code segment base address.
2987 */
2988 if (boardp->bios_signature != 0x55AA) {
2989 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
2990 ASC_PRT_NEXT();
2991 len = asc_prt_line(cp, leftlen,
2992 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
2993 ASC_PRT_NEXT();
2994 len = asc_prt_line(cp, leftlen,
2995 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
2996 ASC_PRT_NEXT();
2997 } else {
2998 major = (boardp->bios_version >> 12) & 0xF;
2999 minor = (boardp->bios_version >> 8) & 0xF;
3000 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003002 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
3003 major, minor,
3004 letter >= 26 ? '?' : letter + 'A');
3005 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003007 /*
3008 * Current available ROM BIOS release is 3.1I for UW
3009 * and 3.2I for U2W. This code doesn't differentiate
3010 * UW and U2W boards.
3011 */
3012 if (major < 3 || (major <= 3 && minor < 1) ||
3013 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
3014 len = asc_prt_line(cp, leftlen,
3015 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
3016 ASC_PRT_NEXT();
3017 len = asc_prt_line(cp, leftlen,
3018 "ftp://ftp.connectcom.net/pub\n");
3019 ASC_PRT_NEXT();
3020 }
3021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003023 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024}
3025
3026/*
3027 * Add serial number to information bar if signature AAh
3028 * is found in at bit 15-9 (7 bits) of word 1.
3029 *
3030 * Serial Number consists fo 12 alpha-numeric digits.
3031 *
3032 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
3033 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
3034 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
3035 * 5 - Product revision (A-J) Word0: " "
3036 *
3037 * Signature Word1: 15-9 (7 bits)
3038 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
3039 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
3040 *
3041 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
3042 *
3043 * Note 1: Only production cards will have a serial number.
3044 *
3045 * Note 2: Signature is most significant 7 bits (0xFE).
3046 *
3047 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
3048 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003049static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003051 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003053 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
3054 return ASC_FALSE;
3055 } else {
3056 /*
3057 * First word - 6 digits.
3058 */
3059 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003061 /* Product type - 1st digit. */
3062 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
3063 /* Product type is P=Prototype */
3064 *cp += 0x8;
3065 }
3066 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003068 /* Manufacturing location - 2nd digit. */
3069 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003071 /* Product ID - 3rd, 4th digits. */
3072 num = w & 0x3FF;
3073 *cp++ = '0' + (num / 100);
3074 num %= 100;
3075 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003077 /* Product revision - 5th digit. */
3078 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003080 /*
3081 * Second word
3082 */
3083 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003085 /*
3086 * Year - 6th digit.
3087 *
3088 * If bit 15 of third word is set, then the
3089 * last digit of the year is greater than 7.
3090 */
3091 if (serialnum[2] & 0x8000) {
3092 *cp++ = '8' + ((w & 0x1C0) >> 6);
3093 } else {
3094 *cp++ = '0' + ((w & 0x1C0) >> 6);
3095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003097 /* Week of year - 7th, 8th digits. */
3098 num = w & 0x003F;
3099 *cp++ = '0' + num / 10;
3100 num %= 10;
3101 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003103 /*
3104 * Third word
3105 */
3106 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003108 /* Serial number - 9th digit. */
3109 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003111 /* 10th, 11th, 12th digits. */
3112 num = w % 1000;
3113 *cp++ = '0' + num / 100;
3114 num %= 100;
3115 *cp++ = '0' + num / 10;
3116 num %= 10;
3117 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003119 *cp = '\0'; /* Null Terminate the string. */
3120 return ASC_TRUE;
3121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122}
3123
3124/*
3125 * asc_prt_asc_board_eeprom()
3126 *
3127 * Print board EEPROM configuration.
3128 *
3129 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3130 * cf. asc_prt_line().
3131 *
3132 * Return the number of characters copied into 'cp'. No more than
3133 * 'cplen' characters will be copied to 'cp'.
3134 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003135static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003137 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003138 ASC_DVC_VAR *asc_dvc_varp;
3139 int leftlen;
3140 int totlen;
3141 int len;
3142 ASCEEP_CONFIG *ep;
3143 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003145 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003147 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003149 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3150 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003152 leftlen = cplen;
3153 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003155 len = asc_prt_line(cp, leftlen,
3156 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3157 shost->host_no);
3158 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003160 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
3161 == ASC_TRUE) {
3162 len =
3163 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3164 serialstr);
3165 ASC_PRT_NEXT();
3166 } else {
3167 if (ep->adapter_info[5] == 0xBB) {
3168 len = asc_prt_line(cp, leftlen,
3169 " Default Settings Used for EEPROM-less Adapter.\n");
3170 ASC_PRT_NEXT();
3171 } else {
3172 len = asc_prt_line(cp, leftlen,
3173 " Serial Number Signature Not Present.\n");
3174 ASC_PRT_NEXT();
3175 }
3176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003178 len = asc_prt_line(cp, leftlen,
3179 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3180 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
3181 ep->max_tag_qng);
3182 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003184 len = asc_prt_line(cp, leftlen,
3185 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
3186 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003188 len = asc_prt_line(cp, leftlen, " Target ID: ");
3189 ASC_PRT_NEXT();
3190 for (i = 0; i <= ASC_MAX_TID; i++) {
3191 len = asc_prt_line(cp, leftlen, " %d", i);
3192 ASC_PRT_NEXT();
3193 }
3194 len = asc_prt_line(cp, leftlen, "\n");
3195 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003197 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3198 ASC_PRT_NEXT();
3199 for (i = 0; i <= ASC_MAX_TID; i++) {
3200 len = asc_prt_line(cp, leftlen, " %c",
3201 (ep->
3202 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3203 'N');
3204 ASC_PRT_NEXT();
3205 }
3206 len = asc_prt_line(cp, leftlen, "\n");
3207 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003209 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3210 ASC_PRT_NEXT();
3211 for (i = 0; i <= ASC_MAX_TID; i++) {
3212 len = asc_prt_line(cp, leftlen, " %c",
3213 (ep->
3214 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3215 'N');
3216 ASC_PRT_NEXT();
3217 }
3218 len = asc_prt_line(cp, leftlen, "\n");
3219 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003221 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3222 ASC_PRT_NEXT();
3223 for (i = 0; i <= ASC_MAX_TID; i++) {
3224 len = asc_prt_line(cp, leftlen, " %c",
3225 (ep->
3226 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3227 'N');
3228 ASC_PRT_NEXT();
3229 }
3230 len = asc_prt_line(cp, leftlen, "\n");
3231 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003233 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3234 ASC_PRT_NEXT();
3235 for (i = 0; i <= ASC_MAX_TID; i++) {
3236 len = asc_prt_line(cp, leftlen, " %c",
3237 (ep->
3238 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3239 'N');
3240 ASC_PRT_NEXT();
3241 }
3242 len = asc_prt_line(cp, leftlen, "\n");
3243 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244
3245#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003246 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3247 len = asc_prt_line(cp, leftlen,
3248 " Host ISA DMA speed: %d MB/S\n",
3249 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
3250 ASC_PRT_NEXT();
3251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252#endif /* CONFIG_ISA */
3253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003254 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255}
3256
3257/*
3258 * asc_prt_adv_board_eeprom()
3259 *
3260 * Print board EEPROM configuration.
3261 *
3262 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3263 * cf. asc_prt_line().
3264 *
3265 * Return the number of characters copied into 'cp'. No more than
3266 * 'cplen' characters will be copied to 'cp'.
3267 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003268static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003270 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003271 ADV_DVC_VAR *adv_dvc_varp;
3272 int leftlen;
3273 int totlen;
3274 int len;
3275 int i;
3276 char *termstr;
3277 uchar serialstr[13];
3278 ADVEEP_3550_CONFIG *ep_3550 = NULL;
3279 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
3280 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
3281 ushort word;
3282 ushort *wordp;
3283 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003285 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3286 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3287 ep_3550 = &boardp->eep_config.adv_3550_eep;
3288 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3289 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
3290 } else {
3291 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
3292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003294 leftlen = cplen;
3295 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003297 len = asc_prt_line(cp, leftlen,
3298 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3299 shost->host_no);
3300 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003302 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3303 wordp = &ep_3550->serial_number_word1;
3304 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3305 wordp = &ep_38C0800->serial_number_word1;
3306 } else {
3307 wordp = &ep_38C1600->serial_number_word1;
3308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003310 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
3311 len =
3312 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3313 serialstr);
3314 ASC_PRT_NEXT();
3315 } else {
3316 len = asc_prt_line(cp, leftlen,
3317 " Serial Number Signature Not Present.\n");
3318 ASC_PRT_NEXT();
3319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003321 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3322 len = asc_prt_line(cp, leftlen,
3323 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3324 ep_3550->adapter_scsi_id,
3325 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
3326 ASC_PRT_NEXT();
3327 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3328 len = asc_prt_line(cp, leftlen,
3329 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3330 ep_38C0800->adapter_scsi_id,
3331 ep_38C0800->max_host_qng,
3332 ep_38C0800->max_dvc_qng);
3333 ASC_PRT_NEXT();
3334 } else {
3335 len = asc_prt_line(cp, leftlen,
3336 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3337 ep_38C1600->adapter_scsi_id,
3338 ep_38C1600->max_host_qng,
3339 ep_38C1600->max_dvc_qng);
3340 ASC_PRT_NEXT();
3341 }
3342 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3343 word = ep_3550->termination;
3344 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3345 word = ep_38C0800->termination_lvd;
3346 } else {
3347 word = ep_38C1600->termination_lvd;
3348 }
3349 switch (word) {
3350 case 1:
3351 termstr = "Low Off/High Off";
3352 break;
3353 case 2:
3354 termstr = "Low Off/High On";
3355 break;
3356 case 3:
3357 termstr = "Low On/High On";
3358 break;
3359 default:
3360 case 0:
3361 termstr = "Automatic";
3362 break;
3363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003365 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3366 len = asc_prt_line(cp, leftlen,
3367 " termination: %u (%s), bios_ctrl: 0x%x\n",
3368 ep_3550->termination, termstr,
3369 ep_3550->bios_ctrl);
3370 ASC_PRT_NEXT();
3371 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3372 len = asc_prt_line(cp, leftlen,
3373 " termination: %u (%s), bios_ctrl: 0x%x\n",
3374 ep_38C0800->termination_lvd, termstr,
3375 ep_38C0800->bios_ctrl);
3376 ASC_PRT_NEXT();
3377 } else {
3378 len = asc_prt_line(cp, leftlen,
3379 " termination: %u (%s), bios_ctrl: 0x%x\n",
3380 ep_38C1600->termination_lvd, termstr,
3381 ep_38C1600->bios_ctrl);
3382 ASC_PRT_NEXT();
3383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003385 len = asc_prt_line(cp, leftlen, " Target ID: ");
3386 ASC_PRT_NEXT();
3387 for (i = 0; i <= ADV_MAX_TID; i++) {
3388 len = asc_prt_line(cp, leftlen, " %X", i);
3389 ASC_PRT_NEXT();
3390 }
3391 len = asc_prt_line(cp, leftlen, "\n");
3392 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003394 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3395 word = ep_3550->disc_enable;
3396 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3397 word = ep_38C0800->disc_enable;
3398 } else {
3399 word = ep_38C1600->disc_enable;
3400 }
3401 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3402 ASC_PRT_NEXT();
3403 for (i = 0; i <= ADV_MAX_TID; i++) {
3404 len = asc_prt_line(cp, leftlen, " %c",
3405 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3406 ASC_PRT_NEXT();
3407 }
3408 len = asc_prt_line(cp, leftlen, "\n");
3409 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003411 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3412 word = ep_3550->tagqng_able;
3413 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3414 word = ep_38C0800->tagqng_able;
3415 } else {
3416 word = ep_38C1600->tagqng_able;
3417 }
3418 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3419 ASC_PRT_NEXT();
3420 for (i = 0; i <= ADV_MAX_TID; i++) {
3421 len = asc_prt_line(cp, leftlen, " %c",
3422 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3423 ASC_PRT_NEXT();
3424 }
3425 len = asc_prt_line(cp, leftlen, "\n");
3426 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003428 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3429 word = ep_3550->start_motor;
3430 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3431 word = ep_38C0800->start_motor;
3432 } else {
3433 word = ep_38C1600->start_motor;
3434 }
3435 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3436 ASC_PRT_NEXT();
3437 for (i = 0; i <= ADV_MAX_TID; i++) {
3438 len = asc_prt_line(cp, leftlen, " %c",
3439 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3440 ASC_PRT_NEXT();
3441 }
3442 len = asc_prt_line(cp, leftlen, "\n");
3443 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003445 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3446 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3447 ASC_PRT_NEXT();
3448 for (i = 0; i <= ADV_MAX_TID; i++) {
3449 len = asc_prt_line(cp, leftlen, " %c",
3450 (ep_3550->
3451 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
3452 'Y' : 'N');
3453 ASC_PRT_NEXT();
3454 }
3455 len = asc_prt_line(cp, leftlen, "\n");
3456 ASC_PRT_NEXT();
3457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003459 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3460 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
3461 ASC_PRT_NEXT();
3462 for (i = 0; i <= ADV_MAX_TID; i++) {
3463 len = asc_prt_line(cp, leftlen, " %c",
3464 (ep_3550->
3465 ultra_able & ADV_TID_TO_TIDMASK(i))
3466 ? 'Y' : 'N');
3467 ASC_PRT_NEXT();
3468 }
3469 len = asc_prt_line(cp, leftlen, "\n");
3470 ASC_PRT_NEXT();
3471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003473 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3474 word = ep_3550->wdtr_able;
3475 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3476 word = ep_38C0800->wdtr_able;
3477 } else {
3478 word = ep_38C1600->wdtr_able;
3479 }
3480 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
3481 ASC_PRT_NEXT();
3482 for (i = 0; i <= ADV_MAX_TID; i++) {
3483 len = asc_prt_line(cp, leftlen, " %c",
3484 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3485 ASC_PRT_NEXT();
3486 }
3487 len = asc_prt_line(cp, leftlen, "\n");
3488 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003490 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
3491 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
3492 len = asc_prt_line(cp, leftlen,
3493 " Synchronous Transfer Speed (Mhz):\n ");
3494 ASC_PRT_NEXT();
3495 for (i = 0; i <= ADV_MAX_TID; i++) {
3496 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003498 if (i == 0) {
3499 sdtr_speed = adv_dvc_varp->sdtr_speed1;
3500 } else if (i == 4) {
3501 sdtr_speed = adv_dvc_varp->sdtr_speed2;
3502 } else if (i == 8) {
3503 sdtr_speed = adv_dvc_varp->sdtr_speed3;
3504 } else if (i == 12) {
3505 sdtr_speed = adv_dvc_varp->sdtr_speed4;
3506 }
3507 switch (sdtr_speed & ADV_MAX_TID) {
3508 case 0:
3509 speed_str = "Off";
3510 break;
3511 case 1:
3512 speed_str = " 5";
3513 break;
3514 case 2:
3515 speed_str = " 10";
3516 break;
3517 case 3:
3518 speed_str = " 20";
3519 break;
3520 case 4:
3521 speed_str = " 40";
3522 break;
3523 case 5:
3524 speed_str = " 80";
3525 break;
3526 default:
3527 speed_str = "Unk";
3528 break;
3529 }
3530 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
3531 ASC_PRT_NEXT();
3532 if (i == 7) {
3533 len = asc_prt_line(cp, leftlen, "\n ");
3534 ASC_PRT_NEXT();
3535 }
3536 sdtr_speed >>= 4;
3537 }
3538 len = asc_prt_line(cp, leftlen, "\n");
3539 ASC_PRT_NEXT();
3540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003542 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543}
3544
3545/*
3546 * asc_prt_driver_conf()
3547 *
3548 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3549 * cf. asc_prt_line().
3550 *
3551 * Return the number of characters copied into 'cp'. No more than
3552 * 'cplen' characters will be copied to 'cp'.
3553 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003554static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003556 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003557 int leftlen;
3558 int totlen;
3559 int len;
3560 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003562 leftlen = cplen;
3563 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003565 len = asc_prt_line(cp, leftlen,
3566 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
3567 shost->host_no);
3568 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003570 len = asc_prt_line(cp, leftlen,
3571 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
3572 shost->host_busy, shost->last_reset, shost->max_id,
3573 shost->max_lun, shost->max_channel);
3574 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003576 len = asc_prt_line(cp, leftlen,
3577 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
3578 shost->unique_id, shost->can_queue, shost->this_id,
3579 shost->sg_tablesize, shost->cmd_per_lun);
3580 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003582 len = asc_prt_line(cp, leftlen,
3583 " unchecked_isa_dma %d, use_clustering %d\n",
3584 shost->unchecked_isa_dma, shost->use_clustering);
3585 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003587 len = asc_prt_line(cp, leftlen,
3588 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
3589 boardp->flags, boardp->last_reset, jiffies,
3590 boardp->asc_n_io_port);
3591 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003593 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003594 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003596 if (ASC_NARROW_BOARD(boardp)) {
3597 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3598 } else {
3599 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003602 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603}
3604
3605/*
3606 * asc_prt_asc_board_info()
3607 *
3608 * Print dynamic board configuration information.
3609 *
3610 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3611 * cf. asc_prt_line().
3612 *
3613 * Return the number of characters copied into 'cp'. No more than
3614 * 'cplen' characters will be copied to 'cp'.
3615 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003616static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003618 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003619 int chip_scsi_id;
3620 int leftlen;
3621 int totlen;
3622 int len;
3623 ASC_DVC_VAR *v;
3624 ASC_DVC_CFG *c;
3625 int i;
3626 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003628 v = &boardp->dvc_var.asc_dvc_var;
3629 c = &boardp->dvc_cfg.asc_dvc_cfg;
3630 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003632 leftlen = cplen;
3633 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003635 len = asc_prt_line(cp, leftlen,
3636 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3637 shost->host_no);
3638 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04003640 len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
3641 "mcode_version 0x%x, err_code %u\n",
3642 c->chip_version, c->mcode_date, c->mcode_version,
3643 v->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003644 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003646 /* Current number of commands waiting for the host. */
3647 len = asc_prt_line(cp, leftlen,
3648 " Total Command Pending: %d\n", v->cur_total_qng);
3649 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003651 len = asc_prt_line(cp, leftlen, " Command Queuing:");
3652 ASC_PRT_NEXT();
3653 for (i = 0; i <= ASC_MAX_TID; i++) {
3654 if ((chip_scsi_id == i) ||
3655 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3656 continue;
3657 }
3658 len = asc_prt_line(cp, leftlen, " %X:%c",
3659 i,
3660 (v->
3661 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
3662 'Y' : 'N');
3663 ASC_PRT_NEXT();
3664 }
3665 len = asc_prt_line(cp, leftlen, "\n");
3666 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003668 /* Current number of commands waiting for a device. */
3669 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
3670 ASC_PRT_NEXT();
3671 for (i = 0; i <= ASC_MAX_TID; i++) {
3672 if ((chip_scsi_id == i) ||
3673 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3674 continue;
3675 }
3676 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
3677 ASC_PRT_NEXT();
3678 }
3679 len = asc_prt_line(cp, leftlen, "\n");
3680 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003682 /* Current limit on number of commands that can be sent to a device. */
3683 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
3684 ASC_PRT_NEXT();
3685 for (i = 0; i <= ASC_MAX_TID; i++) {
3686 if ((chip_scsi_id == i) ||
3687 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3688 continue;
3689 }
3690 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
3691 ASC_PRT_NEXT();
3692 }
3693 len = asc_prt_line(cp, leftlen, "\n");
3694 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003696 /* Indicate whether the device has returned queue full status. */
3697 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
3698 ASC_PRT_NEXT();
3699 for (i = 0; i <= ASC_MAX_TID; i++) {
3700 if ((chip_scsi_id == i) ||
3701 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3702 continue;
3703 }
3704 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
3705 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
3706 i, boardp->queue_full_cnt[i]);
3707 } else {
3708 len = asc_prt_line(cp, leftlen, " %X:N", i);
3709 }
3710 ASC_PRT_NEXT();
3711 }
3712 len = asc_prt_line(cp, leftlen, "\n");
3713 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003715 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3716 ASC_PRT_NEXT();
3717 for (i = 0; i <= ASC_MAX_TID; i++) {
3718 if ((chip_scsi_id == i) ||
3719 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3720 continue;
3721 }
3722 len = asc_prt_line(cp, leftlen, " %X:%c",
3723 i,
3724 (v->
3725 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3726 'N');
3727 ASC_PRT_NEXT();
3728 }
3729 len = asc_prt_line(cp, leftlen, "\n");
3730 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003732 for (i = 0; i <= ASC_MAX_TID; i++) {
3733 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003735 if ((chip_scsi_id == i) ||
3736 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3737 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
3738 continue;
3739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003741 len = asc_prt_line(cp, leftlen, " %X:", i);
3742 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003744 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
3745 len = asc_prt_line(cp, leftlen, " Asynchronous");
3746 ASC_PRT_NEXT();
3747 } else {
3748 syn_period_ix =
3749 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
3750 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003752 len = asc_prt_line(cp, leftlen,
3753 " Transfer Period Factor: %d (%d.%d Mhz),",
3754 v->sdtr_period_tbl[syn_period_ix],
3755 250 /
3756 v->sdtr_period_tbl[syn_period_ix],
3757 ASC_TENTHS(250,
3758 v->
3759 sdtr_period_tbl
3760 [syn_period_ix]));
3761 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003763 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
3764 boardp->
3765 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
3766 ASC_PRT_NEXT();
3767 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003769 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3770 len = asc_prt_line(cp, leftlen, "*\n");
3771 renegotiate = 1;
3772 } else {
3773 len = asc_prt_line(cp, leftlen, "\n");
3774 }
3775 ASC_PRT_NEXT();
3776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003778 if (renegotiate) {
3779 len = asc_prt_line(cp, leftlen,
3780 " * = Re-negotiation pending before next command.\n");
3781 ASC_PRT_NEXT();
3782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003784 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785}
3786
3787/*
3788 * asc_prt_adv_board_info()
3789 *
3790 * Print dynamic board configuration information.
3791 *
3792 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3793 * cf. asc_prt_line().
3794 *
3795 * Return the number of characters copied into 'cp'. No more than
3796 * 'cplen' characters will be copied to 'cp'.
3797 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003798static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04003800 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003801 int leftlen;
3802 int totlen;
3803 int len;
3804 int i;
3805 ADV_DVC_VAR *v;
3806 ADV_DVC_CFG *c;
3807 AdvPortAddr iop_base;
3808 ushort chip_scsi_id;
3809 ushort lramword;
3810 uchar lrambyte;
3811 ushort tagqng_able;
3812 ushort sdtr_able, wdtr_able;
3813 ushort wdtr_done, sdtr_done;
3814 ushort period = 0;
3815 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003817 v = &boardp->dvc_var.adv_dvc_var;
3818 c = &boardp->dvc_cfg.adv_dvc_cfg;
3819 iop_base = v->iop_base;
3820 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003822 leftlen = cplen;
3823 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003825 len = asc_prt_line(cp, leftlen,
3826 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3827 shost->host_no);
3828 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003830 len = asc_prt_line(cp, leftlen,
3831 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
3832 v->iop_base,
3833 AdvReadWordRegister(iop_base,
3834 IOPW_SCSI_CFG1) & CABLE_DETECT,
3835 v->err_code);
3836 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
Matthew Wilcoxb08fc562007-10-02 21:55:32 -04003838 len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
3839 "mcode_version 0x%x\n", c->chip_version,
3840 c->mcode_date, c->mcode_version);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003841 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003843 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
3844 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
3845 ASC_PRT_NEXT();
3846 for (i = 0; i <= ADV_MAX_TID; i++) {
3847 if ((chip_scsi_id == i) ||
3848 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3849 continue;
3850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003852 len = asc_prt_line(cp, leftlen, " %X:%c",
3853 i,
3854 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3855 'N');
3856 ASC_PRT_NEXT();
3857 }
3858 len = asc_prt_line(cp, leftlen, "\n");
3859 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003861 len = asc_prt_line(cp, leftlen, " Queue Limit:");
3862 ASC_PRT_NEXT();
3863 for (i = 0; i <= ADV_MAX_TID; i++) {
3864 if ((chip_scsi_id == i) ||
3865 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3866 continue;
3867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003869 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
3870 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003872 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3873 ASC_PRT_NEXT();
3874 }
3875 len = asc_prt_line(cp, leftlen, "\n");
3876 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003878 len = asc_prt_line(cp, leftlen, " Command Pending:");
3879 ASC_PRT_NEXT();
3880 for (i = 0; i <= ADV_MAX_TID; i++) {
3881 if ((chip_scsi_id == i) ||
3882 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3883 continue;
3884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003886 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
3887 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003889 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3890 ASC_PRT_NEXT();
3891 }
3892 len = asc_prt_line(cp, leftlen, "\n");
3893 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003895 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
3896 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
3897 ASC_PRT_NEXT();
3898 for (i = 0; i <= ADV_MAX_TID; i++) {
3899 if ((chip_scsi_id == i) ||
3900 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3901 continue;
3902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003904 len = asc_prt_line(cp, leftlen, " %X:%c",
3905 i,
3906 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3907 'N');
3908 ASC_PRT_NEXT();
3909 }
3910 len = asc_prt_line(cp, leftlen, "\n");
3911 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003913 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
3914 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
3915 ASC_PRT_NEXT();
3916 for (i = 0; i <= ADV_MAX_TID; i++) {
3917 if ((chip_scsi_id == i) ||
3918 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3919 continue;
3920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003922 AdvReadWordLram(iop_base,
3923 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
3924 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003926 len = asc_prt_line(cp, leftlen, " %X:%d",
3927 i, (lramword & 0x8000) ? 16 : 8);
3928 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003930 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
3931 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3932 len = asc_prt_line(cp, leftlen, "*");
3933 ASC_PRT_NEXT();
3934 renegotiate = 1;
3935 }
3936 }
3937 len = asc_prt_line(cp, leftlen, "\n");
3938 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003940 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
3941 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
3942 ASC_PRT_NEXT();
3943 for (i = 0; i <= ADV_MAX_TID; i++) {
3944 if ((chip_scsi_id == i) ||
3945 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3946 continue;
3947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003949 len = asc_prt_line(cp, leftlen, " %X:%c",
3950 i,
3951 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3952 'N');
3953 ASC_PRT_NEXT();
3954 }
3955 len = asc_prt_line(cp, leftlen, "\n");
3956 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003958 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
3959 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003961 AdvReadWordLram(iop_base,
3962 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
3963 lramword);
3964 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003966 if ((chip_scsi_id == i) ||
3967 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3968 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
3969 continue;
3970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003972 len = asc_prt_line(cp, leftlen, " %X:", i);
3973 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003975 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
3976 len = asc_prt_line(cp, leftlen, " Asynchronous");
3977 ASC_PRT_NEXT();
3978 } else {
3979 len =
3980 asc_prt_line(cp, leftlen,
3981 " Transfer Period Factor: ");
3982 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003984 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
3985 len =
3986 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
3987 ASC_PRT_NEXT();
3988 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
3989 len =
3990 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
3991 ASC_PRT_NEXT();
3992 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003994 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003996 if (period == 0) { /* Should never happen. */
3997 len =
3998 asc_prt_line(cp, leftlen,
3999 "%d (? Mhz), ");
4000 ASC_PRT_NEXT();
4001 } else {
4002 len = asc_prt_line(cp, leftlen,
4003 "%d (%d.%d Mhz),",
4004 period, 250 / period,
4005 ASC_TENTHS(250,
4006 period));
4007 ASC_PRT_NEXT();
4008 }
4009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004011 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
4012 lramword & 0x1F);
4013 ASC_PRT_NEXT();
4014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004016 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
4017 len = asc_prt_line(cp, leftlen, "*\n");
4018 renegotiate = 1;
4019 } else {
4020 len = asc_prt_line(cp, leftlen, "\n");
4021 }
4022 ASC_PRT_NEXT();
4023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004025 if (renegotiate) {
4026 len = asc_prt_line(cp, leftlen,
4027 " * = Re-negotiation pending before next command.\n");
4028 ASC_PRT_NEXT();
4029 }
4030
4031 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032}
4033
4034/*
4035 * asc_proc_copy()
4036 *
4037 * Copy proc information to a read buffer taking into account the current
4038 * read offset in the file and the remaining space in the read buffer.
4039 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004040static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004042 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004044 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004046 ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004047 (unsigned)offset, (unsigned)advoffset, cplen);
4048 if (offset <= advoffset) {
4049 /* Read offset below current offset, copy everything. */
4050 cnt = min(cplen, leftlen);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004051 ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004052 (ulong)curbuf, (ulong)cp, cnt);
4053 memcpy(curbuf, cp, cnt);
4054 } else if (offset < advoffset + cplen) {
4055 /* Read offset within current range, partial copy. */
4056 cnt = (advoffset + cplen) - offset;
4057 cp = (cp + cplen) - cnt;
4058 cnt = min(cnt, leftlen);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004059 ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004060 (ulong)curbuf, (ulong)cp, cnt);
4061 memcpy(curbuf, cp, cnt);
4062 }
4063 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064}
4065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066#ifdef ADVANSYS_STATS
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067/*
4068 * asc_prt_board_stats()
4069 *
4070 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4071 * cf. asc_prt_line().
4072 *
4073 * Return the number of characters copied into 'cp'. No more than
4074 * 'cplen' characters will be copied to 'cp'.
4075 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004076static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004078 struct asc_board *boardp = shost_priv(shost);
4079 struct asc_stats *s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004081 int leftlen = cplen;
4082 int len, totlen = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004084 len = asc_prt_line(cp, leftlen,
4085 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
4086 shost->host_no);
4087 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004089 len = asc_prt_line(cp, leftlen,
4090 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
4091 s->queuecommand, s->reset, s->biosparam,
4092 s->interrupt);
4093 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004095 len = asc_prt_line(cp, leftlen,
4096 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
4097 s->callback, s->done, s->build_error,
4098 s->adv_build_noreq, s->adv_build_nosg);
4099 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004101 len = asc_prt_line(cp, leftlen,
4102 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
4103 s->exe_noerror, s->exe_busy, s->exe_error,
4104 s->exe_unknown);
4105 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004107 /*
4108 * Display data transfer statistics.
4109 */
4110 if (s->cont_cnt > 0) {
4111 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
4112 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004114 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
4115 s->cont_xfer / 2,
4116 ASC_TENTHS(s->cont_xfer, 2));
4117 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004119 /* Contiguous transfer average size */
4120 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
4121 (s->cont_xfer / 2) / s->cont_cnt,
4122 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
4123 ASC_PRT_NEXT();
4124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004126 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004128 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
4129 s->sg_cnt, s->sg_elem);
4130 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004132 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
4133 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
4134 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004136 /* Scatter gather transfer statistics */
4137 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
4138 s->sg_elem / s->sg_cnt,
4139 ASC_TENTHS(s->sg_elem, s->sg_cnt));
4140 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004142 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
4143 (s->sg_xfer / 2) / s->sg_elem,
4144 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
4145 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004147 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
4148 (s->sg_xfer / 2) / s->sg_cnt,
4149 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
4150 ASC_PRT_NEXT();
4151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004153 /*
4154 * Display request queuing statistics.
4155 */
4156 len = asc_prt_line(cp, leftlen,
4157 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
4158 HZ);
4159 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004161 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163#endif /* ADVANSYS_STATS */
4164
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165/*
Matthew Wilcox51219352007-10-02 21:55:22 -04004166 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
4167 *
4168 * *buffer: I/O buffer
4169 * **start: if inout == FALSE pointer into buffer where user read should start
4170 * offset: current offset into a /proc/scsi/advansys/[0...] file
4171 * length: length of buffer
4172 * hostno: Scsi_Host host_no
4173 * inout: TRUE - user is writing; FALSE - user is reading
4174 *
4175 * Return the number of bytes read from or written to a
4176 * /proc/scsi/advansys/[0...] file.
4177 *
4178 * Note: This function uses the per board buffer 'prtbuf' which is
4179 * allocated when the board is initialized in advansys_detect(). The
4180 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4181 * used to write to the buffer. The way asc_proc_copy() is written
4182 * if 'prtbuf' is too small it will not be overwritten. Instead the
4183 * user just won't get all the available statistics.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 */
Matthew Wilcox51219352007-10-02 21:55:22 -04004185static int
4186advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
4187 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004189 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04004190 char *cp;
4191 int cplen;
4192 int cnt;
4193 int totcnt;
4194 int leftlen;
4195 char *curbuf;
4196 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004198 ASC_DBG(1, "begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Matthew Wilcox51219352007-10-02 21:55:22 -04004200 /*
4201 * User write not supported.
4202 */
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004203 if (inout == TRUE)
4204 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205
Matthew Wilcox51219352007-10-02 21:55:22 -04004206 /*
4207 * User read of /proc/scsi/advansys/[0...] file.
4208 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
Matthew Wilcox51219352007-10-02 21:55:22 -04004210 /* Copy read data starting at the beginning of the buffer. */
4211 *start = buffer;
4212 curbuf = buffer;
4213 advoffset = 0;
4214 totcnt = 0;
4215 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216
Matthew Wilcox51219352007-10-02 21:55:22 -04004217 /*
4218 * Get board configuration information.
4219 *
4220 * advansys_info() returns the board string from its own static buffer.
4221 */
4222 cp = (char *)advansys_info(shost);
4223 strcat(cp, "\n");
4224 cplen = strlen(cp);
4225 /* Copy board information. */
4226 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4227 totcnt += cnt;
4228 leftlen -= cnt;
4229 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004230 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004231 return totcnt;
4232 }
4233 advoffset += cplen;
4234 curbuf += cnt;
4235
4236 /*
4237 * Display Wide Board BIOS Information.
4238 */
Matthew Wilcox9a256fa2007-10-02 21:55:28 -04004239 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004240 cp = boardp->prtbuf;
4241 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
4242 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4243 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4244 cplen);
4245 totcnt += cnt;
4246 leftlen -= cnt;
4247 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004248 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004249 return totcnt;
4250 }
4251 advoffset += cplen;
4252 curbuf += cnt;
4253 }
4254
4255 /*
4256 * Display driver information for each device attached to the board.
4257 */
4258 cp = boardp->prtbuf;
4259 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
4260 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4261 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4262 totcnt += cnt;
4263 leftlen -= cnt;
4264 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004265 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004266 return totcnt;
4267 }
4268 advoffset += cplen;
4269 curbuf += cnt;
4270
4271 /*
4272 * Display EEPROM configuration for the board.
4273 */
4274 cp = boardp->prtbuf;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004275 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004276 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004277 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04004278 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004279 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004280 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4281 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4282 totcnt += cnt;
4283 leftlen -= cnt;
4284 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004285 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004286 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004287 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004288 advoffset += cplen;
4289 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290
Matthew Wilcox51219352007-10-02 21:55:22 -04004291 /*
4292 * Display driver configuration and information for the board.
4293 */
4294 cp = boardp->prtbuf;
4295 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
4296 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4297 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4298 totcnt += cnt;
4299 leftlen -= cnt;
4300 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004301 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004302 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004303 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004304 advoffset += cplen;
4305 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
Matthew Wilcox51219352007-10-02 21:55:22 -04004307#ifdef ADVANSYS_STATS
4308 /*
4309 * Display driver statistics for the board.
4310 */
4311 cp = boardp->prtbuf;
4312 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
4313 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4314 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4315 totcnt += cnt;
4316 leftlen -= cnt;
4317 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004318 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004319 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004320 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004321 advoffset += cplen;
4322 curbuf += cnt;
4323#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324
Matthew Wilcox51219352007-10-02 21:55:22 -04004325 /*
4326 * Display Asc Library dynamic configuration information
4327 * for the board.
4328 */
4329 cp = boardp->prtbuf;
4330 if (ASC_NARROW_BOARD(boardp)) {
4331 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
4332 } else {
4333 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004334 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004335 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4336 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4337 totcnt += cnt;
4338 leftlen -= cnt;
4339 if (leftlen == 0) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004340 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004341 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004342 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004343 advoffset += cplen;
4344 curbuf += cnt;
4345
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004346 ASC_DBG(1, "totcnt %d\n", totcnt);
Matthew Wilcox51219352007-10-02 21:55:22 -04004347
4348 return totcnt;
4349}
4350#endif /* CONFIG_PROC_FS */
4351
4352static void asc_scsi_done(struct scsi_cmnd *scp)
4353{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04004354 struct asc_board *boardp = shost_priv(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04004355
4356 if (scp->use_sg)
4357 dma_unmap_sg(boardp->dev,
4358 (struct scatterlist *)scp->request_buffer,
4359 scp->use_sg, scp->sc_data_direction);
4360 else if (scp->request_bufflen)
4361 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
4362 scp->request_bufflen, scp->sc_data_direction);
4363
4364 ASC_STATS(scp->device->host, done);
4365
4366 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367}
4368
Matthew Wilcox51219352007-10-02 21:55:22 -04004369static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370{
Matthew Wilcox51219352007-10-02 21:55:22 -04004371 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
Matthew Wilcox51219352007-10-02 21:55:22 -04004373 val = AscGetChipControl(iop_base) &
4374 (~
4375 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
4376 CC_CHIP_RESET));
4377 if (bank == 1) {
4378 val |= CC_BANK_ONE;
4379 } else if (bank == 2) {
4380 val |= CC_DIAG | CC_BANK_ONE;
4381 } else {
4382 val &= ~CC_BANK_ONE;
4383 }
4384 AscSetChipControl(iop_base, val);
4385 return;
4386}
4387
4388static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
4389{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004390 AscSetBank(iop_base, 1);
Matthew Wilcox51219352007-10-02 21:55:22 -04004391 AscWriteChipIH(iop_base, ins_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004392 AscSetBank(iop_base, 0);
Matthew Wilcox51219352007-10-02 21:55:22 -04004393 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394}
4395
Matthew Wilcox51219352007-10-02 21:55:22 -04004396static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397{
Matthew Wilcox51219352007-10-02 21:55:22 -04004398 AscSetChipControl(iop_base, 0);
4399 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4400 return (0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004401 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004402 return (1);
4403}
4404
4405static int AscStopChip(PortAddr iop_base)
4406{
4407 uchar cc_val;
4408
4409 cc_val =
4410 AscGetChipControl(iop_base) &
4411 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
4412 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
4413 AscSetChipIH(iop_base, INS_HALT);
4414 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4415 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
4416 return (0);
4417 }
4418 return (1);
4419}
4420
4421static int AscIsChipHalted(PortAddr iop_base)
4422{
4423 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4424 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
4425 return (1);
4426 }
4427 }
4428 return (0);
4429}
4430
4431static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
4432{
4433 PortAddr iop_base;
4434 int i = 10;
4435
4436 iop_base = asc_dvc->iop_base;
4437 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
4438 && (i-- > 0)) {
4439 mdelay(100);
4440 }
4441 AscStopChip(iop_base);
4442 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
4443 udelay(60);
4444 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4445 AscSetChipIH(iop_base, INS_HALT);
4446 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
4447 AscSetChipControl(iop_base, CC_HALT);
4448 mdelay(200);
4449 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
4450 AscSetChipStatus(iop_base, 0);
4451 return (AscIsChipHalted(iop_base));
4452}
4453
4454static int AscFindSignature(PortAddr iop_base)
4455{
4456 ushort sig_word;
4457
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004458 ASC_DBG(1, "AscGetChipSignatureByte(0x%x) 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04004459 iop_base, AscGetChipSignatureByte(iop_base));
4460 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004461 ASC_DBG(1, "AscGetChipSignatureWord(0x%x) 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04004462 iop_base, AscGetChipSignatureWord(iop_base));
4463 sig_word = AscGetChipSignatureWord(iop_base);
4464 if ((sig_word == (ushort)ASC_1000_ID0W) ||
4465 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
4466 return (1);
4467 }
4468 }
4469 return (0);
4470}
4471
4472static void AscEnableInterrupt(PortAddr iop_base)
4473{
4474 ushort cfg;
4475
4476 cfg = AscGetChipCfgLsw(iop_base);
4477 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
4478 return;
4479}
4480
4481static void AscDisableInterrupt(PortAddr iop_base)
4482{
4483 ushort cfg;
4484
4485 cfg = AscGetChipCfgLsw(iop_base);
4486 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
4487 return;
4488}
4489
4490static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
4491{
4492 unsigned char byte_data;
4493 unsigned short word_data;
4494
4495 if (isodd_word(addr)) {
4496 AscSetChipLramAddr(iop_base, addr - 1);
4497 word_data = AscGetChipLramData(iop_base);
4498 byte_data = (word_data >> 8) & 0xFF;
4499 } else {
4500 AscSetChipLramAddr(iop_base, addr);
4501 word_data = AscGetChipLramData(iop_base);
4502 byte_data = word_data & 0xFF;
4503 }
4504 return byte_data;
4505}
4506
4507static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
4508{
4509 ushort word_data;
4510
4511 AscSetChipLramAddr(iop_base, addr);
4512 word_data = AscGetChipLramData(iop_base);
4513 return (word_data);
4514}
4515
4516#if CC_VERY_LONG_SG_LIST
4517static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
4518{
4519 ushort val_low, val_high;
4520 ASC_DCNT dword_data;
4521
4522 AscSetChipLramAddr(iop_base, addr);
4523 val_low = AscGetChipLramData(iop_base);
4524 val_high = AscGetChipLramData(iop_base);
4525 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
4526 return (dword_data);
4527}
4528#endif /* CC_VERY_LONG_SG_LIST */
4529
4530static void
4531AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
4532{
4533 int i;
4534
4535 AscSetChipLramAddr(iop_base, s_addr);
4536 for (i = 0; i < words; i++) {
4537 AscSetChipLramData(iop_base, set_wval);
4538 }
4539}
4540
4541static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
4542{
4543 AscSetChipLramAddr(iop_base, addr);
4544 AscSetChipLramData(iop_base, word_val);
4545 return;
4546}
4547
4548static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
4549{
4550 ushort word_data;
4551
4552 if (isodd_word(addr)) {
4553 addr--;
4554 word_data = AscReadLramWord(iop_base, addr);
4555 word_data &= 0x00FF;
4556 word_data |= (((ushort)byte_val << 8) & 0xFF00);
4557 } else {
4558 word_data = AscReadLramWord(iop_base, addr);
4559 word_data &= 0xFF00;
4560 word_data |= ((ushort)byte_val & 0x00FF);
4561 }
4562 AscWriteLramWord(iop_base, addr, word_data);
4563 return;
4564}
4565
4566/*
4567 * Copy 2 bytes to LRAM.
4568 *
4569 * The source data is assumed to be in little-endian order in memory
4570 * and is maintained in little-endian order when written to LRAM.
4571 */
4572static void
4573AscMemWordCopyPtrToLram(PortAddr iop_base,
4574 ushort s_addr, uchar *s_buffer, int words)
4575{
4576 int i;
4577
4578 AscSetChipLramAddr(iop_base, s_addr);
4579 for (i = 0; i < 2 * words; i += 2) {
4580 /*
4581 * On a little-endian system the second argument below
4582 * produces a little-endian ushort which is written to
4583 * LRAM in little-endian order. On a big-endian system
4584 * the second argument produces a big-endian ushort which
4585 * is "transparently" byte-swapped by outpw() and written
4586 * in little-endian order to LRAM.
4587 */
4588 outpw(iop_base + IOP_RAM_DATA,
4589 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
4590 }
4591 return;
4592}
4593
4594/*
4595 * Copy 4 bytes to LRAM.
4596 *
4597 * The source data is assumed to be in little-endian order in memory
4598 * and is maintained in little-endian order when writen to LRAM.
4599 */
4600static void
4601AscMemDWordCopyPtrToLram(PortAddr iop_base,
4602 ushort s_addr, uchar *s_buffer, int dwords)
4603{
4604 int i;
4605
4606 AscSetChipLramAddr(iop_base, s_addr);
4607 for (i = 0; i < 4 * dwords; i += 4) {
4608 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
4609 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
4610 }
4611 return;
4612}
4613
4614/*
4615 * Copy 2 bytes from LRAM.
4616 *
4617 * The source data is assumed to be in little-endian order in LRAM
4618 * and is maintained in little-endian order when written to memory.
4619 */
4620static void
4621AscMemWordCopyPtrFromLram(PortAddr iop_base,
4622 ushort s_addr, uchar *d_buffer, int words)
4623{
4624 int i;
4625 ushort word;
4626
4627 AscSetChipLramAddr(iop_base, s_addr);
4628 for (i = 0; i < 2 * words; i += 2) {
4629 word = inpw(iop_base + IOP_RAM_DATA);
4630 d_buffer[i] = word & 0xff;
4631 d_buffer[i + 1] = (word >> 8) & 0xff;
4632 }
4633 return;
4634}
4635
4636static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
4637{
4638 ASC_DCNT sum;
4639 int i;
4640
4641 sum = 0L;
4642 for (i = 0; i < words; i++, s_addr += 2) {
4643 sum += AscReadLramWord(iop_base, s_addr);
4644 }
4645 return (sum);
4646}
4647
4648static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
4649{
4650 uchar i;
4651 ushort s_addr;
4652 PortAddr iop_base;
4653 ushort warn_code;
4654
4655 iop_base = asc_dvc->iop_base;
4656 warn_code = 0;
4657 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
4658 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
4659 64) >> 1));
4660 i = ASC_MIN_ACTIVE_QNO;
4661 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
4662 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4663 (uchar)(i + 1));
4664 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4665 (uchar)(asc_dvc->max_total_qng));
4666 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4667 (uchar)i);
4668 i++;
4669 s_addr += ASC_QBLK_SIZE;
4670 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
4671 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4672 (uchar)(i + 1));
4673 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4674 (uchar)(i - 1));
4675 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4676 (uchar)i);
4677 }
4678 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4679 (uchar)ASC_QLINK_END);
4680 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4681 (uchar)(asc_dvc->max_total_qng - 1));
4682 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4683 (uchar)asc_dvc->max_total_qng);
4684 i++;
4685 s_addr += ASC_QBLK_SIZE;
4686 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
4687 i++, s_addr += ASC_QBLK_SIZE) {
4688 AscWriteLramByte(iop_base,
4689 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
4690 AscWriteLramByte(iop_base,
4691 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
4692 AscWriteLramByte(iop_base,
4693 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
4694 }
4695 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696}
4697
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004698static ASC_DCNT
4699AscLoadMicroCode(PortAddr iop_base,
4700 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004702 ASC_DCNT chksum;
4703 ushort mcode_word_size;
4704 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004706 /* Write the microcode buffer starting at LRAM address 0. */
4707 mcode_word_size = (ushort)(mcode_size >> 1);
4708 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
4709 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004711 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004712 ASC_DBG(1, "chksum 0x%lx\n", (ulong)chksum);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004713 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
4714 (ushort)ASC_CODE_SEC_BEG,
4715 (ushort)((mcode_size -
4716 s_addr - (ushort)
4717 ASC_CODE_SEC_BEG) /
4718 2));
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004719 ASC_DBG(1, "mcode_chksum 0x%lx\n", (ulong)mcode_chksum);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004720 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
4721 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04004722 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723}
4724
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004726static uchar _asc_mcode_buf[] = {
4727 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004728 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
4733 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4734 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004735 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004736 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
4737 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
4738 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004739 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004740 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
4741 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
4742 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004743 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004744 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
4745 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
4746 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004747 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004748 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
4749 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
4750 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004751 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004752 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
4753 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
4754 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004755 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004756 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
4757 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
4758 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004759 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004760 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
4761 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
4762 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004763 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004764 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
4765 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
4766 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004767 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004768 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
4769 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
4770 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004771 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004772 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
4773 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
4774 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004775 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004776 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
4777 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
4778 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004779 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004780 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
4781 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
4782 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004783 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004784 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
4785 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
4786 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004787 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004788 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
4789 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
4790 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004791 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004792 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
4793 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
4794 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004795 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004796 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
4797 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
4798 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004799 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004800 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
4801 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
4802 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004803 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004804 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
4805 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
4806 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004807 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004808 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
4809 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
4810 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004811 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004812 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
4813 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
4814 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004815 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004816 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
4817 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
4818 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004819 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004820 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
4821 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
4822 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004823 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004824 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
4825 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
4826 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004827 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004828 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
4829 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
4830 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004831 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004832 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
4833 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
4834 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004835 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004836 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
4837 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
4838 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004839 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004840 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
4841 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
4842 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004843 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004844 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
4845 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
4846 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004847 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004848 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
4849 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
4850 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004851 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004852 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
4853 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
4854 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004855 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004856 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
4857 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
4858 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004859 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004860 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
4861 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
4862 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004863 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004864 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
4865 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
4866 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004867 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004868 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
4869 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
4870 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004871 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004872 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
4873 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
4874 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004875 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004876 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
4877 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
4878 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004879 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004880 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
4881 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
4882 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004883 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004884 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
4885 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
4886 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004887 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004888 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
4889 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
4890 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004891 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004892 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
4893 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
4894 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004895 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004896 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
4897 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
4898 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004899 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004900 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
4901 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
4902 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004903 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004904 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
4905 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
4906 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004907 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004908 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
4909 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
4910 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004911 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004912 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
4913 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
4914 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004915 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004916 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
4917 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
4918 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919};
4920
Matthew Wilcox51219352007-10-02 21:55:22 -04004921static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004922static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004925static unsigned char _adv_asc3550_buf[] = {
4926 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004927 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
4928 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
4929 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004930 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004931 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
4932 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
4933 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004934 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004935 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
4936 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
4937 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004938 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004939 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
4940 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
4941 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004942 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004943 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
4944 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
4945 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004946 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004947 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
4948 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
4949 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004950 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004951 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
4952 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
4953 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004954 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004955 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
4956 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
4957 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004958 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004959 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
4960 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
4961 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004962 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004963 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
4964 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
4965 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004966 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004967 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
4968 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
4969 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004970 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004971 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
4972 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
4973 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004974 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004975 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
4976 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
4977 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004978 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004979 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
4980 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
4981 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004982 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004983 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
4984 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
4985 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004986 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004987 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
4988 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
4989 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004990 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004991 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
4992 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
4993 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004994 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004995 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
4996 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
4997 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004998 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004999 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
5000 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
5001 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005002 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005003 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
5004 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
5005 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005006 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005007 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
5008 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
5009 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005010 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005011 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
5012 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
5013 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005014 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005015 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
5016 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
5017 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005018 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005019 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
5020 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
5021 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005022 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005023 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
5024 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
5025 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005026 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005027 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
5028 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
5029 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005030 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005031 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
5032 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
5033 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005034 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005035 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
5036 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
5037 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005038 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005039 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
5040 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
5041 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005042 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005043 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
5044 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
5045 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005046 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005047 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
5048 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
5049 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005050 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005051 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
5052 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
5053 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005054 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005055 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
5056 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
5057 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005058 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005059 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
5060 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
5061 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005062 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005063 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
5064 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
5065 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005066 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005067 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
5068 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
5069 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005070 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005071 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5072 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
5073 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005074 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005075 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
5076 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
5077 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005078 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005079 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
5080 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
5081 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005082 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005083 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
5084 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
5085 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005086 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005087 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
5088 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
5089 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005090 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005091 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
5092 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
5093 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005094 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005095 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
5096 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
5097 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005098 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005099 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
5100 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
5101 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005102 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005103 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
5104 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
5105 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005106 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005107 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
5108 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
5109 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005110 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005111 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
5112 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
5113 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005114 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005115 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
5116 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
5117 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005118 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005119 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
5120 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
5121 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005122 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005123 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
5124 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
5125 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005126 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005127 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
5128 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
5129 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005130 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005131 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
5132 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
5133 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005134 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005135 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
5136 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
5137 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005138 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005139 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
5140 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
5141 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005142 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005143 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
5144 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
5145 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005146 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005147 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
5148 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
5149 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005150 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005151 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
5152 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
5153 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005154 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005155 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
5156 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
5157 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005158 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005159 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
5160 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
5161 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005162 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005163 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
5164 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
5165 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005166 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005167 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
5168 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
5169 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005170 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005171 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
5172 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
5173 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005174 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005175 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
5176 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
5177 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005178 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005179 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
5180 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
5181 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005182 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005183 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
5184 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
5185 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005186 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005187 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
5188 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
5189 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005190 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005191 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
5192 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
5193 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005194 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005195 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
5196 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
5197 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005198 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005199 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
5200 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
5201 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005202 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005203 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
5204 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
5205 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005206 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005207 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
5208 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
5209 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005210 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005211 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
5212 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
5213 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005214 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005215 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
5216 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
5217 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005218 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005219 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
5220 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
5221 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005222 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005223 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
5224 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
5225 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005226 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005227 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
5228 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
5229 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005230 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005231 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
5232 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
5233 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005234 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005235 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
5236 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
5237 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005238 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005239 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
5240 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
5241 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005242 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005243 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
5244 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
5245 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005246 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005247 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
5248 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
5249 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005250 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005251 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
5252 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
5253 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005254 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005255 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
5256 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
5257 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005258 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005259 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
5260 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
5261 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005262 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005263 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
5264 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
5265 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005266 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005267 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
5268 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
5269 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005270 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005271 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
5272 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
5273 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005274 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005275 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
5276 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
5277 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005278 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005279 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
5280 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
5281 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005282 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005283 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
5284 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
5285 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005286 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005287 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
5288 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
5289 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005290 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005291 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
5292 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
5293 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005294 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005295 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
5296 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
5297 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005298 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005299 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
5300 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
5301 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005302 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005303 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
5304 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
5305 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005306 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005307 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
5308 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
5309 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005310 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005311 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
5312 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
5313 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005314 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005315 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
5316 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
5317 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005318 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005319 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
5320 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
5321 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005322 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005323 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
5324 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
5325 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005326 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005327 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
5328 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
5329 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005330 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005331 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
5332 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
5333 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005334 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005335 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
5336 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
5337 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005338 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005339 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
5340 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
5341 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005342 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005343 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
5344 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345};
5346
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005347static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
5348static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
5350/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005351static unsigned char _adv_asc38C0800_buf[] = {
5352 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005353 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
5354 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
5355 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005356 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005357 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
5358 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
5359 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005360 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005361 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
5362 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
5363 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005364 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005365 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
5366 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
5367 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005368 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005369 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
5370 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
5371 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005372 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005373 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
5374 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
5375 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005376 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005377 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
5378 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
5379 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005380 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005381 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
5382 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
5383 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005384 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005385 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
5386 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
5387 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005388 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005389 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
5390 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
5391 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005392 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005393 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
5394 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
5395 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005396 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005397 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
5398 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5399 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005400 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005401 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
5402 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
5403 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005404 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005405 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
5406 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5407 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005408 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005409 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
5410 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
5411 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005412 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005413 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
5414 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
5415 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005416 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005417 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
5418 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
5419 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005420 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005421 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
5422 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
5423 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005424 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005425 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
5426 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
5427 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005428 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005429 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
5430 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
5431 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005432 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005433 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
5434 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
5435 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005436 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005437 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
5438 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
5439 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005440 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005441 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
5442 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
5443 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005444 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005445 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
5446 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
5447 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005448 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005449 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
5450 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
5451 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005452 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005453 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
5454 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
5455 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005456 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005457 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
5458 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
5459 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005460 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005461 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
5462 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
5463 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005464 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005465 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
5466 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
5467 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005468 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005469 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
5470 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
5471 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005472 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005473 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
5474 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
5475 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005476 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005477 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
5478 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
5479 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005480 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005481 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
5482 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
5483 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005485 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
5486 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
5487 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005488 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005489 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
5490 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
5491 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005492 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005493 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
5494 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
5495 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005496 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005497 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
5498 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
5499 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005500 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005501 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
5502 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
5503 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005504 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005505 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
5506 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
5507 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005508 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005509 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
5510 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
5511 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005512 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005513 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
5514 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
5515 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005516 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005517 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
5518 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
5519 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005520 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005521 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
5522 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
5523 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005524 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005525 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
5526 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
5527 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005528 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005529 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
5530 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
5531 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005532 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005533 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
5534 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
5535 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005536 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005537 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
5538 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
5539 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005540 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005541 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
5542 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
5543 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005544 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005545 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
5546 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
5547 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005548 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005549 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
5550 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
5551 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005552 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005553 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
5554 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
5555 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005556 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005557 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
5558 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
5559 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005560 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005561 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
5562 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
5563 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005564 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005565 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
5566 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
5567 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005568 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005569 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
5570 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
5571 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005572 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005573 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
5574 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
5575 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005576 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005577 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
5578 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
5579 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005580 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005581 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
5582 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
5583 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005584 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005585 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
5586 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
5587 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005588 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005589 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
5590 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
5591 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005592 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005593 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
5594 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
5595 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005596 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005597 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
5598 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
5599 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005600 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005601 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
5602 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
5603 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005604 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005605 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
5606 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
5607 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005608 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005609 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
5610 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
5611 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005612 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005613 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
5614 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
5615 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005616 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005617 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
5618 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
5619 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005620 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005621 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
5622 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
5623 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005624 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005625 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
5626 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
5627 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005628 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005629 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
5630 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
5631 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005632 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005633 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
5634 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
5635 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005636 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005637 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
5638 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
5639 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005640 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005641 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
5642 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
5643 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005644 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005645 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
5646 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
5647 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005648 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005649 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
5650 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
5651 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005652 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005653 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
5654 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
5655 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005656 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005657 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
5658 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
5659 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005660 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005661 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
5662 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
5663 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005664 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005665 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
5666 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
5667 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005668 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005669 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
5670 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
5671 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005672 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005673 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
5674 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
5675 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005676 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005677 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
5678 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
5679 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005680 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005681 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
5682 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
5683 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005684 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005685 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
5686 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
5687 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005688 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005689 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
5690 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
5691 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005692 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005693 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
5694 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
5695 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005696 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005697 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
5698 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5699 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005700 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005701 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5702 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
5703 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005704 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005705 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
5706 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
5707 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005708 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005709 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
5710 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
5711 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005712 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005713 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
5714 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
5715 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005716 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005717 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
5718 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
5719 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005720 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005721 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
5722 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
5723 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005724 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005725 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
5726 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
5727 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005728 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005729 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
5730 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
5731 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005732 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005733 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
5734 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
5735 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005736 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005737 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
5738 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
5739 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005740 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005741 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
5742 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
5743 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005744 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005745 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
5746 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
5747 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005748 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005749 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
5750 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
5751 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005752 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005753 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
5754 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
5755 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005756 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005757 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
5758 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
5759 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005760 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005761 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
5762 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
5763 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005764 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005765 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
5766 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
5767 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005768 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005769 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
5770 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
5771 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005772 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005773 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
5774 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
5775 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005776 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005777 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
5778 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
5779 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005780 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005781 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
5782 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
5783 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005784 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005785 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
5786 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
5787 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005788 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005789 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
5790 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
5791 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005792 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005793 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
5794 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
5795 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005796 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797};
5798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005799static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
5800static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801
5802/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005803static unsigned char _adv_asc38C1600_buf[] = {
5804 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005805 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
5806 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
5807 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005808 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005809 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
5810 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
5811 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005812 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005813 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
5814 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
5815 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005816 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005817 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
5818 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
5819 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005820 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005821 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
5822 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
5823 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005824 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005825 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
5826 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
5827 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005828 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005829 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
5830 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
5831 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005832 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005833 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
5834 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
5835 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005836 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005837 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
5838 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
5839 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005840 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005841 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
5842 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
5843 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005844 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005845 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
5846 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
5847 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005848 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005849 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
5850 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5851 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005852 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005853 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
5854 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
5855 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005856 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005857 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
5858 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
5859 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005860 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005861 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
5862 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
5863 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005864 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005865 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
5866 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
5867 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005868 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005869 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
5870 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
5871 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005872 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005873 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
5874 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
5875 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005876 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005877 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
5878 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
5879 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005880 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005881 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
5882 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
5883 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005884 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005885 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
5886 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
5887 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005888 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005889 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
5890 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
5891 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005892 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005893 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
5894 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
5895 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005896 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005897 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
5898 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
5899 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005900 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005901 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
5902 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
5903 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005904 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005905 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
5906 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
5907 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005908 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005909 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
5910 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
5911 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005912 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005913 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
5914 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
5915 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005916 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005917 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
5918 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
5919 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005920 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005921 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
5922 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
5923 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005924 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005925 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
5926 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
5927 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005928 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005929 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
5930 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
5931 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005932 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005933 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
5934 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
5935 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005936 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005937 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
5938 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
5939 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005940 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005941 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
5942 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
5943 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005944 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005945 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
5946 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
5947 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005948 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005949 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
5950 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
5951 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005952 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005953 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
5954 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
5955 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005956 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005957 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
5958 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
5959 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005960 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005961 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
5962 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
5963 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005964 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005965 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
5966 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
5967 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005968 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005969 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
5970 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5971 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005972 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005973 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
5974 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
5975 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005976 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005977 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
5978 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
5979 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005980 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005981 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
5982 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
5983 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005984 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005985 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
5986 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
5987 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005988 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005989 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
5990 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
5991 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005992 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005993 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
5994 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
5995 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005996 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005997 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
5998 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
5999 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006000 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006001 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
6002 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
6003 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006004 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006005 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
6006 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
6007 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006008 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006009 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
6010 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
6011 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006012 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006013 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
6014 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
6015 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006016 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006017 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
6018 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
6019 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006020 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006021 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
6022 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
6023 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006024 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006025 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
6026 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
6027 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006028 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006029 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
6030 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
6031 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006032 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006033 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
6034 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
6035 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006036 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006037 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
6038 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
6039 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006040 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006041 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
6042 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
6043 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006044 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006045 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
6046 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
6047 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006048 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006049 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
6050 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
6051 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006052 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006053 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
6054 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
6055 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006056 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006057 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
6058 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
6059 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006060 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006061 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
6062 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
6063 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006064 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006065 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
6066 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
6067 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006068 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006069 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
6070 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
6071 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006072 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006073 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
6074 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
6075 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006076 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006077 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
6078 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
6079 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006080 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006081 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
6082 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
6083 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006084 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006085 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
6086 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
6087 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006088 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006089 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
6090 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
6091 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006092 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006093 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
6094 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
6095 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006096 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006097 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
6098 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
6099 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006100 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006101 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
6102 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
6103 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006104 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006105 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
6106 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
6107 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006108 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006109 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
6110 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
6111 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006112 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006113 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
6114 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
6115 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006116 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006117 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
6118 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
6119 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006120 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006121 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
6122 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
6123 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006124 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006125 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
6126 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
6127 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006128 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006129 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
6130 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
6131 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006132 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006133 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
6134 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
6135 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006136 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006137 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
6138 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
6139 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006140 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006141 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
6142 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
6143 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006144 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006145 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
6146 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
6147 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006148 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006149 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
6150 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
6151 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006152 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006153 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
6154 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
6155 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006156 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006157 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
6158 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
6159 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006160 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006161 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
6162 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
6163 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006164 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006165 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
6166 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
6167 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006168 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006169 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
6170 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
6171 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006172 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006173 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
6174 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
6175 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006176 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006177 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
6178 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
6179 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006180 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006181 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
6182 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
6183 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006184 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006185 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
6186 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
6187 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006188 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006189 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
6190 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
6191 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006192 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006193 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
6194 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
6195 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006196 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006197 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
6198 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
6199 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006200 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006201 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
6202 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
6203 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006204 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006205 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
6206 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
6207 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006208 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006209 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
6210 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
6211 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006212 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006213 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
6214 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
6215 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006216 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006217 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
6218 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
6219 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006220 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006221 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
6222 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
6223 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006224 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006225 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
6226 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
6227 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006228 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006229 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
6230 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
6231 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006232 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006233 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
6234 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
6235 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006236 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006237 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
6238 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
6239 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006240 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006241 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
6242 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
6243 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006244 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006245 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
6246 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
6247 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006248 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006249 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
6250 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
6251 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006252 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006253 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
6254 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
6255 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006256 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006257 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
6258 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
6259 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006260 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006261 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
6262 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
6263 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006264 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006265 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
6266 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
6267 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006268 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006269 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
6270 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
6271 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006272 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006273 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
6274 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
6275 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006276 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006277 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
6278 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
6279 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006280 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006281 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
6282 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
6283 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006284 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006285 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
6286 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
6287 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006288 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006289 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
6290 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
6291 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006292 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006293 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
6294 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
6295 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006296 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006297 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
6298 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
6299 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006300 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006301 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
6302 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
6303 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006304 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006305 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
6306 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
6307 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006308 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006309 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
6310 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
6311 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006312 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006313 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
6314 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
6315 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006316 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006317 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
6318 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
6319 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006321 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
6322 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
6323 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006324 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006325 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
6326 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
6327 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006328 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006329 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
6330 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
6331 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332};
6333
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006334static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
6335static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336
Matthew Wilcox51219352007-10-02 21:55:22 -04006337static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338{
Matthew Wilcox51219352007-10-02 21:55:22 -04006339 PortAddr iop_base;
6340 int i;
6341 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006342
Matthew Wilcox51219352007-10-02 21:55:22 -04006343 iop_base = asc_dvc->iop_base;
6344 AscPutRiscVarFreeQHead(iop_base, 1);
6345 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6346 AscPutVarFreeQHead(iop_base, 1);
6347 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6348 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6349 (uchar)((int)asc_dvc->max_total_qng + 1));
6350 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6351 (uchar)((int)asc_dvc->max_total_qng + 2));
6352 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
6353 asc_dvc->max_total_qng);
6354 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6355 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6356 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6357 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6358 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6359 AscPutQDoneInProgress(iop_base, 0);
6360 lram_addr = ASC_QADR_BEG;
6361 for (i = 0; i < 32; i++, lram_addr += 2) {
6362 AscWriteLramWord(iop_base, lram_addr, 0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364}
6365
Matthew Wilcox51219352007-10-02 21:55:22 -04006366static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006367{
Matthew Wilcox51219352007-10-02 21:55:22 -04006368 int i;
6369 ushort warn_code;
6370 PortAddr iop_base;
6371 ASC_PADDR phy_addr;
6372 ASC_DCNT phy_size;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006373
Matthew Wilcox51219352007-10-02 21:55:22 -04006374 iop_base = asc_dvc->iop_base;
6375 warn_code = 0;
6376 for (i = 0; i <= ASC_MAX_TID; i++) {
6377 AscPutMCodeInitSDTRAtID(iop_base, i,
6378 asc_dvc->cfg->sdtr_period_offset[i]);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006379 }
6380
Matthew Wilcox51219352007-10-02 21:55:22 -04006381 AscInitQLinkVar(asc_dvc);
6382 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
6383 asc_dvc->cfg->disc_enable);
6384 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
6385 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006386
Matthew Wilcox51219352007-10-02 21:55:22 -04006387 /* Align overrun buffer on an 8 byte boundary. */
6388 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
6389 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
6390 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
6391 (uchar *)&phy_addr, 1);
6392 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
6393 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
6394 (uchar *)&phy_size, 1);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006395
Matthew Wilcox51219352007-10-02 21:55:22 -04006396 asc_dvc->cfg->mcode_date =
6397 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
6398 asc_dvc->cfg->mcode_version =
6399 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006400
Matthew Wilcox51219352007-10-02 21:55:22 -04006401 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6402 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6403 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
6404 return warn_code;
6405 }
6406 if (AscStartChip(iop_base) != 1) {
6407 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
6408 return warn_code;
6409 }
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006410
Matthew Wilcox51219352007-10-02 21:55:22 -04006411 return warn_code;
6412}
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006413
Matthew Wilcox51219352007-10-02 21:55:22 -04006414static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
6415{
6416 ushort warn_code;
6417 PortAddr iop_base;
6418
6419 iop_base = asc_dvc->iop_base;
6420 warn_code = 0;
6421 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
6422 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
6423 AscResetChipAndScsiBus(asc_dvc);
6424 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6425 }
6426 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
6427 if (asc_dvc->err_code != 0)
6428 return UW_ERR;
6429 if (!AscFindSignature(asc_dvc->iop_base)) {
6430 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
6431 return warn_code;
6432 }
6433 AscDisableInterrupt(iop_base);
6434 warn_code |= AscInitLram(asc_dvc);
6435 if (asc_dvc->err_code != 0)
6436 return UW_ERR;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04006437 ASC_DBG(1, "_asc_mcode_chksum 0x%lx\n", (ulong)_asc_mcode_chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -04006438 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
6439 _asc_mcode_size) != _asc_mcode_chksum) {
6440 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
6441 return warn_code;
6442 }
6443 warn_code |= AscInitMicroCodeVar(asc_dvc);
6444 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
6445 AscEnableInterrupt(iop_base);
6446 return warn_code;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006447}
6448
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006450 * Load the Microcode
6451 *
6452 * Write the microcode image to RISC memory starting at address 0.
6453 *
6454 * The microcode is stored compressed in the following format:
6455 *
6456 * 254 word (508 byte) table indexed by byte code followed
6457 * by the following byte codes:
6458 *
6459 * 1-Byte Code:
6460 * 00: Emit word 0 in table.
6461 * 01: Emit word 1 in table.
6462 * .
6463 * FD: Emit word 253 in table.
6464 *
6465 * Multi-Byte Code:
6466 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
6467 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
6468 *
6469 * Returns 0 or an error if the checksum doesn't match
6470 */
6471static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
6472 int memsize, int chksum)
6473{
6474 int i, j, end, len = 0;
6475 ADV_DCNT sum;
6476
6477 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6478
6479 for (i = 253 * 2; i < size; i++) {
6480 if (buf[i] == 0xff) {
6481 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
6482 for (j = 0; j < buf[i + 1]; j++) {
6483 AdvWriteWordAutoIncLram(iop_base, word);
6484 len += 2;
6485 }
6486 i += 3;
6487 } else if (buf[i] == 0xfe) {
6488 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
6489 AdvWriteWordAutoIncLram(iop_base, word);
6490 i += 2;
6491 len += 2;
6492 } else {
6493 unsigned char off = buf[i] * 2;
6494 unsigned short word = (buf[off + 1] << 8) | buf[off];
6495 AdvWriteWordAutoIncLram(iop_base, word);
6496 len += 2;
6497 }
6498 }
6499
6500 end = len;
6501
6502 while (len < memsize) {
6503 AdvWriteWordAutoIncLram(iop_base, 0);
6504 len += 2;
6505 }
6506
6507 /* Verify the microcode checksum. */
6508 sum = 0;
6509 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6510
6511 for (len = 0; len < end; len += 2) {
6512 sum += AdvReadWordAutoIncLram(iop_base);
6513 }
6514
6515 if (sum != chksum)
6516 return ASC_IERR_MCODE_CHKSUM;
6517
6518 return 0;
6519}
6520
6521/*
Matthew Wilcox51219352007-10-02 21:55:22 -04006522 * DvcGetPhyAddr()
6523 *
6524 * Return the physical address of 'vaddr' and set '*lenp' to the
6525 * number of physically contiguous bytes that follow 'vaddr'.
6526 * 'flag' indicates the type of structure whose physical address
6527 * is being translated.
6528 *
6529 * Note: Because Linux currently doesn't page the kernel and all
6530 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
6531 */
6532ADV_PADDR
6533DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
6534 uchar *vaddr, ADV_SDCNT *lenp, int flag)
6535{
6536 ADV_PADDR paddr = virt_to_bus(vaddr);
6537
Matthew Wilcoxb352f922007-10-02 21:55:33 -04006538 ASC_DBG(4, "vaddr 0x%p, lenp 0x%p *lenp %lu, paddr 0x%lx\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04006539 vaddr, lenp, (ulong)*((ulong *)lenp), (ulong)paddr);
6540
6541 return paddr;
6542}
6543
6544static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
6545{
6546 ADV_CARR_T *carrp;
6547 ADV_SDCNT buf_size;
6548 ADV_PADDR carr_paddr;
6549
6550 BUG_ON(!asc_dvc->carrier_buf);
6551
6552 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
6553 asc_dvc->carr_freelist = NULL;
6554 if (carrp == asc_dvc->carrier_buf) {
6555 buf_size = ADV_CARRIER_BUFSIZE;
6556 } else {
6557 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
6558 }
6559
6560 do {
6561 /* Get physical address of the carrier 'carrp'. */
6562 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
6563 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
6564 (uchar *)carrp,
6565 (ADV_SDCNT *)&contig_len,
6566 ADV_IS_CARRIER_FLAG));
6567
6568 buf_size -= sizeof(ADV_CARR_T);
6569
6570 /*
6571 * If the current carrier is not physically contiguous, then
6572 * maybe there was a page crossing. Try the next carrier
6573 * aligned start address.
6574 */
6575 if (contig_len < sizeof(ADV_CARR_T)) {
6576 carrp++;
6577 continue;
6578 }
6579
6580 carrp->carr_pa = carr_paddr;
6581 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
6582
6583 /*
6584 * Insert the carrier at the beginning of the freelist.
6585 */
6586 carrp->next_vpa =
6587 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
6588 asc_dvc->carr_freelist = carrp;
6589
6590 carrp++;
6591 } while (buf_size > 0);
6592}
6593
6594/*
6595 * Send an idle command to the chip and wait for completion.
6596 *
6597 * Command completion is polled for once per microsecond.
6598 *
6599 * The function can be called from anywhere including an interrupt handler.
6600 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
6601 * functions to prevent reentrancy.
6602 *
6603 * Return Values:
6604 * ADV_TRUE - command completed successfully
6605 * ADV_FALSE - command failed
6606 * ADV_ERROR - command timed out
6607 */
6608static int
6609AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
6610 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
6611{
6612 int result;
6613 ADV_DCNT i, j;
6614 AdvPortAddr iop_base;
6615
6616 iop_base = asc_dvc->iop_base;
6617
6618 /*
6619 * Clear the idle command status which is set by the microcode
6620 * to a non-zero value to indicate when the command is completed.
6621 * The non-zero result is one of the IDLE_CMD_STATUS_* values
6622 */
6623 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
6624
6625 /*
6626 * Write the idle command value after the idle command parameter
6627 * has been written to avoid a race condition. If the order is not
6628 * followed, the microcode may process the idle command before the
6629 * parameters have been written to LRAM.
6630 */
6631 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
6632 cpu_to_le32(idle_cmd_parameter));
6633 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
6634
6635 /*
6636 * Tickle the RISC to tell it to process the idle command.
6637 */
6638 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
6639 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
6640 /*
6641 * Clear the tickle value. In the ASC-3550 the RISC flag
6642 * command 'clr_tickle_b' does not work unless the host
6643 * value is cleared.
6644 */
6645 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
6646 }
6647
6648 /* Wait for up to 100 millisecond for the idle command to timeout. */
6649 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
6650 /* Poll once each microsecond for command completion. */
6651 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
6652 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
6653 result);
6654 if (result != 0)
6655 return result;
6656 udelay(1);
6657 }
6658 }
6659
6660 BUG(); /* The idle command should never timeout. */
6661 return ADV_ERROR;
6662}
6663
6664/*
6665 * Reset SCSI Bus and purge all outstanding requests.
6666 *
6667 * Return Value:
6668 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
6669 * ADV_FALSE(0) - Microcode command failed.
6670 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
6671 * may be hung which requires driver recovery.
6672 */
6673static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
6674{
6675 int status;
6676
6677 /*
6678 * Send the SCSI Bus Reset idle start idle command which asserts
6679 * the SCSI Bus Reset signal.
6680 */
6681 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
6682 if (status != ADV_TRUE) {
6683 return status;
6684 }
6685
6686 /*
6687 * Delay for the specified SCSI Bus Reset hold time.
6688 *
6689 * The hold time delay is done on the host because the RISC has no
6690 * microsecond accurate timer.
6691 */
6692 udelay(ASC_SCSI_RESET_HOLD_TIME_US);
6693
6694 /*
6695 * Send the SCSI Bus Reset end idle command which de-asserts
6696 * the SCSI Bus Reset signal and purges any pending requests.
6697 */
6698 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
6699 if (status != ADV_TRUE) {
6700 return status;
6701 }
6702
6703 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6704
6705 return status;
6706}
6707
6708/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006709 * Initialize the ASC-3550.
6710 *
6711 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
6712 *
6713 * For a non-fatal error return a warning code. If there are no warnings
6714 * then 0 is returned.
6715 *
6716 * Needed after initialization for error recovery.
6717 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006718static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006719{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006720 AdvPortAddr iop_base;
6721 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006722 int begin_addr;
6723 int end_addr;
6724 ushort code_sum;
6725 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006726 int i;
6727 ushort scsi_cfg1;
6728 uchar tid;
6729 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
6730 ushort wdtr_able = 0, sdtr_able, tagqng_able;
6731 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006732
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006733 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006734 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006735 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006737 /*
6738 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
6739 */
6740 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006741 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006742 return ADV_ERROR;
6743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006745 warn_code = 0;
6746 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006747
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006748 /*
6749 * Save the RISC memory BIOS region before writing the microcode.
6750 * The BIOS may already be loaded and using its RISC LRAM region
6751 * so its region must be saved and restored.
6752 *
6753 * Note: This code makes the assumption, which is currently true,
6754 * that a chip reset does not clear RISC LRAM.
6755 */
6756 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6757 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6758 bios_mem[i]);
6759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006761 /*
6762 * Save current per TID negotiated values.
6763 */
6764 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
6765 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006767 bios_version =
6768 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
6769 major = (bios_version >> 12) & 0xF;
6770 minor = (bios_version >> 8) & 0xF;
6771 if (major < 3 || (major == 3 && minor == 1)) {
6772 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
6773 AdvReadWordLram(iop_base, 0x120, wdtr_able);
6774 } else {
6775 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6776 }
6777 }
6778 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
6779 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6780 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6781 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
6782 max_cmd[tid]);
6783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006784
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006785 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
6786 _adv_asc3550_size, ADV_3550_MEMSIZE,
6787 _adv_asc3550_chksum);
6788 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006789 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006790
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006791 /*
6792 * Restore the RISC memory BIOS region.
6793 */
6794 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6795 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6796 bios_mem[i]);
6797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006799 /*
6800 * Calculate and write the microcode code checksum to the microcode
6801 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
6802 */
6803 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
6804 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
6805 code_sum = 0;
6806 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
6807 for (word = begin_addr; word < end_addr; word += 2) {
6808 code_sum += AdvReadWordAutoIncLram(iop_base);
6809 }
6810 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006811
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006812 /*
6813 * Read and save microcode version and date.
6814 */
6815 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
6816 asc_dvc->cfg->mcode_date);
6817 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
6818 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006820 /*
6821 * Set the chip type to indicate the ASC3550.
6822 */
6823 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006824
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006825 /*
6826 * If the PCI Configuration Command Register "Parity Error Response
6827 * Control" Bit was clear (0), then set the microcode variable
6828 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
6829 * to ignore DMA parity errors.
6830 */
6831 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
6832 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6833 word |= CONTROL_FLAG_IGNORE_PERR;
6834 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006837 /*
6838 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
6839 * threshold of 128 bytes. This register is only accessible to the host.
6840 */
6841 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
6842 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006844 /*
6845 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006846 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006847 * device reports it is capable of in Inquiry byte 7.
6848 *
6849 * If SCSI Bus Resets have been disabled, then directly set
6850 * SDTR and WDTR from the EEPROM configuration. This will allow
6851 * the BIOS and warm boot to work without a SCSI bus hang on
6852 * the Inquiry caused by host and target mismatched DTR values.
6853 * Without the SCSI Bus Reset, before an Inquiry a device can't
6854 * be assumed to be in Asynchronous, Narrow mode.
6855 */
6856 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
6857 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
6858 asc_dvc->wdtr_able);
6859 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
6860 asc_dvc->sdtr_able);
6861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006863 /*
6864 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
6865 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
6866 * bitmask. These values determine the maximum SDTR speed negotiated
6867 * with a device.
6868 *
6869 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
6870 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
6871 * without determining here whether the device supports SDTR.
6872 *
6873 * 4-bit speed SDTR speed name
6874 * =========== ===============
6875 * 0000b (0x0) SDTR disabled
6876 * 0001b (0x1) 5 Mhz
6877 * 0010b (0x2) 10 Mhz
6878 * 0011b (0x3) 20 Mhz (Ultra)
6879 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
6880 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
6881 * 0110b (0x6) Undefined
6882 * .
6883 * 1111b (0xF) Undefined
6884 */
6885 word = 0;
6886 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6887 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
6888 /* Set Ultra speed for TID 'tid'. */
6889 word |= (0x3 << (4 * (tid % 4)));
6890 } else {
6891 /* Set Fast speed for TID 'tid'. */
6892 word |= (0x2 << (4 * (tid % 4)));
6893 }
6894 if (tid == 3) { /* Check if done with sdtr_speed1. */
6895 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
6896 word = 0;
6897 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
6898 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
6899 word = 0;
6900 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
6901 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
6902 word = 0;
6903 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
6904 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
6905 /* End of loop. */
6906 }
6907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006908
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006909 /*
6910 * Set microcode operating variable for the disconnect per TID bitmask.
6911 */
6912 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
6913 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006915 /*
6916 * Set SCSI_CFG0 Microcode Default Value.
6917 *
6918 * The microcode will set the SCSI_CFG0 register using this value
6919 * after it is started below.
6920 */
6921 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
6922 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
6923 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006925 /*
6926 * Determine SCSI_CFG1 Microcode Default Value.
6927 *
6928 * The microcode will set the SCSI_CFG1 register using this value
6929 * after it is started below.
6930 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006932 /* Read current SCSI_CFG1 Register value. */
6933 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006935 /*
6936 * If all three connectors are in use, return an error.
6937 */
6938 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
6939 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
6940 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
6941 return ADV_ERROR;
6942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006944 /*
6945 * If the internal narrow cable is reversed all of the SCSI_CTRL
6946 * register signals will be set. Check for and return an error if
6947 * this condition is found.
6948 */
6949 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
6950 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
6951 return ADV_ERROR;
6952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006954 /*
6955 * If this is a differential board and a single-ended device
6956 * is attached to one of the connectors, return an error.
6957 */
6958 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
6959 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
6960 return ADV_ERROR;
6961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006963 /*
6964 * If automatic termination control is enabled, then set the
6965 * termination value based on a table listed in a_condor.h.
6966 *
6967 * If manual termination was specified with an EEPROM setting
6968 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
6969 * is ready to be 'ored' into SCSI_CFG1.
6970 */
6971 if (asc_dvc->cfg->termination == 0) {
6972 /*
6973 * The software always controls termination by setting TERM_CTL_SEL.
6974 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
6975 */
6976 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006978 switch (scsi_cfg1 & CABLE_DETECT) {
6979 /* TERM_CTL_H: on, TERM_CTL_L: on */
6980 case 0x3:
6981 case 0x7:
6982 case 0xB:
6983 case 0xD:
6984 case 0xE:
6985 case 0xF:
6986 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
6987 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006989 /* TERM_CTL_H: on, TERM_CTL_L: off */
6990 case 0x1:
6991 case 0x5:
6992 case 0x9:
6993 case 0xA:
6994 case 0xC:
6995 asc_dvc->cfg->termination |= TERM_CTL_H;
6996 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006997
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006998 /* TERM_CTL_H: off, TERM_CTL_L: off */
6999 case 0x2:
7000 case 0x6:
7001 break;
7002 }
7003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007004
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007005 /*
7006 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
7007 */
7008 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007009
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007010 /*
7011 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
7012 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
7013 * referenced, because the hardware internally inverts
7014 * the Termination High and Low bits if TERM_POL is set.
7015 */
7016 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007018 /*
7019 * Set SCSI_CFG1 Microcode Default Value
7020 *
7021 * Set filter value and possibly modified termination control
7022 * bits in the Microcode SCSI_CFG1 Register Value.
7023 *
7024 * The microcode will set the SCSI_CFG1 register using this value
7025 * after it is started below.
7026 */
7027 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
7028 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007030 /*
7031 * Set MEM_CFG Microcode Default Value
7032 *
7033 * The microcode will set the MEM_CFG register using this value
7034 * after it is started below.
7035 *
7036 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7037 * are defined.
7038 *
7039 * ASC-3550 has 8KB internal memory.
7040 */
7041 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7042 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007043
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007044 /*
7045 * Set SEL_MASK Microcode Default Value
7046 *
7047 * The microcode will set the SEL_MASK register using this value
7048 * after it is started below.
7049 */
7050 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7051 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007052
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007053 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007054
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007055 /*
7056 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7057 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007058
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007059 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7060 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7061 return ADV_ERROR;
7062 }
7063 asc_dvc->carr_freelist = (ADV_CARR_T *)
7064 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007066 /*
7067 * The first command issued will be placed in the stopper carrier.
7068 */
7069 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007071 /*
7072 * Set RISC ICQ physical address start value.
7073 */
7074 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007076 /*
7077 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7078 */
7079 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7080 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7081 return ADV_ERROR;
7082 }
7083 asc_dvc->carr_freelist = (ADV_CARR_T *)
7084 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007086 /*
7087 * The first command completed by the RISC will be placed in
7088 * the stopper.
7089 *
7090 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7091 * completed the RISC will set the ASC_RQ_STOPPER bit.
7092 */
7093 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007095 /*
7096 * Set RISC IRQ physical address start value.
7097 */
7098 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7099 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007101 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7102 (ADV_INTR_ENABLE_HOST_INTR |
7103 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007105 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7106 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007107
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007108 /* finally, finally, gentlemen, start your engine */
7109 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007111 /*
7112 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7113 * Resets should be performed. The RISC has to be running
7114 * to issue a SCSI Bus Reset.
7115 */
7116 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7117 /*
7118 * If the BIOS Signature is present in memory, restore the
7119 * BIOS Handshake Configuration Table and do not perform
7120 * a SCSI Bus Reset.
7121 */
7122 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7123 0x55AA) {
7124 /*
7125 * Restore per TID negotiated values.
7126 */
7127 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7128 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7129 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7130 tagqng_able);
7131 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7132 AdvWriteByteLram(iop_base,
7133 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7134 max_cmd[tid]);
7135 }
7136 } else {
7137 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7138 warn_code = ASC_WARN_BUSRESET_ERROR;
7139 }
7140 }
7141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007143 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007144}
7145
7146/*
7147 * Initialize the ASC-38C0800.
7148 *
7149 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
7150 *
7151 * For a non-fatal error return a warning code. If there are no warnings
7152 * then 0 is returned.
7153 *
7154 * Needed after initialization for error recovery.
7155 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007156static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007157{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007158 AdvPortAddr iop_base;
7159 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007160 int begin_addr;
7161 int end_addr;
7162 ushort code_sum;
7163 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007164 int i;
7165 ushort scsi_cfg1;
7166 uchar byte;
7167 uchar tid;
7168 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7169 ushort wdtr_able, sdtr_able, tagqng_able;
7170 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007171
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007172 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007173 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007174 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007176 /*
7177 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
7178 */
7179 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
7180 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7181 return ADV_ERROR;
7182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007184 warn_code = 0;
7185 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007186
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007187 /*
7188 * Save the RISC memory BIOS region before writing the microcode.
7189 * The BIOS may already be loaded and using its RISC LRAM region
7190 * so its region must be saved and restored.
7191 *
7192 * Note: This code makes the assumption, which is currently true,
7193 * that a chip reset does not clear RISC LRAM.
7194 */
7195 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7196 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7197 bios_mem[i]);
7198 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007200 /*
7201 * Save current per TID negotiated values.
7202 */
7203 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7204 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7205 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7206 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7207 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7208 max_cmd[tid]);
7209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007210
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007211 /*
7212 * RAM BIST (RAM Built-In Self Test)
7213 *
7214 * Address : I/O base + offset 0x38h register (byte).
7215 * Function: Bit 7-6(RW) : RAM mode
7216 * Normal Mode : 0x00
7217 * Pre-test Mode : 0x40
7218 * RAM Test Mode : 0x80
7219 * Bit 5 : unused
7220 * Bit 4(RO) : Done bit
7221 * Bit 3-0(RO) : Status
7222 * Host Error : 0x08
7223 * Int_RAM Error : 0x04
7224 * RISC Error : 0x02
7225 * SCSI Error : 0x01
7226 * No Error : 0x00
7227 *
7228 * Note: RAM BIST code should be put right here, before loading the
7229 * microcode and after saving the RISC memory BIOS region.
7230 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007231
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007232 /*
7233 * LRAM Pre-test
7234 *
7235 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7236 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7237 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7238 * to NORMAL_MODE, return an error too.
7239 */
7240 for (i = 0; i < 2; i++) {
7241 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007242 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007243 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7244 if ((byte & RAM_TEST_DONE) == 0
7245 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007246 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007247 return ADV_ERROR;
7248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007249
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007250 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007251 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007252 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7253 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007254 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007255 return ADV_ERROR;
7256 }
7257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007259 /*
7260 * LRAM Test - It takes about 1.5 ms to run through the test.
7261 *
7262 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7263 * If Done bit not set or Status not 0, save register byte, set the
7264 * err_code, and return an error.
7265 */
7266 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007267 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007268
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007269 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7270 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7271 /* Get here if Done bit not set or Status not 0. */
7272 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007273 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007274 return ADV_ERROR;
7275 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007277 /* We need to reset back to normal mode after LRAM test passes. */
7278 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007280 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
7281 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
7282 _adv_asc38C0800_chksum);
7283 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007284 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007285
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007286 /*
7287 * Restore the RISC memory BIOS region.
7288 */
7289 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7290 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7291 bios_mem[i]);
7292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007294 /*
7295 * Calculate and write the microcode code checksum to the microcode
7296 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7297 */
7298 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7299 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7300 code_sum = 0;
7301 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7302 for (word = begin_addr; word < end_addr; word += 2) {
7303 code_sum += AdvReadWordAutoIncLram(iop_base);
7304 }
7305 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007307 /*
7308 * Read microcode version and date.
7309 */
7310 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7311 asc_dvc->cfg->mcode_date);
7312 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7313 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007315 /*
7316 * Set the chip type to indicate the ASC38C0800.
7317 */
7318 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007320 /*
7321 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7322 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7323 * cable detection and then we are able to read C_DET[3:0].
7324 *
7325 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7326 * Microcode Default Value' section below.
7327 */
7328 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7329 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7330 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007331
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007332 /*
7333 * If the PCI Configuration Command Register "Parity Error Response
7334 * Control" Bit was clear (0), then set the microcode variable
7335 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7336 * to ignore DMA parity errors.
7337 */
7338 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7339 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7340 word |= CONTROL_FLAG_IGNORE_PERR;
7341 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7342 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007343
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007344 /*
7345 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
7346 * bits for the default FIFO threshold.
7347 *
7348 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
7349 *
7350 * For DMA Errata #4 set the BC_THRESH_ENB bit.
7351 */
7352 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7353 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
7354 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007356 /*
7357 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007358 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007359 * device reports it is capable of in Inquiry byte 7.
7360 *
7361 * If SCSI Bus Resets have been disabled, then directly set
7362 * SDTR and WDTR from the EEPROM configuration. This will allow
7363 * the BIOS and warm boot to work without a SCSI bus hang on
7364 * the Inquiry caused by host and target mismatched DTR values.
7365 * Without the SCSI Bus Reset, before an Inquiry a device can't
7366 * be assumed to be in Asynchronous, Narrow mode.
7367 */
7368 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7369 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7370 asc_dvc->wdtr_able);
7371 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7372 asc_dvc->sdtr_able);
7373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007374
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007375 /*
7376 * Set microcode operating variables for DISC and SDTR_SPEED1,
7377 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7378 * configuration values.
7379 *
7380 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7381 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7382 * without determining here whether the device supports SDTR.
7383 */
7384 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7385 asc_dvc->cfg->disc_enable);
7386 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7387 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7388 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7389 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007391 /*
7392 * Set SCSI_CFG0 Microcode Default Value.
7393 *
7394 * The microcode will set the SCSI_CFG0 register using this value
7395 * after it is started below.
7396 */
7397 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7398 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7399 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007400
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007401 /*
7402 * Determine SCSI_CFG1 Microcode Default Value.
7403 *
7404 * The microcode will set the SCSI_CFG1 register using this value
7405 * after it is started below.
7406 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007407
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007408 /* Read current SCSI_CFG1 Register value. */
7409 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007411 /*
7412 * If the internal narrow cable is reversed all of the SCSI_CTRL
7413 * register signals will be set. Check for and return an error if
7414 * this condition is found.
7415 */
7416 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7417 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7418 return ADV_ERROR;
7419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007420
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007421 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007422 * All kind of combinations of devices attached to one of four
7423 * connectors are acceptable except HVD device attached. For example,
7424 * LVD device can be attached to SE connector while SE device attached
7425 * to LVD connector. If LVD device attached to SE connector, it only
7426 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007427 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007428 * If an HVD device is attached to one of LVD connectors, return an
7429 * error. However, there is no way to detect HVD device attached to
7430 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007431 */
7432 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007433 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007434 return ADV_ERROR;
7435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007436
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007437 /*
7438 * If either SE or LVD automatic termination control is enabled, then
7439 * set the termination value based on a table listed in a_condor.h.
7440 *
7441 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007442 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
7443 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007444 */
7445 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
7446 /* SE automatic termination control is enabled. */
7447 switch (scsi_cfg1 & C_DET_SE) {
7448 /* TERM_SE_HI: on, TERM_SE_LO: on */
7449 case 0x1:
7450 case 0x2:
7451 case 0x3:
7452 asc_dvc->cfg->termination |= TERM_SE;
7453 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007454
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007455 /* TERM_SE_HI: on, TERM_SE_LO: off */
7456 case 0x0:
7457 asc_dvc->cfg->termination |= TERM_SE_HI;
7458 break;
7459 }
7460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007462 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
7463 /* LVD automatic termination control is enabled. */
7464 switch (scsi_cfg1 & C_DET_LVD) {
7465 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
7466 case 0x4:
7467 case 0x8:
7468 case 0xC:
7469 asc_dvc->cfg->termination |= TERM_LVD;
7470 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007471
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007472 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
7473 case 0x0:
7474 break;
7475 }
7476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007477
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007478 /*
7479 * Clear any set TERM_SE and TERM_LVD bits.
7480 */
7481 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007482
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007483 /*
7484 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
7485 */
7486 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007487
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007488 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007489 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
7490 * bits and set possibly modified termination control bits in the
7491 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007492 */
7493 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007494
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007495 /*
7496 * Set SCSI_CFG1 Microcode Default Value
7497 *
7498 * Set possibly modified termination control and reset DIS_TERM_DRV
7499 * bits in the Microcode SCSI_CFG1 Register Value.
7500 *
7501 * The microcode will set the SCSI_CFG1 register using this value
7502 * after it is started below.
7503 */
7504 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007505
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007506 /*
7507 * Set MEM_CFG Microcode Default Value
7508 *
7509 * The microcode will set the MEM_CFG register using this value
7510 * after it is started below.
7511 *
7512 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7513 * are defined.
7514 *
7515 * ASC-38C0800 has 16KB internal memory.
7516 */
7517 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7518 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007520 /*
7521 * Set SEL_MASK Microcode Default Value
7522 *
7523 * The microcode will set the SEL_MASK register using this value
7524 * after it is started below.
7525 */
7526 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7527 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007528
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007529 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007530
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007531 /*
7532 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7533 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007535 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7536 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7537 return ADV_ERROR;
7538 }
7539 asc_dvc->carr_freelist = (ADV_CARR_T *)
7540 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007542 /*
7543 * The first command issued will be placed in the stopper carrier.
7544 */
7545 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007546
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007547 /*
7548 * Set RISC ICQ physical address start value.
7549 * carr_pa is LE, must be native before write
7550 */
7551 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007552
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007553 /*
7554 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7555 */
7556 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7557 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7558 return ADV_ERROR;
7559 }
7560 asc_dvc->carr_freelist = (ADV_CARR_T *)
7561 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007563 /*
7564 * The first command completed by the RISC will be placed in
7565 * the stopper.
7566 *
7567 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7568 * completed the RISC will set the ASC_RQ_STOPPER bit.
7569 */
7570 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007571
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007572 /*
7573 * Set RISC IRQ physical address start value.
7574 *
7575 * carr_pa is LE, must be native before write *
7576 */
7577 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7578 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007580 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7581 (ADV_INTR_ENABLE_HOST_INTR |
7582 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007584 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7585 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007587 /* finally, finally, gentlemen, start your engine */
7588 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007589
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007590 /*
7591 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7592 * Resets should be performed. The RISC has to be running
7593 * to issue a SCSI Bus Reset.
7594 */
7595 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7596 /*
7597 * If the BIOS Signature is present in memory, restore the
7598 * BIOS Handshake Configuration Table and do not perform
7599 * a SCSI Bus Reset.
7600 */
7601 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7602 0x55AA) {
7603 /*
7604 * Restore per TID negotiated values.
7605 */
7606 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7607 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7608 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7609 tagqng_able);
7610 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7611 AdvWriteByteLram(iop_base,
7612 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7613 max_cmd[tid]);
7614 }
7615 } else {
7616 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7617 warn_code = ASC_WARN_BUSRESET_ERROR;
7618 }
7619 }
7620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007622 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007623}
7624
7625/*
7626 * Initialize the ASC-38C1600.
7627 *
7628 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
7629 *
7630 * For a non-fatal error return a warning code. If there are no warnings
7631 * then 0 is returned.
7632 *
7633 * Needed after initialization for error recovery.
7634 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007635static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007636{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007637 AdvPortAddr iop_base;
7638 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007639 int begin_addr;
7640 int end_addr;
7641 ushort code_sum;
7642 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007643 int i;
7644 ushort scsi_cfg1;
7645 uchar byte;
7646 uchar tid;
7647 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7648 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
7649 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007651 /* If there is already an error, don't continue. */
7652 if (asc_dvc->err_code != 0) {
7653 return ADV_ERROR;
7654 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007655
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007656 /*
7657 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
7658 */
7659 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
7660 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7661 return ADV_ERROR;
7662 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007663
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007664 warn_code = 0;
7665 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007667 /*
7668 * Save the RISC memory BIOS region before writing the microcode.
7669 * The BIOS may already be loaded and using its RISC LRAM region
7670 * so its region must be saved and restored.
7671 *
7672 * Note: This code makes the assumption, which is currently true,
7673 * that a chip reset does not clear RISC LRAM.
7674 */
7675 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7676 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7677 bios_mem[i]);
7678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007679
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007680 /*
7681 * Save current per TID negotiated values.
7682 */
7683 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7684 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7685 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
7686 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7687 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7688 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7689 max_cmd[tid]);
7690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007692 /*
7693 * RAM BIST (Built-In Self Test)
7694 *
7695 * Address : I/O base + offset 0x38h register (byte).
7696 * Function: Bit 7-6(RW) : RAM mode
7697 * Normal Mode : 0x00
7698 * Pre-test Mode : 0x40
7699 * RAM Test Mode : 0x80
7700 * Bit 5 : unused
7701 * Bit 4(RO) : Done bit
7702 * Bit 3-0(RO) : Status
7703 * Host Error : 0x08
7704 * Int_RAM Error : 0x04
7705 * RISC Error : 0x02
7706 * SCSI Error : 0x01
7707 * No Error : 0x00
7708 *
7709 * Note: RAM BIST code should be put right here, before loading the
7710 * microcode and after saving the RISC memory BIOS region.
7711 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007713 /*
7714 * LRAM Pre-test
7715 *
7716 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7717 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7718 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7719 * to NORMAL_MODE, return an error too.
7720 */
7721 for (i = 0; i < 2; i++) {
7722 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007723 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007724 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7725 if ((byte & RAM_TEST_DONE) == 0
7726 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007727 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007728 return ADV_ERROR;
7729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007731 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007732 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007733 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7734 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007735 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007736 return ADV_ERROR;
7737 }
7738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007739
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007740 /*
7741 * LRAM Test - It takes about 1.5 ms to run through the test.
7742 *
7743 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7744 * If Done bit not set or Status not 0, save register byte, set the
7745 * err_code, and return an error.
7746 */
7747 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007748 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007749
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007750 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7751 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7752 /* Get here if Done bit not set or Status not 0. */
7753 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007754 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007755 return ADV_ERROR;
7756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007757
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007758 /* We need to reset back to normal mode after LRAM test passes. */
7759 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007760
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007761 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
7762 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
7763 _adv_asc38C1600_chksum);
7764 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007765 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007767 /*
7768 * Restore the RISC memory BIOS region.
7769 */
7770 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7771 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7772 bios_mem[i]);
7773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007774
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007775 /*
7776 * Calculate and write the microcode code checksum to the microcode
7777 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7778 */
7779 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7780 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7781 code_sum = 0;
7782 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7783 for (word = begin_addr; word < end_addr; word += 2) {
7784 code_sum += AdvReadWordAutoIncLram(iop_base);
7785 }
7786 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007787
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007788 /*
7789 * Read microcode version and date.
7790 */
7791 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7792 asc_dvc->cfg->mcode_date);
7793 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7794 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007796 /*
7797 * Set the chip type to indicate the ASC38C1600.
7798 */
7799 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007800
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007801 /*
7802 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7803 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7804 * cable detection and then we are able to read C_DET[3:0].
7805 *
7806 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7807 * Microcode Default Value' section below.
7808 */
7809 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7810 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7811 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007812
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007813 /*
7814 * If the PCI Configuration Command Register "Parity Error Response
7815 * Control" Bit was clear (0), then set the microcode variable
7816 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7817 * to ignore DMA parity errors.
7818 */
7819 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7820 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7821 word |= CONTROL_FLAG_IGNORE_PERR;
7822 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007824
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007825 /*
7826 * If the BIOS control flag AIPP (Asynchronous Information
7827 * Phase Protection) disable bit is not set, then set the firmware
7828 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
7829 * AIPP checking and encoding.
7830 */
7831 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
7832 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7833 word |= CONTROL_FLAG_ENABLE_AIPP;
7834 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007837 /*
7838 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
7839 * and START_CTL_TH [3:2].
7840 */
7841 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7842 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007844 /*
7845 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007846 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007847 * device reports it is capable of in Inquiry byte 7.
7848 *
7849 * If SCSI Bus Resets have been disabled, then directly set
7850 * SDTR and WDTR from the EEPROM configuration. This will allow
7851 * the BIOS and warm boot to work without a SCSI bus hang on
7852 * the Inquiry caused by host and target mismatched DTR values.
7853 * Without the SCSI Bus Reset, before an Inquiry a device can't
7854 * be assumed to be in Asynchronous, Narrow mode.
7855 */
7856 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7857 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7858 asc_dvc->wdtr_able);
7859 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7860 asc_dvc->sdtr_able);
7861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007863 /*
7864 * Set microcode operating variables for DISC and SDTR_SPEED1,
7865 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7866 * configuration values.
7867 *
7868 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7869 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7870 * without determining here whether the device supports SDTR.
7871 */
7872 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7873 asc_dvc->cfg->disc_enable);
7874 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7875 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7876 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7877 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007879 /*
7880 * Set SCSI_CFG0 Microcode Default Value.
7881 *
7882 * The microcode will set the SCSI_CFG0 register using this value
7883 * after it is started below.
7884 */
7885 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7886 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7887 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007889 /*
7890 * Calculate SCSI_CFG1 Microcode Default Value.
7891 *
7892 * The microcode will set the SCSI_CFG1 register using this value
7893 * after it is started below.
7894 *
7895 * Each ASC-38C1600 function has only two cable detect bits.
7896 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
7897 */
7898 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007899
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007900 /*
7901 * If the cable is reversed all of the SCSI_CTRL register signals
7902 * will be set. Check for and return an error if this condition is
7903 * found.
7904 */
7905 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7906 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7907 return ADV_ERROR;
7908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007910 /*
7911 * Each ASC-38C1600 function has two connectors. Only an HVD device
7912 * can not be connected to either connector. An LVD device or SE device
7913 * may be connected to either connecor. If an SE device is connected,
7914 * then at most Ultra speed (20 Mhz) can be used on both connectors.
7915 *
7916 * If an HVD device is attached, return an error.
7917 */
7918 if (scsi_cfg1 & HVD) {
7919 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
7920 return ADV_ERROR;
7921 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007922
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007923 /*
7924 * Each function in the ASC-38C1600 uses only the SE cable detect and
7925 * termination because there are two connectors for each function. Each
7926 * function may use either LVD or SE mode. Corresponding the SE automatic
7927 * termination control EEPROM bits are used for each function. Each
7928 * function has its own EEPROM. If SE automatic control is enabled for
7929 * the function, then set the termination value based on a table listed
7930 * in a_condor.h.
7931 *
7932 * If manual termination is specified in the EEPROM for the function,
7933 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
7934 * ready to be 'ored' into SCSI_CFG1.
7935 */
7936 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06007937 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007938 /* SE automatic termination control is enabled. */
7939 switch (scsi_cfg1 & C_DET_SE) {
7940 /* TERM_SE_HI: on, TERM_SE_LO: on */
7941 case 0x1:
7942 case 0x2:
7943 case 0x3:
7944 asc_dvc->cfg->termination |= TERM_SE;
7945 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007946
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007947 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06007948 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007949 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
7950 } else {
7951 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
7952 asc_dvc->cfg->termination |= TERM_SE_HI;
7953 }
7954 break;
7955 }
7956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007958 /*
7959 * Clear any set TERM_SE bits.
7960 */
7961 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007963 /*
7964 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
7965 */
7966 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007967
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007968 /*
7969 * Clear Big Endian and Terminator Polarity bits and set possibly
7970 * modified termination control bits in the Microcode SCSI_CFG1
7971 * Register Value.
7972 *
7973 * Big Endian bit is not used even on big endian machines.
7974 */
7975 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007977 /*
7978 * Set SCSI_CFG1 Microcode Default Value
7979 *
7980 * Set possibly modified termination control bits in the Microcode
7981 * SCSI_CFG1 Register Value.
7982 *
7983 * The microcode will set the SCSI_CFG1 register using this value
7984 * after it is started below.
7985 */
7986 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007987
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007988 /*
7989 * Set MEM_CFG Microcode Default Value
7990 *
7991 * The microcode will set the MEM_CFG register using this value
7992 * after it is started below.
7993 *
7994 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7995 * are defined.
7996 *
7997 * ASC-38C1600 has 32KB internal memory.
7998 *
7999 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
8000 * out a special 16K Adv Library and Microcode version. After the issue
8001 * resolved, we should turn back to the 32K support. Both a_condor.h and
8002 * mcode.sas files also need to be updated.
8003 *
8004 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8005 * BIOS_EN | RAM_SZ_32KB);
8006 */
8007 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8008 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008009
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008010 /*
8011 * Set SEL_MASK Microcode Default Value
8012 *
8013 * The microcode will set the SEL_MASK register using this value
8014 * after it is started below.
8015 */
8016 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
8017 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008018
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06008019 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008020
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008021 /*
8022 * Set-up the Host->RISC Initiator Command Queue (ICQ).
8023 */
8024 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
8025 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8026 return ADV_ERROR;
8027 }
8028 asc_dvc->carr_freelist = (ADV_CARR_T *)
8029 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008031 /*
8032 * The first command issued will be placed in the stopper carrier.
8033 */
8034 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008035
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008036 /*
8037 * Set RISC ICQ physical address start value. Initialize the
8038 * COMMA register to the same value otherwise the RISC will
8039 * prematurely detect a command is available.
8040 */
8041 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
8042 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
8043 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008044
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008045 /*
8046 * Set-up the RISC->Host Initiator Response Queue (IRQ).
8047 */
8048 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
8049 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8050 return ADV_ERROR;
8051 }
8052 asc_dvc->carr_freelist = (ADV_CARR_T *)
8053 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008054
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008055 /*
8056 * The first command completed by the RISC will be placed in
8057 * the stopper.
8058 *
8059 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
8060 * completed the RISC will set the ASC_RQ_STOPPER bit.
8061 */
8062 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008064 /*
8065 * Set RISC IRQ physical address start value.
8066 */
8067 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
8068 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008070 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
8071 (ADV_INTR_ENABLE_HOST_INTR |
8072 ADV_INTR_ENABLE_GLOBAL_INTR));
8073 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
8074 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008076 /* finally, finally, gentlemen, start your engine */
8077 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008078
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008079 /*
8080 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
8081 * Resets should be performed. The RISC has to be running
8082 * to issue a SCSI Bus Reset.
8083 */
8084 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
8085 /*
8086 * If the BIOS Signature is present in memory, restore the
8087 * per TID microcode operating variables.
8088 */
8089 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
8090 0x55AA) {
8091 /*
8092 * Restore per TID negotiated values.
8093 */
8094 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8095 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8096 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8097 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
8098 tagqng_able);
8099 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
8100 AdvWriteByteLram(iop_base,
8101 ASC_MC_NUMBER_OF_MAX_CMD + tid,
8102 max_cmd[tid]);
8103 }
8104 } else {
8105 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
8106 warn_code = ASC_WARN_BUSRESET_ERROR;
8107 }
8108 }
8109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008111 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008112}
8113
8114/*
Matthew Wilcox51219352007-10-02 21:55:22 -04008115 * Reset chip and SCSI Bus.
8116 *
8117 * Return Value:
8118 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
8119 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
8120 */
8121static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
8122{
8123 int status;
8124 ushort wdtr_able, sdtr_able, tagqng_able;
8125 ushort ppr_able = 0;
8126 uchar tid, max_cmd[ADV_MAX_TID + 1];
8127 AdvPortAddr iop_base;
8128 ushort bios_sig;
8129
8130 iop_base = asc_dvc->iop_base;
8131
8132 /*
8133 * Save current per TID negotiated values.
8134 */
8135 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8136 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8137 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8138 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8139 }
8140 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8141 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8142 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8143 max_cmd[tid]);
8144 }
8145
8146 /*
8147 * Force the AdvInitAsc3550/38C0800Driver() function to
8148 * perform a SCSI Bus Reset by clearing the BIOS signature word.
8149 * The initialization functions assumes a SCSI Bus Reset is not
8150 * needed if the BIOS signature word is present.
8151 */
8152 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8153 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
8154
8155 /*
8156 * Stop chip and reset it.
8157 */
8158 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
8159 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
8160 mdelay(100);
8161 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
8162 ADV_CTRL_REG_CMD_WR_IO_REG);
8163
8164 /*
8165 * Reset Adv Library error code, if any, and try
8166 * re-initializing the chip.
8167 */
8168 asc_dvc->err_code = 0;
8169 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8170 status = AdvInitAsc38C1600Driver(asc_dvc);
8171 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8172 status = AdvInitAsc38C0800Driver(asc_dvc);
8173 } else {
8174 status = AdvInitAsc3550Driver(asc_dvc);
8175 }
8176
8177 /* Translate initialization return value to status value. */
8178 if (status == 0) {
8179 status = ADV_TRUE;
8180 } else {
8181 status = ADV_FALSE;
8182 }
8183
8184 /*
8185 * Restore the BIOS signature word.
8186 */
8187 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8188
8189 /*
8190 * Restore per TID negotiated values.
8191 */
8192 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8193 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8194 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8195 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8196 }
8197 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8198 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8199 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8200 max_cmd[tid]);
8201 }
8202
8203 return status;
8204}
8205
8206/*
8207 * adv_async_callback() - Adv Library asynchronous event callback function.
8208 */
8209static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
8210{
8211 switch (code) {
8212 case ADV_ASYNC_SCSI_BUS_RESET_DET:
8213 /*
8214 * The firmware detected a SCSI Bus reset.
8215 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008216 ASC_DBG(0, "ADV_ASYNC_SCSI_BUS_RESET_DET\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008217 break;
8218
8219 case ADV_ASYNC_RDMA_FAILURE:
8220 /*
8221 * Handle RDMA failure by resetting the SCSI Bus and
8222 * possibly the chip if it is unresponsive. Log the error
8223 * with a unique code.
8224 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008225 ASC_DBG(0, "ADV_ASYNC_RDMA_FAILURE\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008226 AdvResetChipAndSB(adv_dvc_varp);
8227 break;
8228
8229 case ADV_HOST_SCSI_BUS_RESET:
8230 /*
8231 * Host generated SCSI bus reset occurred.
8232 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008233 ASC_DBG(0, "ADV_HOST_SCSI_BUS_RESET\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008234 break;
8235
8236 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008237 ASC_DBG(0, "unknown code 0x%x\n", code);
Matthew Wilcox51219352007-10-02 21:55:22 -04008238 break;
8239 }
8240}
8241
8242/*
8243 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
8244 *
8245 * Callback function for the Wide SCSI Adv Library.
8246 */
8247static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
8248{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008249 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04008250 adv_req_t *reqp;
8251 adv_sgblk_t *sgblkp;
8252 struct scsi_cmnd *scp;
8253 struct Scsi_Host *shost;
8254 ADV_DCNT resid_cnt;
8255
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008256 ASC_DBG(1, "adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04008257 (ulong)adv_dvc_varp, (ulong)scsiqp);
8258 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
8259
8260 /*
8261 * Get the adv_req_t structure for the command that has been
8262 * completed. The adv_req_t structure actually contains the
8263 * completed ADV_SCSI_REQ_Q structure.
8264 */
8265 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008266 ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp);
Matthew Wilcox51219352007-10-02 21:55:22 -04008267 if (reqp == NULL) {
8268 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
8269 return;
8270 }
8271
8272 /*
8273 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
8274 * command that has been completed.
8275 *
8276 * Note: The adv_req_t request structure and adv_sgblk_t structure,
8277 * if any, are dropped, because a board structure pointer can not be
8278 * determined.
8279 */
8280 scp = reqp->cmndp;
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008281 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04008282 if (scp == NULL) {
8283 ASC_PRINT
8284 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
8285 return;
8286 }
8287 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
8288
8289 shost = scp->device->host;
8290 ASC_STATS(shost, callback);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008291 ASC_DBG(1, "shost 0x%p\n", shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04008292
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008293 boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04008294 BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
8295
8296 /*
8297 * 'done_status' contains the command's ending status.
8298 */
8299 switch (scsiqp->done_status) {
8300 case QD_NO_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008301 ASC_DBG(2, "QD_NO_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008302 scp->result = 0;
8303
8304 /*
8305 * Check for an underrun condition.
8306 *
8307 * If there was no error and an underrun condition, then
8308 * then return the number of underrun bytes.
8309 */
8310 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
8311 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
8312 resid_cnt <= scp->request_bufflen) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008313 ASC_DBG(1, "underrun condition %lu bytes\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04008314 (ulong)resid_cnt);
8315 scp->resid = resid_cnt;
8316 }
8317 break;
8318
8319 case QD_WITH_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008320 ASC_DBG(2, "QD_WITH_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008321 switch (scsiqp->host_status) {
8322 case QHSTA_NO_ERROR:
8323 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008324 ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008325 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
8326 sizeof(scp->sense_buffer));
8327 /*
8328 * Note: The 'status_byte()' macro used by
8329 * target drivers defined in scsi.h shifts the
8330 * status byte returned by host drivers right
8331 * by 1 bit. This is why target drivers also
8332 * use right shifted status byte definitions.
8333 * For instance target drivers use
8334 * CHECK_CONDITION, defined to 0x1, instead of
8335 * the SCSI defined check condition value of
8336 * 0x2. Host drivers are supposed to return
8337 * the status byte as it is defined by SCSI.
8338 */
8339 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
8340 STATUS_BYTE(scsiqp->scsi_status);
8341 } else {
8342 scp->result = STATUS_BYTE(scsiqp->scsi_status);
8343 }
8344 break;
8345
8346 default:
8347 /* Some other QHSTA error occurred. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008348 ASC_DBG(1, "host_status 0x%x\n", scsiqp->host_status);
Matthew Wilcox51219352007-10-02 21:55:22 -04008349 scp->result = HOST_BYTE(DID_BAD_TARGET);
8350 break;
8351 }
8352 break;
8353
8354 case QD_ABORTED_BY_HOST:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008355 ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008356 scp->result =
8357 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
8358 break;
8359
8360 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008361 ASC_DBG(1, "done_status 0x%x\n", scsiqp->done_status);
Matthew Wilcox51219352007-10-02 21:55:22 -04008362 scp->result =
8363 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
8364 break;
8365 }
8366
8367 /*
8368 * If the 'init_tidmask' bit isn't already set for the target and the
8369 * current request finished normally, then set the bit for the target
8370 * to indicate that a device is present.
8371 */
8372 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
8373 scsiqp->done_status == QD_NO_ERROR &&
8374 scsiqp->host_status == QHSTA_NO_ERROR) {
8375 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
8376 }
8377
8378 asc_scsi_done(scp);
8379
8380 /*
8381 * Free all 'adv_sgblk_t' structures allocated for the request.
8382 */
8383 while ((sgblkp = reqp->sgblkp) != NULL) {
8384 /* Remove 'sgblkp' from the request list. */
8385 reqp->sgblkp = sgblkp->next_sgblkp;
8386
8387 /* Add 'sgblkp' to the board free list. */
8388 sgblkp->next_sgblkp = boardp->adv_sgblkp;
8389 boardp->adv_sgblkp = sgblkp;
8390 }
8391
8392 /*
8393 * Free the adv_req_t structure used with the command by adding
8394 * it back to the board free list.
8395 */
8396 reqp->next_reqp = boardp->adv_reqp;
8397 boardp->adv_reqp = reqp;
8398
Matthew Wilcoxb352f922007-10-02 21:55:33 -04008399 ASC_DBG(1, "done\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04008400
8401 return;
8402}
8403
8404/*
8405 * Adv Library Interrupt Service Routine
8406 *
8407 * This function is called by a driver's interrupt service routine.
8408 * The function disables and re-enables interrupts.
8409 *
8410 * When a microcode idle command is completed, the ADV_DVC_VAR
8411 * 'idle_cmd_done' field is set to ADV_TRUE.
8412 *
8413 * Note: AdvISR() can be called when interrupts are disabled or even
8414 * when there is no hardware interrupt condition present. It will
8415 * always check for completed idle commands and microcode requests.
8416 * This is an important feature that shouldn't be changed because it
8417 * allows commands to be completed from polling mode loops.
8418 *
8419 * Return:
8420 * ADV_TRUE(1) - interrupt was pending
8421 * ADV_FALSE(0) - no interrupt was pending
8422 */
8423static int AdvISR(ADV_DVC_VAR *asc_dvc)
8424{
8425 AdvPortAddr iop_base;
8426 uchar int_stat;
8427 ushort target_bit;
8428 ADV_CARR_T *free_carrp;
8429 ADV_VADDR irq_next_vpa;
8430 ADV_SCSI_REQ_Q *scsiq;
8431
8432 iop_base = asc_dvc->iop_base;
8433
8434 /* Reading the register clears the interrupt. */
8435 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
8436
8437 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
8438 ADV_INTR_STATUS_INTRC)) == 0) {
8439 return ADV_FALSE;
8440 }
8441
8442 /*
8443 * Notify the driver of an asynchronous microcode condition by
8444 * calling the adv_async_callback function. The function
8445 * is passed the microcode ASC_MC_INTRB_CODE byte value.
8446 */
8447 if (int_stat & ADV_INTR_STATUS_INTRB) {
8448 uchar intrb_code;
8449
8450 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
8451
8452 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
8453 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8454 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
8455 asc_dvc->carr_pending_cnt != 0) {
8456 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
8457 ADV_TICKLE_A);
8458 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
8459 AdvWriteByteRegister(iop_base,
8460 IOPB_TICKLE,
8461 ADV_TICKLE_NOP);
8462 }
8463 }
8464 }
8465
8466 adv_async_callback(asc_dvc, intrb_code);
8467 }
8468
8469 /*
8470 * Check if the IRQ stopper carrier contains a completed request.
8471 */
8472 while (((irq_next_vpa =
8473 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
8474 /*
8475 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
8476 * The RISC will have set 'areq_vpa' to a virtual address.
8477 *
8478 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
8479 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
8480 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
8481 * in AdvExeScsiQueue().
8482 */
8483 scsiq = (ADV_SCSI_REQ_Q *)
8484 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
8485
8486 /*
8487 * Request finished with good status and the queue was not
8488 * DMAed to host memory by the firmware. Set all status fields
8489 * to indicate good status.
8490 */
8491 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
8492 scsiq->done_status = QD_NO_ERROR;
8493 scsiq->host_status = scsiq->scsi_status = 0;
8494 scsiq->data_cnt = 0L;
8495 }
8496
8497 /*
8498 * Advance the stopper pointer to the next carrier
8499 * ignoring the lower four bits. Free the previous
8500 * stopper carrier.
8501 */
8502 free_carrp = asc_dvc->irq_sp;
8503 asc_dvc->irq_sp = (ADV_CARR_T *)
8504 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
8505
8506 free_carrp->next_vpa =
8507 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
8508 asc_dvc->carr_freelist = free_carrp;
8509 asc_dvc->carr_pending_cnt--;
8510
8511 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
8512
8513 /*
8514 * Clear request microcode control flag.
8515 */
8516 scsiq->cntl = 0;
8517
8518 /*
8519 * Notify the driver of the completed request by passing
8520 * the ADV_SCSI_REQ_Q pointer to its callback function.
8521 */
8522 scsiq->a_flag |= ADV_SCSIQ_DONE;
8523 adv_isr_callback(asc_dvc, scsiq);
8524 /*
8525 * Note: After the driver callback function is called, 'scsiq'
8526 * can no longer be referenced.
8527 *
8528 * Fall through and continue processing other completed
8529 * requests...
8530 */
8531 }
8532 return ADV_TRUE;
8533}
8534
8535static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
8536{
8537 if (asc_dvc->err_code == 0) {
8538 asc_dvc->err_code = err_code;
8539 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8540 err_code);
8541 }
8542 return err_code;
8543}
8544
8545static void AscAckInterrupt(PortAddr iop_base)
8546{
8547 uchar host_flag;
8548 uchar risc_flag;
8549 ushort loop;
8550
8551 loop = 0;
8552 do {
8553 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8554 if (loop++ > 0x7FFF) {
8555 break;
8556 }
8557 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8558 host_flag =
8559 AscReadLramByte(iop_base,
8560 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8561 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8562 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8563 AscSetChipStatus(iop_base, CIW_INT_ACK);
8564 loop = 0;
8565 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8566 AscSetChipStatus(iop_base, CIW_INT_ACK);
8567 if (loop++ > 3) {
8568 break;
8569 }
8570 }
8571 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8572 return;
8573}
8574
8575static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
8576{
8577 uchar *period_table;
8578 int max_index;
8579 int min_index;
8580 int i;
8581
8582 period_table = asc_dvc->sdtr_period_tbl;
8583 max_index = (int)asc_dvc->max_sdtr_index;
8584 min_index = (int)asc_dvc->host_init_sdtr_index;
8585 if ((syn_time <= period_table[max_index])) {
8586 for (i = min_index; i < (max_index - 1); i++) {
8587 if (syn_time <= period_table[i]) {
8588 return (uchar)i;
8589 }
8590 }
8591 return (uchar)max_index;
8592 } else {
8593 return (uchar)(max_index + 1);
8594 }
8595}
8596
8597static uchar
8598AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
8599{
8600 EXT_MSG sdtr_buf;
8601 uchar sdtr_period_index;
8602 PortAddr iop_base;
8603
8604 iop_base = asc_dvc->iop_base;
8605 sdtr_buf.msg_type = EXTENDED_MESSAGE;
8606 sdtr_buf.msg_len = MS_SDTR_LEN;
8607 sdtr_buf.msg_req = EXTENDED_SDTR;
8608 sdtr_buf.xfer_period = sdtr_period;
8609 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8610 sdtr_buf.req_ack_offset = sdtr_offset;
8611 sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8612 if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
8613 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8614 (uchar *)&sdtr_buf,
8615 sizeof(EXT_MSG) >> 1);
8616 return ((sdtr_period_index << 4) | sdtr_offset);
8617 } else {
8618 sdtr_buf.req_ack_offset = 0;
8619 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8620 (uchar *)&sdtr_buf,
8621 sizeof(EXT_MSG) >> 1);
8622 return 0;
8623 }
8624}
8625
8626static uchar
8627AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
8628{
8629 uchar byte;
8630 uchar sdtr_period_ix;
8631
8632 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8633 if (sdtr_period_ix > asc_dvc->max_sdtr_index) {
8634 return 0xFF;
8635 }
8636 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8637 return byte;
8638}
8639
8640static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
8641{
8642 ASC_SCSI_BIT_ID_TYPE org_id;
8643 int i;
8644 int sta = TRUE;
8645
8646 AscSetBank(iop_base, 1);
8647 org_id = AscReadChipDvcID(iop_base);
8648 for (i = 0; i <= ASC_MAX_TID; i++) {
8649 if (org_id == (0x01 << i))
8650 break;
8651 }
8652 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8653 AscWriteChipDvcID(iop_base, id);
8654 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8655 AscSetBank(iop_base, 0);
8656 AscSetChipSyn(iop_base, sdtr_data);
8657 if (AscGetChipSyn(iop_base) != sdtr_data) {
8658 sta = FALSE;
8659 }
8660 } else {
8661 sta = FALSE;
8662 }
8663 AscSetBank(iop_base, 1);
8664 AscWriteChipDvcID(iop_base, org_id);
8665 AscSetBank(iop_base, 0);
8666 return (sta);
8667}
8668
8669static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
8670{
8671 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8672 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8673}
8674
8675static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
8676{
8677 EXT_MSG ext_msg;
8678 EXT_MSG out_msg;
8679 ushort halt_q_addr;
8680 int sdtr_accept;
8681 ushort int_halt_code;
8682 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8683 ASC_SCSI_BIT_ID_TYPE target_id;
8684 PortAddr iop_base;
8685 uchar tag_code;
8686 uchar q_status;
8687 uchar halt_qp;
8688 uchar sdtr_data;
8689 uchar target_ix;
8690 uchar q_cntl, tid_no;
8691 uchar cur_dvc_qng;
8692 uchar asyn_sdtr;
8693 uchar scsi_status;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04008694 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04008695
8696 BUG_ON(!asc_dvc->drv_ptr);
8697 boardp = asc_dvc->drv_ptr;
8698
8699 iop_base = asc_dvc->iop_base;
8700 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
8701
8702 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8703 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8704 target_ix = AscReadLramByte(iop_base,
8705 (ushort)(halt_q_addr +
8706 (ushort)ASC_SCSIQ_B_TARGET_IX));
8707 q_cntl = AscReadLramByte(iop_base,
8708 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8709 tid_no = ASC_TIX_TO_TID(target_ix);
8710 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8711 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8712 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8713 } else {
8714 asyn_sdtr = 0;
8715 }
8716 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8717 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8718 AscSetChipSDTR(iop_base, 0, tid_no);
8719 boardp->sdtr_data[tid_no] = 0;
8720 }
8721 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8722 return (0);
8723 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8724 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8725 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8726 boardp->sdtr_data[tid_no] = asyn_sdtr;
8727 }
8728 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8729 return (0);
8730 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
8731 AscMemWordCopyPtrFromLram(iop_base,
8732 ASCV_MSGIN_BEG,
8733 (uchar *)&ext_msg,
8734 sizeof(EXT_MSG) >> 1);
8735
8736 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8737 ext_msg.msg_req == EXTENDED_SDTR &&
8738 ext_msg.msg_len == MS_SDTR_LEN) {
8739 sdtr_accept = TRUE;
8740 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
8741
8742 sdtr_accept = FALSE;
8743 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8744 }
8745 if ((ext_msg.xfer_period <
8746 asc_dvc->sdtr_period_tbl[asc_dvc->
8747 host_init_sdtr_index])
8748 || (ext_msg.xfer_period >
8749 asc_dvc->sdtr_period_tbl[asc_dvc->
8750 max_sdtr_index])) {
8751 sdtr_accept = FALSE;
8752 ext_msg.xfer_period =
8753 asc_dvc->sdtr_period_tbl[asc_dvc->
8754 host_init_sdtr_index];
8755 }
8756 if (sdtr_accept) {
8757 sdtr_data =
8758 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8759 ext_msg.req_ack_offset);
8760 if ((sdtr_data == 0xFF)) {
8761
8762 q_cntl |= QC_MSG_OUT;
8763 asc_dvc->init_sdtr &= ~target_id;
8764 asc_dvc->sdtr_done &= ~target_id;
8765 AscSetChipSDTR(iop_base, asyn_sdtr,
8766 tid_no);
8767 boardp->sdtr_data[tid_no] = asyn_sdtr;
8768 }
8769 }
8770 if (ext_msg.req_ack_offset == 0) {
8771
8772 q_cntl &= ~QC_MSG_OUT;
8773 asc_dvc->init_sdtr &= ~target_id;
8774 asc_dvc->sdtr_done &= ~target_id;
8775 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8776 } else {
8777 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
8778
8779 q_cntl &= ~QC_MSG_OUT;
8780 asc_dvc->sdtr_done |= target_id;
8781 asc_dvc->init_sdtr |= target_id;
8782 asc_dvc->pci_fix_asyn_xfer &=
8783 ~target_id;
8784 sdtr_data =
8785 AscCalSDTRData(asc_dvc,
8786 ext_msg.xfer_period,
8787 ext_msg.
8788 req_ack_offset);
8789 AscSetChipSDTR(iop_base, sdtr_data,
8790 tid_no);
8791 boardp->sdtr_data[tid_no] = sdtr_data;
8792 } else {
8793
8794 q_cntl |= QC_MSG_OUT;
8795 AscMsgOutSDTR(asc_dvc,
8796 ext_msg.xfer_period,
8797 ext_msg.req_ack_offset);
8798 asc_dvc->pci_fix_asyn_xfer &=
8799 ~target_id;
8800 sdtr_data =
8801 AscCalSDTRData(asc_dvc,
8802 ext_msg.xfer_period,
8803 ext_msg.
8804 req_ack_offset);
8805 AscSetChipSDTR(iop_base, sdtr_data,
8806 tid_no);
8807 boardp->sdtr_data[tid_no] = sdtr_data;
8808 asc_dvc->sdtr_done |= target_id;
8809 asc_dvc->init_sdtr |= target_id;
8810 }
8811 }
8812
8813 AscWriteLramByte(iop_base,
8814 (ushort)(halt_q_addr +
8815 (ushort)ASC_SCSIQ_B_CNTL),
8816 q_cntl);
8817 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8818 return (0);
8819 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8820 ext_msg.msg_req == EXTENDED_WDTR &&
8821 ext_msg.msg_len == MS_WDTR_LEN) {
8822
8823 ext_msg.wdtr_width = 0;
8824 AscMemWordCopyPtrToLram(iop_base,
8825 ASCV_MSGOUT_BEG,
8826 (uchar *)&ext_msg,
8827 sizeof(EXT_MSG) >> 1);
8828 q_cntl |= QC_MSG_OUT;
8829 AscWriteLramByte(iop_base,
8830 (ushort)(halt_q_addr +
8831 (ushort)ASC_SCSIQ_B_CNTL),
8832 q_cntl);
8833 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8834 return (0);
8835 } else {
8836
8837 ext_msg.msg_type = MESSAGE_REJECT;
8838 AscMemWordCopyPtrToLram(iop_base,
8839 ASCV_MSGOUT_BEG,
8840 (uchar *)&ext_msg,
8841 sizeof(EXT_MSG) >> 1);
8842 q_cntl |= QC_MSG_OUT;
8843 AscWriteLramByte(iop_base,
8844 (ushort)(halt_q_addr +
8845 (ushort)ASC_SCSIQ_B_CNTL),
8846 q_cntl);
8847 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8848 return (0);
8849 }
8850 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
8851
8852 q_cntl |= QC_REQ_SENSE;
8853
8854 if ((asc_dvc->init_sdtr & target_id) != 0) {
8855
8856 asc_dvc->sdtr_done &= ~target_id;
8857
8858 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8859 q_cntl |= QC_MSG_OUT;
8860 AscMsgOutSDTR(asc_dvc,
8861 asc_dvc->
8862 sdtr_period_tbl[(sdtr_data >> 4) &
8863 (uchar)(asc_dvc->
8864 max_sdtr_index -
8865 1)],
8866 (uchar)(sdtr_data & (uchar)
8867 ASC_SYN_MAX_OFFSET));
8868 }
8869
8870 AscWriteLramByte(iop_base,
8871 (ushort)(halt_q_addr +
8872 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8873
8874 tag_code = AscReadLramByte(iop_base,
8875 (ushort)(halt_q_addr + (ushort)
8876 ASC_SCSIQ_B_TAG_CODE));
8877 tag_code &= 0xDC;
8878 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
8879 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
8880 ) {
8881
8882 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
8883 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
8884
8885 }
8886 AscWriteLramByte(iop_base,
8887 (ushort)(halt_q_addr +
8888 (ushort)ASC_SCSIQ_B_TAG_CODE),
8889 tag_code);
8890
8891 q_status = AscReadLramByte(iop_base,
8892 (ushort)(halt_q_addr + (ushort)
8893 ASC_SCSIQ_B_STATUS));
8894 q_status |= (QS_READY | QS_BUSY);
8895 AscWriteLramByte(iop_base,
8896 (ushort)(halt_q_addr +
8897 (ushort)ASC_SCSIQ_B_STATUS),
8898 q_status);
8899
8900 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
8901 scsi_busy &= ~target_id;
8902 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8903
8904 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8905 return (0);
8906 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
8907
8908 AscMemWordCopyPtrFromLram(iop_base,
8909 ASCV_MSGOUT_BEG,
8910 (uchar *)&out_msg,
8911 sizeof(EXT_MSG) >> 1);
8912
8913 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
8914 (out_msg.msg_len == MS_SDTR_LEN) &&
8915 (out_msg.msg_req == EXTENDED_SDTR)) {
8916
8917 asc_dvc->init_sdtr &= ~target_id;
8918 asc_dvc->sdtr_done &= ~target_id;
8919 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8920 boardp->sdtr_data[tid_no] = asyn_sdtr;
8921 }
8922 q_cntl &= ~QC_MSG_OUT;
8923 AscWriteLramByte(iop_base,
8924 (ushort)(halt_q_addr +
8925 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
8926 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8927 return (0);
8928 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
8929
8930 scsi_status = AscReadLramByte(iop_base,
8931 (ushort)((ushort)halt_q_addr +
8932 (ushort)
8933 ASC_SCSIQ_SCSI_STATUS));
8934 cur_dvc_qng =
8935 AscReadLramByte(iop_base,
8936 (ushort)((ushort)ASC_QADR_BEG +
8937 (ushort)target_ix));
8938 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
8939
8940 scsi_busy = AscReadLramByte(iop_base,
8941 (ushort)ASCV_SCSIBUSY_B);
8942 scsi_busy |= target_id;
8943 AscWriteLramByte(iop_base,
8944 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
8945 asc_dvc->queue_full_or_busy |= target_id;
8946
8947 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
8948 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
8949 cur_dvc_qng -= 1;
8950 asc_dvc->max_dvc_qng[tid_no] =
8951 cur_dvc_qng;
8952
8953 AscWriteLramByte(iop_base,
8954 (ushort)((ushort)
8955 ASCV_MAX_DVC_QNG_BEG
8956 + (ushort)
8957 tid_no),
8958 cur_dvc_qng);
8959
8960 /*
8961 * Set the device queue depth to the
8962 * number of active requests when the
8963 * QUEUE FULL condition was encountered.
8964 */
8965 boardp->queue_full |= target_id;
8966 boardp->queue_full_cnt[tid_no] =
8967 cur_dvc_qng;
8968 }
8969 }
8970 }
8971 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8972 return (0);
8973 }
8974#if CC_VERY_LONG_SG_LIST
8975 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
8976 uchar q_no;
8977 ushort q_addr;
8978 uchar sg_wk_q_no;
8979 uchar first_sg_wk_q_no;
8980 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
8981 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
8982 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
8983 ushort sg_list_dwords;
8984 ushort sg_entry_cnt;
8985 uchar next_qp;
8986 int i;
8987
8988 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
8989 if (q_no == ASC_QLINK_END)
8990 return 0;
8991
8992 q_addr = ASC_QNO_TO_QADDR(q_no);
8993
8994 /*
8995 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
8996 * structure pointer using a macro provided by the driver.
8997 * The ASC_SCSI_REQ pointer provides a pointer to the
8998 * host ASC_SG_HEAD structure.
8999 */
9000 /* Read request's SRB pointer. */
9001 scsiq = (ASC_SCSI_Q *)
9002 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
9003 (ushort)
9004 (q_addr +
9005 ASC_SCSIQ_D_SRBPTR))));
9006
9007 /*
9008 * Get request's first and working SG queue.
9009 */
9010 sg_wk_q_no = AscReadLramByte(iop_base,
9011 (ushort)(q_addr +
9012 ASC_SCSIQ_B_SG_WK_QP));
9013
9014 first_sg_wk_q_no = AscReadLramByte(iop_base,
9015 (ushort)(q_addr +
9016 ASC_SCSIQ_B_FIRST_SG_WK_QP));
9017
9018 /*
9019 * Reset request's working SG queue back to the
9020 * first SG queue.
9021 */
9022 AscWriteLramByte(iop_base,
9023 (ushort)(q_addr +
9024 (ushort)ASC_SCSIQ_B_SG_WK_QP),
9025 first_sg_wk_q_no);
9026
9027 sg_head = scsiq->sg_head;
9028
9029 /*
9030 * Set sg_entry_cnt to the number of SG elements
9031 * that will be completed on this interrupt.
9032 *
9033 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
9034 * SG elements. The data_cnt and data_addr fields which
9035 * add 1 to the SG element capacity are not used when
9036 * restarting SG handling after a halt.
9037 */
9038 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
9039 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
9040
9041 /*
9042 * Keep track of remaining number of SG elements that
9043 * will need to be handled on the next interrupt.
9044 */
9045 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
9046 } else {
9047 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
9048 scsiq->remain_sg_entry_cnt = 0;
9049 }
9050
9051 /*
9052 * Copy SG elements into the list of allocated SG queues.
9053 *
9054 * Last index completed is saved in scsiq->next_sg_index.
9055 */
9056 next_qp = first_sg_wk_q_no;
9057 q_addr = ASC_QNO_TO_QADDR(next_qp);
9058 scsi_sg_q.sg_head_qp = q_no;
9059 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9060 for (i = 0; i < sg_head->queue_cnt; i++) {
9061 scsi_sg_q.seq_no = i + 1;
9062 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9063 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9064 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9065 /*
9066 * After very first SG queue RISC FW uses next
9067 * SG queue first element then checks sg_list_cnt
9068 * against zero and then decrements, so set
9069 * sg_list_cnt 1 less than number of SG elements
9070 * in each SG queue.
9071 */
9072 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
9073 scsi_sg_q.sg_cur_list_cnt =
9074 ASC_SG_LIST_PER_Q - 1;
9075 } else {
9076 /*
9077 * This is the last SG queue in the list of
9078 * allocated SG queues. If there are more
9079 * SG elements than will fit in the allocated
9080 * queues, then set the QCSG_SG_XFER_MORE flag.
9081 */
9082 if (scsiq->remain_sg_entry_cnt != 0) {
9083 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9084 } else {
9085 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
9086 }
9087 /* equals sg_entry_cnt * 2 */
9088 sg_list_dwords = sg_entry_cnt << 1;
9089 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
9090 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
9091 sg_entry_cnt = 0;
9092 }
9093
9094 scsi_sg_q.q_no = next_qp;
9095 AscMemWordCopyPtrToLram(iop_base,
9096 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9097 (uchar *)&scsi_sg_q,
9098 sizeof(ASC_SG_LIST_Q) >> 1);
9099
9100 AscMemDWordCopyPtrToLram(iop_base,
9101 q_addr + ASC_SGQ_LIST_BEG,
9102 (uchar *)&sg_head->
9103 sg_list[scsiq->next_sg_index],
9104 sg_list_dwords);
9105
9106 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
9107
9108 /*
9109 * If the just completed SG queue contained the
9110 * last SG element, then no more SG queues need
9111 * to be written.
9112 */
9113 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
9114 break;
9115 }
9116
9117 next_qp = AscReadLramByte(iop_base,
9118 (ushort)(q_addr +
9119 ASC_SCSIQ_B_FWD));
9120 q_addr = ASC_QNO_TO_QADDR(next_qp);
9121 }
9122
9123 /*
9124 * Clear the halt condition so the RISC will be restarted
9125 * after the return.
9126 */
9127 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9128 return (0);
9129 }
9130#endif /* CC_VERY_LONG_SG_LIST */
9131 return (0);
9132}
9133
9134/*
9135 * void
9136 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9137 *
9138 * Calling/Exit State:
9139 * none
9140 *
9141 * Description:
9142 * Input an ASC_QDONE_INFO structure from the chip
9143 */
9144static void
9145DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9146{
9147 int i;
9148 ushort word;
9149
9150 AscSetChipLramAddr(iop_base, s_addr);
9151 for (i = 0; i < 2 * words; i += 2) {
9152 if (i == 10) {
9153 continue;
9154 }
9155 word = inpw(iop_base + IOP_RAM_DATA);
9156 inbuf[i] = word & 0xff;
9157 inbuf[i + 1] = (word >> 8) & 0xff;
9158 }
9159 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
9160}
9161
9162static uchar
9163_AscCopyLramScsiDoneQ(PortAddr iop_base,
9164 ushort q_addr,
9165 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
9166{
9167 ushort _val;
9168 uchar sg_queue_cnt;
9169
9170 DvcGetQinfo(iop_base,
9171 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
9172 (uchar *)scsiq,
9173 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
9174
9175 _val = AscReadLramWord(iop_base,
9176 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
9177 scsiq->q_status = (uchar)_val;
9178 scsiq->q_no = (uchar)(_val >> 8);
9179 _val = AscReadLramWord(iop_base,
9180 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
9181 scsiq->cntl = (uchar)_val;
9182 sg_queue_cnt = (uchar)(_val >> 8);
9183 _val = AscReadLramWord(iop_base,
9184 (ushort)(q_addr +
9185 (ushort)ASC_SCSIQ_B_SENSE_LEN));
9186 scsiq->sense_len = (uchar)_val;
9187 scsiq->extra_bytes = (uchar)(_val >> 8);
9188
9189 /*
9190 * Read high word of remain bytes from alternate location.
9191 */
9192 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
9193 (ushort)(q_addr +
9194 (ushort)
9195 ASC_SCSIQ_W_ALT_DC1)))
9196 << 16);
9197 /*
9198 * Read low word of remain bytes from original location.
9199 */
9200 scsiq->remain_bytes += AscReadLramWord(iop_base,
9201 (ushort)(q_addr + (ushort)
9202 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
9203
9204 scsiq->remain_bytes &= max_dma_count;
9205 return sg_queue_cnt;
9206}
9207
9208/*
9209 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
9210 *
9211 * Interrupt callback function for the Narrow SCSI Asc Library.
9212 */
9213static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9214{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009215 struct asc_board *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04009216 struct scsi_cmnd *scp;
9217 struct Scsi_Host *shost;
9218
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009219 ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
Matthew Wilcox51219352007-10-02 21:55:22 -04009220 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
9221
9222 /*
9223 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
9224 * command that has been completed.
9225 */
9226 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009227 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009228
9229 if (scp == NULL) {
9230 ASC_PRINT("asc_isr_callback: scp is NULL\n");
9231 return;
9232 }
9233 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
9234
9235 shost = scp->device->host;
9236 ASC_STATS(shost, callback);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009237 ASC_DBG(1, "shost 0x%p\n", shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009238
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009239 boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009240 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
9241
9242 /*
9243 * 'qdonep' contains the command's ending status.
9244 */
9245 switch (qdonep->d3.done_stat) {
9246 case QD_NO_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009247 ASC_DBG(2, "QD_NO_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009248 scp->result = 0;
9249
9250 /*
9251 * Check for an underrun condition.
9252 *
9253 * If there was no error and an underrun condition, then
9254 * return the number of underrun bytes.
9255 */
9256 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
9257 qdonep->remain_bytes <= scp->request_bufflen) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009258 ASC_DBG(1, "underrun condition %u bytes\n",
Matthew Wilcox51219352007-10-02 21:55:22 -04009259 (unsigned)qdonep->remain_bytes);
9260 scp->resid = qdonep->remain_bytes;
9261 }
9262 break;
9263
9264 case QD_WITH_ERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009265 ASC_DBG(2, "QD_WITH_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009266 switch (qdonep->d3.host_stat) {
9267 case QHSTA_NO_ERROR:
9268 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009269 ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009270 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
9271 sizeof(scp->sense_buffer));
9272 /*
9273 * Note: The 'status_byte()' macro used by
9274 * target drivers defined in scsi.h shifts the
9275 * status byte returned by host drivers right
9276 * by 1 bit. This is why target drivers also
9277 * use right shifted status byte definitions.
9278 * For instance target drivers use
9279 * CHECK_CONDITION, defined to 0x1, instead of
9280 * the SCSI defined check condition value of
9281 * 0x2. Host drivers are supposed to return
9282 * the status byte as it is defined by SCSI.
9283 */
9284 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
9285 STATUS_BYTE(qdonep->d3.scsi_stat);
9286 } else {
9287 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
9288 }
9289 break;
9290
9291 default:
9292 /* QHSTA error occurred */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009293 ASC_DBG(1, "host_stat 0x%x\n", qdonep->d3.host_stat);
Matthew Wilcox51219352007-10-02 21:55:22 -04009294 scp->result = HOST_BYTE(DID_BAD_TARGET);
9295 break;
9296 }
9297 break;
9298
9299 case QD_ABORTED_BY_HOST:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009300 ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009301 scp->result =
9302 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
9303 scsi_msg) |
9304 STATUS_BYTE(qdonep->d3.scsi_stat);
9305 break;
9306
9307 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009308 ASC_DBG(1, "done_stat 0x%x\n", qdonep->d3.done_stat);
Matthew Wilcox51219352007-10-02 21:55:22 -04009309 scp->result =
9310 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
9311 scsi_msg) |
9312 STATUS_BYTE(qdonep->d3.scsi_stat);
9313 break;
9314 }
9315
9316 /*
9317 * If the 'init_tidmask' bit isn't already set for the target and the
9318 * current request finished normally, then set the bit for the target
9319 * to indicate that a device is present.
9320 */
9321 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
9322 qdonep->d3.done_stat == QD_NO_ERROR &&
9323 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
9324 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
9325 }
9326
9327 asc_scsi_done(scp);
9328
9329 return;
9330}
9331
9332static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
9333{
9334 uchar next_qp;
9335 uchar n_q_used;
9336 uchar sg_list_qp;
9337 uchar sg_queue_cnt;
9338 uchar q_cnt;
9339 uchar done_q_tail;
9340 uchar tid_no;
9341 ASC_SCSI_BIT_ID_TYPE scsi_busy;
9342 ASC_SCSI_BIT_ID_TYPE target_id;
9343 PortAddr iop_base;
9344 ushort q_addr;
9345 ushort sg_q_addr;
9346 uchar cur_target_qng;
9347 ASC_QDONE_INFO scsiq_buf;
9348 ASC_QDONE_INFO *scsiq;
9349 int false_overrun;
9350
9351 iop_base = asc_dvc->iop_base;
9352 n_q_used = 1;
9353 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
9354 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
9355 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
9356 next_qp = AscReadLramByte(iop_base,
9357 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
9358 if (next_qp != ASC_QLINK_END) {
9359 AscPutVarDoneQTail(iop_base, next_qp);
9360 q_addr = ASC_QNO_TO_QADDR(next_qp);
9361 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
9362 asc_dvc->max_dma_count);
9363 AscWriteLramByte(iop_base,
9364 (ushort)(q_addr +
9365 (ushort)ASC_SCSIQ_B_STATUS),
9366 (uchar)(scsiq->
9367 q_status & (uchar)~(QS_READY |
9368 QS_ABORTED)));
9369 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
9370 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
9371 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
9372 sg_q_addr = q_addr;
9373 sg_list_qp = next_qp;
9374 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
9375 sg_list_qp = AscReadLramByte(iop_base,
9376 (ushort)(sg_q_addr
9377 + (ushort)
9378 ASC_SCSIQ_B_FWD));
9379 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
9380 if (sg_list_qp == ASC_QLINK_END) {
9381 AscSetLibErrorCode(asc_dvc,
9382 ASCQ_ERR_SG_Q_LINKS);
9383 scsiq->d3.done_stat = QD_WITH_ERROR;
9384 scsiq->d3.host_stat =
9385 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
9386 goto FATAL_ERR_QDONE;
9387 }
9388 AscWriteLramByte(iop_base,
9389 (ushort)(sg_q_addr + (ushort)
9390 ASC_SCSIQ_B_STATUS),
9391 QS_FREE);
9392 }
9393 n_q_used = sg_queue_cnt + 1;
9394 AscPutVarDoneQTail(iop_base, sg_list_qp);
9395 }
9396 if (asc_dvc->queue_full_or_busy & target_id) {
9397 cur_target_qng = AscReadLramByte(iop_base,
9398 (ushort)((ushort)
9399 ASC_QADR_BEG
9400 + (ushort)
9401 scsiq->d2.
9402 target_ix));
9403 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
9404 scsi_busy = AscReadLramByte(iop_base, (ushort)
9405 ASCV_SCSIBUSY_B);
9406 scsi_busy &= ~target_id;
9407 AscWriteLramByte(iop_base,
9408 (ushort)ASCV_SCSIBUSY_B,
9409 scsi_busy);
9410 asc_dvc->queue_full_or_busy &= ~target_id;
9411 }
9412 }
9413 if (asc_dvc->cur_total_qng >= n_q_used) {
9414 asc_dvc->cur_total_qng -= n_q_used;
9415 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
9416 asc_dvc->cur_dvc_qng[tid_no]--;
9417 }
9418 } else {
9419 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
9420 scsiq->d3.done_stat = QD_WITH_ERROR;
9421 goto FATAL_ERR_QDONE;
9422 }
9423 if ((scsiq->d2.srb_ptr == 0UL) ||
9424 ((scsiq->q_status & QS_ABORTED) != 0)) {
9425 return (0x11);
9426 } else if (scsiq->q_status == QS_DONE) {
9427 false_overrun = FALSE;
9428 if (scsiq->extra_bytes != 0) {
9429 scsiq->remain_bytes +=
9430 (ADV_DCNT)scsiq->extra_bytes;
9431 }
9432 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
9433 if (scsiq->d3.host_stat ==
9434 QHSTA_M_DATA_OVER_RUN) {
9435 if ((scsiq->
9436 cntl & (QC_DATA_IN | QC_DATA_OUT))
9437 == 0) {
9438 scsiq->d3.done_stat =
9439 QD_NO_ERROR;
9440 scsiq->d3.host_stat =
9441 QHSTA_NO_ERROR;
9442 } else if (false_overrun) {
9443 scsiq->d3.done_stat =
9444 QD_NO_ERROR;
9445 scsiq->d3.host_stat =
9446 QHSTA_NO_ERROR;
9447 }
9448 } else if (scsiq->d3.host_stat ==
9449 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
9450 AscStopChip(iop_base);
9451 AscSetChipControl(iop_base,
9452 (uchar)(CC_SCSI_RESET
9453 | CC_HALT));
9454 udelay(60);
9455 AscSetChipControl(iop_base, CC_HALT);
9456 AscSetChipStatus(iop_base,
9457 CIW_CLR_SCSI_RESET_INT);
9458 AscSetChipStatus(iop_base, 0);
9459 AscSetChipControl(iop_base, 0);
9460 }
9461 }
9462 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9463 asc_isr_callback(asc_dvc, scsiq);
9464 } else {
9465 if ((AscReadLramByte(iop_base,
9466 (ushort)(q_addr + (ushort)
9467 ASC_SCSIQ_CDB_BEG))
9468 == START_STOP)) {
9469 asc_dvc->unit_not_ready &= ~target_id;
9470 if (scsiq->d3.done_stat != QD_NO_ERROR) {
9471 asc_dvc->start_motor &=
9472 ~target_id;
9473 }
9474 }
9475 }
9476 return (1);
9477 } else {
9478 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
9479 FATAL_ERR_QDONE:
9480 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9481 asc_isr_callback(asc_dvc, scsiq);
9482 }
9483 return (0x80);
9484 }
9485 }
9486 return (0);
9487}
9488
9489static int AscISR(ASC_DVC_VAR *asc_dvc)
9490{
9491 ASC_CS_TYPE chipstat;
9492 PortAddr iop_base;
9493 ushort saved_ram_addr;
9494 uchar ctrl_reg;
9495 uchar saved_ctrl_reg;
9496 int int_pending;
9497 int status;
9498 uchar host_flag;
9499
9500 iop_base = asc_dvc->iop_base;
9501 int_pending = FALSE;
9502
9503 if (AscIsIntPending(iop_base) == 0)
9504 return int_pending;
9505
9506 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
9507 return ERR;
9508 }
9509 if (asc_dvc->in_critical_cnt != 0) {
9510 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
9511 return ERR;
9512 }
9513 if (asc_dvc->is_in_int) {
9514 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
9515 return ERR;
9516 }
9517 asc_dvc->is_in_int = TRUE;
9518 ctrl_reg = AscGetChipControl(iop_base);
9519 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
9520 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
9521 chipstat = AscGetChipStatus(iop_base);
9522 if (chipstat & CSW_SCSI_RESET_LATCH) {
9523 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
9524 int i = 10;
9525 int_pending = TRUE;
9526 asc_dvc->sdtr_done = 0;
9527 saved_ctrl_reg &= (uchar)(~CC_HALT);
9528 while ((AscGetChipStatus(iop_base) &
9529 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
9530 mdelay(100);
9531 }
9532 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
9533 AscSetChipControl(iop_base, CC_HALT);
9534 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9535 AscSetChipStatus(iop_base, 0);
9536 chipstat = AscGetChipStatus(iop_base);
9537 }
9538 }
9539 saved_ram_addr = AscGetChipLramAddr(iop_base);
9540 host_flag = AscReadLramByte(iop_base,
9541 ASCV_HOST_FLAG_B) &
9542 (uchar)(~ASC_HOST_FLAG_IN_ISR);
9543 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
9544 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
9545 if ((chipstat & CSW_INT_PENDING) || (int_pending)) {
9546 AscAckInterrupt(iop_base);
9547 int_pending = TRUE;
9548 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
9549 if (AscIsrChipHalted(asc_dvc) == ERR) {
9550 goto ISR_REPORT_QDONE_FATAL_ERROR;
9551 } else {
9552 saved_ctrl_reg &= (uchar)(~CC_HALT);
9553 }
9554 } else {
9555 ISR_REPORT_QDONE_FATAL_ERROR:
9556 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
9557 while (((status =
9558 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
9559 }
9560 } else {
9561 do {
9562 if ((status =
9563 AscIsrQDone(asc_dvc)) == 1) {
9564 break;
9565 }
9566 } while (status == 0x11);
9567 }
9568 if ((status & 0x80) != 0)
9569 int_pending = ERR;
9570 }
9571 }
9572 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9573 AscSetChipLramAddr(iop_base, saved_ram_addr);
9574 AscSetChipControl(iop_base, saved_ctrl_reg);
9575 asc_dvc->is_in_int = FALSE;
9576 return int_pending;
9577}
9578
9579/*
9580 * advansys_reset()
9581 *
9582 * Reset the bus associated with the command 'scp'.
9583 *
9584 * This function runs its own thread. Interrupts must be blocked but
9585 * sleeping is allowed and no locking other than for host structures is
9586 * required. Returns SUCCESS or FAILED.
9587 */
9588static int advansys_reset(struct scsi_cmnd *scp)
9589{
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009590 struct Scsi_Host *shost = scp->device->host;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009591 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009592 unsigned long flags;
Matthew Wilcox51219352007-10-02 21:55:22 -04009593 int status;
9594 int ret = SUCCESS;
9595
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009596 ASC_DBG(1, "0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009597
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009598 ASC_STATS(shost, reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04009599
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009600 scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009601
9602 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009603 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009604
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009605 /* Reset the chip and SCSI bus. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009606 ASC_DBG(1, "before AscInitAsc1000Driver()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009607 status = AscInitAsc1000Driver(asc_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009608
9609 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009610 if (asc_dvc->err_code) {
9611 scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
9612 "0x%x\n", asc_dvc->err_code);
Matthew Wilcox51219352007-10-02 21:55:22 -04009613 ret = FAILED;
9614 } else if (status) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009615 scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
9616 "0x%x\n", status);
Matthew Wilcox51219352007-10-02 21:55:22 -04009617 } else {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009618 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9619 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009620 }
9621
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009622 ASC_DBG(1, "after AscInitAsc1000Driver()\n");
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009623 spin_lock_irqsave(shost->host_lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009624 } else {
9625 /*
Matthew Wilcox51219352007-10-02 21:55:22 -04009626 * If the suggest reset bus flags are set, then reset the bus.
9627 * Otherwise only reset the device.
9628 */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009629 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009630
9631 /*
9632 * Reset the target's SCSI bus.
9633 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009634 ASC_DBG(1, "before AdvResetChipAndSB()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009635 switch (AdvResetChipAndSB(adv_dvc)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04009636 case ASC_TRUE:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009637 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9638 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009639 break;
9640 case ASC_FALSE:
9641 default:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009642 scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009643 ret = FAILED;
9644 break;
9645 }
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009646 spin_lock_irqsave(shost->host_lock, flags);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009647 AdvISR(adv_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009648 }
Matthew Wilcox51219352007-10-02 21:55:22 -04009649
9650 /* Save the time of the most recently completed reset. */
9651 boardp->last_reset = jiffies;
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009652 spin_unlock_irqrestore(shost->host_lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009653
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009654 ASC_DBG(1, "ret %d\n", ret);
Matthew Wilcox51219352007-10-02 21:55:22 -04009655
9656 return ret;
9657}
9658
9659/*
9660 * advansys_biosparam()
9661 *
9662 * Translate disk drive geometry if the "BIOS greater than 1 GB"
9663 * support is enabled for a drive.
9664 *
9665 * ip (information pointer) is an int array with the following definition:
9666 * ip[0]: heads
9667 * ip[1]: sectors
9668 * ip[2]: cylinders
9669 */
9670static int
9671advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
9672 sector_t capacity, int ip[])
9673{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009674 struct asc_board *boardp = shost_priv(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04009675
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009676 ASC_DBG(1, "begin\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009677 ASC_STATS(sdev->host, biosparam);
Matthew Wilcox51219352007-10-02 21:55:22 -04009678 if (ASC_NARROW_BOARD(boardp)) {
9679 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
9680 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
9681 ip[0] = 255;
9682 ip[1] = 63;
9683 } else {
9684 ip[0] = 64;
9685 ip[1] = 32;
9686 }
9687 } else {
9688 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
9689 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
9690 ip[0] = 255;
9691 ip[1] = 63;
9692 } else {
9693 ip[0] = 64;
9694 ip[1] = 32;
9695 }
9696 }
9697 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009698 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009699 return 0;
9700}
9701
9702/*
9703 * First-level interrupt handler.
9704 *
9705 * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host.
9706 */
9707static irqreturn_t advansys_interrupt(int irq, void *dev_id)
9708{
Matthew Wilcox51219352007-10-02 21:55:22 -04009709 struct Scsi_Host *shost = dev_id;
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009710 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox51219352007-10-02 21:55:22 -04009711 irqreturn_t result = IRQ_NONE;
9712
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009713 ASC_DBG(2, "boardp 0x%p\n", boardp);
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009714 spin_lock(shost->host_lock);
Matthew Wilcox51219352007-10-02 21:55:22 -04009715 if (ASC_NARROW_BOARD(boardp)) {
9716 if (AscIsIntPending(shost->io_port)) {
9717 result = IRQ_HANDLED;
9718 ASC_STATS(shost, interrupt);
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009719 ASC_DBG(1, "before AscISR()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009720 AscISR(&boardp->dvc_var.asc_dvc_var);
9721 }
9722 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009723 ASC_DBG(1, "before AdvISR()\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009724 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
9725 result = IRQ_HANDLED;
9726 ASC_STATS(shost, interrupt);
9727 }
9728 }
Matthew Wilcoxf092d222007-10-02 21:55:34 -04009729 spin_unlock(shost->host_lock);
Matthew Wilcox51219352007-10-02 21:55:22 -04009730
Matthew Wilcoxb352f922007-10-02 21:55:33 -04009731 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009732 return result;
9733}
9734
9735static int AscHostReqRiscHalt(PortAddr iop_base)
9736{
9737 int count = 0;
9738 int sta = 0;
9739 uchar saved_stop_code;
9740
9741 if (AscIsChipHalted(iop_base))
9742 return (1);
9743 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
9744 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9745 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
9746 do {
9747 if (AscIsChipHalted(iop_base)) {
9748 sta = 1;
9749 break;
9750 }
9751 mdelay(100);
9752 } while (count++ < 20);
9753 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
9754 return (sta);
9755}
9756
9757static int
9758AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
9759{
9760 int sta = FALSE;
9761
9762 if (AscHostReqRiscHalt(iop_base)) {
9763 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9764 AscStartChip(iop_base);
9765 }
9766 return sta;
9767}
9768
9769static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
9770{
9771 char type = sdev->type;
9772 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
9773
9774 if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN))
9775 return;
9776 if (asc_dvc->init_sdtr & tid_bits)
9777 return;
9778
9779 if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0))
9780 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9781
9782 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
9783 if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) ||
9784 (type == TYPE_ROM) || (type == TYPE_TAPE))
9785 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9786
9787 if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
9788 AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id,
9789 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
9790}
9791
9792static void
9793advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
9794{
9795 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
9796 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
9797
9798 if (sdev->lun == 0) {
9799 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
9800 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
9801 asc_dvc->init_sdtr |= tid_bit;
9802 } else {
9803 asc_dvc->init_sdtr &= ~tid_bit;
9804 }
9805
9806 if (orig_init_sdtr != asc_dvc->init_sdtr)
9807 AscAsyncFix(asc_dvc, sdev);
9808 }
9809
9810 if (sdev->tagged_supported) {
9811 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
9812 if (sdev->lun == 0) {
9813 asc_dvc->cfg->can_tagged_qng |= tid_bit;
9814 asc_dvc->use_tagged_qng |= tid_bit;
9815 }
9816 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9817 asc_dvc->max_dvc_qng[sdev->id]);
9818 }
9819 } else {
9820 if (sdev->lun == 0) {
9821 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
9822 asc_dvc->use_tagged_qng &= ~tid_bit;
9823 }
9824 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9825 }
9826
9827 if ((sdev->lun == 0) &&
9828 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
9829 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
9830 asc_dvc->cfg->disc_enable);
9831 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
9832 asc_dvc->use_tagged_qng);
9833 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
9834 asc_dvc->cfg->can_tagged_qng);
9835
9836 asc_dvc->max_dvc_qng[sdev->id] =
9837 asc_dvc->cfg->max_tag_qng[sdev->id];
9838 AscWriteLramByte(asc_dvc->iop_base,
9839 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
9840 asc_dvc->max_dvc_qng[sdev->id]);
9841 }
9842}
9843
9844/*
9845 * Wide Transfers
9846 *
9847 * If the EEPROM enabled WDTR for the device and the device supports wide
9848 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
9849 * write the new value to the microcode.
9850 */
9851static void
9852advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
9853{
9854 unsigned short cfg_word;
9855 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9856 if ((cfg_word & tidmask) != 0)
9857 return;
9858
9859 cfg_word |= tidmask;
9860 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9861
9862 /*
9863 * Clear the microcode SDTR and WDTR negotiation done indicators for
9864 * the target to cause it to negotiate with the new setting set above.
9865 * WDTR when accepted causes the target to enter asynchronous mode, so
9866 * SDTR must be negotiated.
9867 */
9868 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9869 cfg_word &= ~tidmask;
9870 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9871 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
9872 cfg_word &= ~tidmask;
9873 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
9874}
9875
9876/*
9877 * Synchronous Transfers
9878 *
9879 * If the EEPROM enabled SDTR for the device and the device
9880 * supports synchronous transfers, then turn on the device's
9881 * 'sdtr_able' bit. Write the new value to the microcode.
9882 */
9883static void
9884advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
9885{
9886 unsigned short cfg_word;
9887 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
9888 if ((cfg_word & tidmask) != 0)
9889 return;
9890
9891 cfg_word |= tidmask;
9892 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
9893
9894 /*
9895 * Clear the microcode "SDTR negotiation" done indicator for the
9896 * target to cause it to negotiate with the new setting set above.
9897 */
9898 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9899 cfg_word &= ~tidmask;
9900 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
9901}
9902
9903/*
9904 * PPR (Parallel Protocol Request) Capable
9905 *
9906 * If the device supports DT mode, then it must be PPR capable.
9907 * The PPR message will be used in place of the SDTR and WDTR
9908 * messages to negotiate synchronous speed and offset, transfer
9909 * width, and protocol options.
9910 */
9911static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
9912 AdvPortAddr iop_base, unsigned short tidmask)
9913{
9914 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
9915 adv_dvc->ppr_able |= tidmask;
9916 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
9917}
9918
9919static void
9920advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
9921{
9922 AdvPortAddr iop_base = adv_dvc->iop_base;
9923 unsigned short tidmask = 1 << sdev->id;
9924
9925 if (sdev->lun == 0) {
9926 /*
9927 * Handle WDTR, SDTR, and Tag Queuing. If the feature
9928 * is enabled in the EEPROM and the device supports the
9929 * feature, then enable it in the microcode.
9930 */
9931
9932 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
9933 advansys_wide_enable_wdtr(iop_base, tidmask);
9934 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
9935 advansys_wide_enable_sdtr(iop_base, tidmask);
9936 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
9937 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
9938
9939 /*
9940 * Tag Queuing is disabled for the BIOS which runs in polled
9941 * mode and would see no benefit from Tag Queuing. Also by
9942 * disabling Tag Queuing in the BIOS devices with Tag Queuing
9943 * bugs will at least work with the BIOS.
9944 */
9945 if ((adv_dvc->tagqng_able & tidmask) &&
9946 sdev->tagged_supported) {
9947 unsigned short cfg_word;
9948 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
9949 cfg_word |= tidmask;
9950 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
9951 cfg_word);
9952 AdvWriteByteLram(iop_base,
9953 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
9954 adv_dvc->max_dvc_qng);
9955 }
9956 }
9957
9958 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
9959 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9960 adv_dvc->max_dvc_qng);
9961 } else {
9962 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9963 }
9964}
9965
9966/*
9967 * Set the number of commands to queue per device for the
9968 * specified host adapter.
9969 */
9970static int advansys_slave_configure(struct scsi_device *sdev)
9971{
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009972 struct asc_board *boardp = shost_priv(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -04009973
Matthew Wilcox51219352007-10-02 21:55:22 -04009974 if (ASC_NARROW_BOARD(boardp))
9975 advansys_narrow_slave_configure(sdev,
9976 &boardp->dvc_var.asc_dvc_var);
9977 else
9978 advansys_wide_slave_configure(sdev,
9979 &boardp->dvc_var.adv_dvc_var);
9980
9981 return 0;
9982}
9983
Matthew Wilcoxd2411492007-10-02 21:55:31 -04009984static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
Matthew Wilcox05848b62007-10-02 21:55:25 -04009985 struct asc_scsi_q *asc_scsi_q)
Matthew Wilcox51219352007-10-02 21:55:22 -04009986{
Matthew Wilcox05848b62007-10-02 21:55:25 -04009987 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
Matthew Wilcox51219352007-10-02 21:55:22 -04009988
9989 /*
9990 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
9991 */
Matthew Wilcox05848b62007-10-02 21:55:25 -04009992 asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009993
9994 /*
9995 * Build the ASC_SCSI_Q request.
9996 */
Matthew Wilcox05848b62007-10-02 21:55:25 -04009997 asc_scsi_q->cdbptr = &scp->cmnd[0];
9998 asc_scsi_q->q2.cdb_len = scp->cmd_len;
9999 asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
10000 asc_scsi_q->q1.target_lun = scp->device->lun;
10001 asc_scsi_q->q2.target_ix =
Matthew Wilcox51219352007-10-02 21:55:22 -040010002 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
Matthew Wilcox05848b62007-10-02 21:55:25 -040010003 asc_scsi_q->q1.sense_addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010004 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010005 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
Matthew Wilcox51219352007-10-02 21:55:22 -040010006
10007 /*
10008 * If there are any outstanding requests for the current target,
10009 * then every 255th request send an ORDERED request. This heuristic
10010 * tries to retain the benefit of request sorting while preventing
10011 * request starvation. 255 is the max number of tags or pending commands
10012 * a device may have outstanding.
10013 *
10014 * The request count is incremented below for every successfully
10015 * started request.
10016 *
10017 */
10018 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
10019 (boardp->reqcnt[scp->device->id] % 255) == 0) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010020 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010021 } else {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010022 asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010023 }
10024
10025 /*
10026 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
10027 * buffer command.
10028 */
10029 if (scp->use_sg == 0) {
10030 /*
10031 * CDB request of single contiguous buffer.
10032 */
10033 ASC_STATS(scp->device->host, cont_cnt);
10034 scp->SCp.dma_handle = scp->request_bufflen ?
10035 dma_map_single(boardp->dev, scp->request_buffer,
10036 scp->request_bufflen,
10037 scp->sc_data_direction) : 0;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010038 asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
10039 asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen);
Matthew Wilcox51219352007-10-02 21:55:22 -040010040 ASC_STATS_ADD(scp->device->host, cont_xfer,
10041 ASC_CEILING(scp->request_bufflen, 512));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010042 asc_scsi_q->q1.sg_queue_cnt = 0;
10043 asc_scsi_q->sg_head = NULL;
Matthew Wilcox51219352007-10-02 21:55:22 -040010044 } else {
10045 /*
10046 * CDB scatter-gather request list.
10047 */
10048 int sgcnt;
10049 int use_sg;
10050 struct scatterlist *slp;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010051 struct asc_sg_head *asc_sg_head;
Matthew Wilcox51219352007-10-02 21:55:22 -040010052
10053 slp = (struct scatterlist *)scp->request_buffer;
10054 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10055 scp->sc_data_direction);
10056
10057 if (use_sg > scp->device->host->sg_tablesize) {
10058 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
10059 "sg_tablesize %d\n", boardp->id, use_sg,
10060 scp->device->host->sg_tablesize);
10061 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10062 scp->sc_data_direction);
10063 scp->result = HOST_BYTE(DID_ERROR);
10064 return ASC_ERROR;
10065 }
10066
10067 ASC_STATS(scp->device->host, sg_cnt);
10068
Matthew Wilcox05848b62007-10-02 21:55:25 -040010069 asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
10070 use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
10071 if (!asc_sg_head) {
10072 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10073 scp->sc_data_direction);
10074 scp->result = HOST_BYTE(DID_SOFT_ERROR);
10075 return ASC_ERROR;
10076 }
Matthew Wilcox51219352007-10-02 21:55:22 -040010077
Matthew Wilcox05848b62007-10-02 21:55:25 -040010078 asc_scsi_q->q1.cntl |= QC_SG_HEAD;
10079 asc_scsi_q->sg_head = asc_sg_head;
10080 asc_scsi_q->q1.data_cnt = 0;
10081 asc_scsi_q->q1.data_addr = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040010082 /* This is a byte value, otherwise it would need to be swapped. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010083 asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
Matthew Wilcox51219352007-10-02 21:55:22 -040010084 ASC_STATS_ADD(scp->device->host, sg_elem,
Matthew Wilcox05848b62007-10-02 21:55:25 -040010085 asc_sg_head->entry_cnt);
Matthew Wilcox51219352007-10-02 21:55:22 -040010086
10087 /*
10088 * Convert scatter-gather list into ASC_SG_HEAD list.
10089 */
10090 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010091 asc_sg_head->sg_list[sgcnt].addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010092 cpu_to_le32(sg_dma_address(slp));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010093 asc_sg_head->sg_list[sgcnt].bytes =
Matthew Wilcox51219352007-10-02 21:55:22 -040010094 cpu_to_le32(sg_dma_len(slp));
10095 ASC_STATS_ADD(scp->device->host, sg_xfer,
10096 ASC_CEILING(sg_dma_len(slp), 512));
10097 }
10098 }
10099
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010100 ASC_DBG_PRT_ASC_SCSI_Q(2, asc_scsi_q);
Matthew Wilcox51219352007-10-02 21:55:22 -040010101 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10102
10103 return ASC_NOERROR;
10104}
10105
10106/*
10107 * Build scatter-gather list for Adv Library (Wide Board).
10108 *
10109 * Additional ADV_SG_BLOCK structures will need to be allocated
10110 * if the total number of scatter-gather elements exceeds
10111 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
10112 * assumed to be physically contiguous.
10113 *
10114 * Return:
10115 * ADV_SUCCESS(1) - SG List successfully created
10116 * ADV_ERROR(-1) - SG List creation failed
10117 */
10118static int
Matthew Wilcoxd2411492007-10-02 21:55:31 -040010119adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
Matthew Wilcox51219352007-10-02 21:55:22 -040010120 int use_sg)
10121{
10122 adv_sgblk_t *sgblkp;
10123 ADV_SCSI_REQ_Q *scsiqp;
10124 struct scatterlist *slp;
10125 int sg_elem_cnt;
10126 ADV_SG_BLOCK *sg_block, *prev_sg_block;
10127 ADV_PADDR sg_block_paddr;
10128 int i;
10129
10130 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10131 slp = (struct scatterlist *)scp->request_buffer;
10132 sg_elem_cnt = use_sg;
10133 prev_sg_block = NULL;
10134 reqp->sgblkp = NULL;
10135
10136 for (;;) {
10137 /*
10138 * Allocate a 'adv_sgblk_t' structure from the board free
10139 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
10140 * (15) scatter-gather elements.
10141 */
10142 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010143 ASC_DBG(1, "no free adv_sgblk_t\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040010144 ASC_STATS(scp->device->host, adv_build_nosg);
10145
10146 /*
10147 * Allocation failed. Free 'adv_sgblk_t' structures
10148 * already allocated for the request.
10149 */
10150 while ((sgblkp = reqp->sgblkp) != NULL) {
10151 /* Remove 'sgblkp' from the request list. */
10152 reqp->sgblkp = sgblkp->next_sgblkp;
10153
10154 /* Add 'sgblkp' to the board free list. */
10155 sgblkp->next_sgblkp = boardp->adv_sgblkp;
10156 boardp->adv_sgblkp = sgblkp;
10157 }
10158 return ASC_BUSY;
10159 }
10160
10161 /* Complete 'adv_sgblk_t' board allocation. */
10162 boardp->adv_sgblkp = sgblkp->next_sgblkp;
10163 sgblkp->next_sgblkp = NULL;
10164
10165 /*
10166 * Get 8 byte aligned virtual and physical addresses
10167 * for the allocated ADV_SG_BLOCK structure.
10168 */
10169 sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
10170 sg_block_paddr = virt_to_bus(sg_block);
10171
10172 /*
10173 * Check if this is the first 'adv_sgblk_t' for the
10174 * request.
10175 */
10176 if (reqp->sgblkp == NULL) {
10177 /* Request's first scatter-gather block. */
10178 reqp->sgblkp = sgblkp;
10179
10180 /*
10181 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
10182 * address pointers.
10183 */
10184 scsiqp->sg_list_ptr = sg_block;
10185 scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
10186 } else {
10187 /* Request's second or later scatter-gather block. */
10188 sgblkp->next_sgblkp = reqp->sgblkp;
10189 reqp->sgblkp = sgblkp;
10190
10191 /*
10192 * Point the previous ADV_SG_BLOCK structure to
10193 * the newly allocated ADV_SG_BLOCK structure.
10194 */
10195 prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
10196 }
10197
10198 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
10199 sg_block->sg_list[i].sg_addr =
10200 cpu_to_le32(sg_dma_address(slp));
10201 sg_block->sg_list[i].sg_count =
10202 cpu_to_le32(sg_dma_len(slp));
10203 ASC_STATS_ADD(scp->device->host, sg_xfer,
10204 ASC_CEILING(sg_dma_len(slp), 512));
10205
10206 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
10207 sg_block->sg_cnt = i + 1;
10208 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
10209 return ADV_SUCCESS;
10210 }
10211 slp++;
10212 }
10213 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
10214 prev_sg_block = sg_block;
10215 }
10216}
10217
10218/*
10219 * Build a request structure for the Adv Library (Wide Board).
10220 *
10221 * If an adv_req_t can not be allocated to issue the request,
10222 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
10223 *
10224 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
10225 * microcode for DMA addresses or math operations are byte swapped
10226 * to little-endian order.
10227 */
10228static int
Matthew Wilcoxd2411492007-10-02 21:55:31 -040010229adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
Matthew Wilcox51219352007-10-02 21:55:22 -040010230 ADV_SCSI_REQ_Q **adv_scsiqpp)
10231{
10232 adv_req_t *reqp;
10233 ADV_SCSI_REQ_Q *scsiqp;
10234 int i;
10235 int ret;
10236
10237 /*
10238 * Allocate an adv_req_t structure from the board to execute
10239 * the command.
10240 */
10241 if (boardp->adv_reqp == NULL) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040010242 ASC_DBG(1, "no free adv_req_t\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040010243 ASC_STATS(scp->device->host, adv_build_noreq);
10244 return ASC_BUSY;
10245 } else {
10246 reqp = boardp->adv_reqp;
10247 boardp->adv_reqp = reqp->next_reqp;
10248 reqp->next_reqp = NULL;
10249 }
10250
10251 /*
10252 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
10253 */
10254 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10255
10256 /*
10257 * Initialize the structure.
10258 */
10259 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
10260
10261 /*
10262 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
10263 */
10264 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
10265
10266 /*
10267 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
10268 */
10269 reqp->cmndp = scp;
10270
10271 /*
10272 * Build the ADV_SCSI_REQ_Q request.
10273 */
10274
10275 /* Set CDB length and copy it to the request structure. */
10276 scsiqp->cdb_len = scp->cmd_len;
10277 /* Copy first 12 CDB bytes to cdb[]. */
10278 for (i = 0; i < scp->cmd_len && i < 12; i++) {
10279 scsiqp->cdb[i] = scp->cmnd[i];
10280 }
10281 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
10282 for (; i < scp->cmd_len; i++) {
10283 scsiqp->cdb16[i - 12] = scp->cmnd[i];
10284 }
10285
10286 scsiqp->target_id = scp->device->id;
10287 scsiqp->target_lun = scp->device->lun;
10288
10289 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
10290 scsiqp->sense_len = sizeof(scp->sense_buffer);
10291
10292 /*
10293 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
10294 * buffer command.
10295 */
10296
10297 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10298 scsiqp->vdata_addr = scp->request_buffer;
10299 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
10300
10301 if (scp->use_sg == 0) {
10302 /*
10303 * CDB request of single contiguous buffer.
10304 */
10305 reqp->sgblkp = NULL;
10306 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10307 if (scp->request_bufflen) {
10308 scsiqp->vdata_addr = scp->request_buffer;
10309 scp->SCp.dma_handle =
10310 dma_map_single(boardp->dev, scp->request_buffer,
10311 scp->request_bufflen,
10312 scp->sc_data_direction);
10313 } else {
10314 scsiqp->vdata_addr = NULL;
10315 scp->SCp.dma_handle = 0;
10316 }
10317 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
10318 scsiqp->sg_list_ptr = NULL;
10319 scsiqp->sg_real_addr = 0;
10320 ASC_STATS(scp->device->host, cont_cnt);
10321 ASC_STATS_ADD(scp->device->host, cont_xfer,
10322 ASC_CEILING(scp->request_bufflen, 512));
10323 } else {
10324 /*
10325 * CDB scatter-gather request list.
10326 */
10327 struct scatterlist *slp;
10328 int use_sg;
10329
10330 slp = (struct scatterlist *)scp->request_buffer;
10331 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10332 scp->sc_data_direction);
10333
10334 if (use_sg > ADV_MAX_SG_LIST) {
10335 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
10336 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
10337 scp->device->host->sg_tablesize);
10338 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10339 scp->sc_data_direction);
10340 scp->result = HOST_BYTE(DID_ERROR);
10341
10342 /*
10343 * Free the 'adv_req_t' structure by adding it back
10344 * to the board free list.
10345 */
10346 reqp->next_reqp = boardp->adv_reqp;
10347 boardp->adv_reqp = reqp;
10348
10349 return ASC_ERROR;
10350 }
10351
10352 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
10353 if (ret != ADV_SUCCESS) {
10354 /*
10355 * Free the adv_req_t structure by adding it back to
10356 * the board free list.
10357 */
10358 reqp->next_reqp = boardp->adv_reqp;
10359 boardp->adv_reqp = reqp;
10360
10361 return ret;
10362 }
10363
10364 ASC_STATS(scp->device->host, sg_cnt);
10365 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
10366 }
10367
10368 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
10369 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10370
10371 *adv_scsiqpp = scsiqp;
10372
10373 return ASC_NOERROR;
10374}
10375
10376static int AscSgListToQueue(int sg_list)
10377{
10378 int n_sg_list_qs;
10379
10380 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
10381 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
10382 n_sg_list_qs++;
10383 return n_sg_list_qs + 1;
10384}
10385
10386static uint
10387AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
10388{
10389 uint cur_used_qs;
10390 uint cur_free_qs;
10391 ASC_SCSI_BIT_ID_TYPE target_id;
10392 uchar tid_no;
10393
10394 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
10395 tid_no = ASC_TIX_TO_TID(target_ix);
10396 if ((asc_dvc->unit_not_ready & target_id) ||
10397 (asc_dvc->queue_full_or_busy & target_id)) {
10398 return 0;
10399 }
10400 if (n_qs == 1) {
10401 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10402 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
10403 } else {
10404 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10405 (uint) ASC_MIN_FREE_Q;
10406 }
10407 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
10408 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
10409 if (asc_dvc->cur_dvc_qng[tid_no] >=
10410 asc_dvc->max_dvc_qng[tid_no]) {
10411 return 0;
10412 }
10413 return cur_free_qs;
10414 }
10415 if (n_qs > 1) {
10416 if ((n_qs > asc_dvc->last_q_shortage)
10417 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
10418 asc_dvc->last_q_shortage = n_qs;
10419 }
10420 }
10421 return 0;
10422}
10423
10424static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
10425{
10426 ushort q_addr;
10427 uchar next_qp;
10428 uchar q_status;
10429
10430 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10431 q_status = (uchar)AscReadLramByte(iop_base,
10432 (ushort)(q_addr +
10433 ASC_SCSIQ_B_STATUS));
10434 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10435 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END))
10436 return next_qp;
10437 return ASC_QLINK_END;
10438}
10439
10440static uchar
10441AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
10442{
10443 uchar i;
10444
10445 for (i = 0; i < n_free_q; i++) {
10446 free_q_head = AscAllocFreeQueue(iop_base, free_q_head);
10447 if (free_q_head == ASC_QLINK_END)
10448 break;
10449 }
10450 return free_q_head;
10451}
10452
10453/*
10454 * void
10455 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10456 *
10457 * Calling/Exit State:
10458 * none
10459 *
10460 * Description:
10461 * Output an ASC_SCSI_Q structure to the chip
10462 */
10463static void
10464DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10465{
10466 int i;
10467
10468 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
10469 AscSetChipLramAddr(iop_base, s_addr);
10470 for (i = 0; i < 2 * words; i += 2) {
10471 if (i == 4 || i == 20) {
10472 continue;
10473 }
10474 outpw(iop_base + IOP_RAM_DATA,
10475 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
10476 }
10477}
10478
10479static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10480{
10481 ushort q_addr;
10482 uchar tid_no;
10483 uchar sdtr_data;
10484 uchar syn_period_ix;
10485 uchar syn_offset;
10486 PortAddr iop_base;
10487
10488 iop_base = asc_dvc->iop_base;
10489 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
10490 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
10491 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
10492 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10493 syn_period_ix =
10494 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
10495 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
10496 AscMsgOutSDTR(asc_dvc,
10497 asc_dvc->sdtr_period_tbl[syn_period_ix],
10498 syn_offset);
10499 scsiq->q1.cntl |= QC_MSG_OUT;
10500 }
10501 q_addr = ASC_QNO_TO_QADDR(q_no);
10502 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
10503 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10504 }
10505 scsiq->q1.status = QS_FREE;
10506 AscMemWordCopyPtrToLram(iop_base,
10507 q_addr + ASC_SCSIQ_CDB_BEG,
10508 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
10509
10510 DvcPutScsiQ(iop_base,
10511 q_addr + ASC_SCSIQ_CPY_BEG,
10512 (uchar *)&scsiq->q1.cntl,
10513 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
10514 AscWriteLramWord(iop_base,
10515 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
10516 (ushort)(((ushort)scsiq->q1.
10517 q_no << 8) | (ushort)QS_READY));
10518 return 1;
10519}
10520
10521static int
10522AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10523{
10524 int sta;
10525 int i;
10526 ASC_SG_HEAD *sg_head;
10527 ASC_SG_LIST_Q scsi_sg_q;
10528 ASC_DCNT saved_data_addr;
10529 ASC_DCNT saved_data_cnt;
10530 PortAddr iop_base;
10531 ushort sg_list_dwords;
10532 ushort sg_index;
10533 ushort sg_entry_cnt;
10534 ushort q_addr;
10535 uchar next_qp;
10536
10537 iop_base = asc_dvc->iop_base;
10538 sg_head = scsiq->sg_head;
10539 saved_data_addr = scsiq->q1.data_addr;
10540 saved_data_cnt = scsiq->q1.data_cnt;
10541 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
10542 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
10543#if CC_VERY_LONG_SG_LIST
10544 /*
10545 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
10546 * then not all SG elements will fit in the allocated queues.
10547 * The rest of the SG elements will be copied when the RISC
10548 * completes the SG elements that fit and halts.
10549 */
10550 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10551 /*
10552 * Set sg_entry_cnt to be the number of SG elements that
10553 * will fit in the allocated SG queues. It is minus 1, because
10554 * the first SG element is handled above. ASC_MAX_SG_LIST is
10555 * already inflated by 1 to account for this. For example it
10556 * may be 50 which is 1 + 7 queues * 7 SG elements.
10557 */
10558 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
10559
10560 /*
10561 * Keep track of remaining number of SG elements that will
10562 * need to be handled from a_isr.c.
10563 */
10564 scsiq->remain_sg_entry_cnt =
10565 sg_head->entry_cnt - ASC_MAX_SG_LIST;
10566 } else {
10567#endif /* CC_VERY_LONG_SG_LIST */
10568 /*
10569 * Set sg_entry_cnt to be the number of SG elements that
10570 * will fit in the allocated SG queues. It is minus 1, because
10571 * the first SG element is handled above.
10572 */
10573 sg_entry_cnt = sg_head->entry_cnt - 1;
10574#if CC_VERY_LONG_SG_LIST
10575 }
10576#endif /* CC_VERY_LONG_SG_LIST */
10577 if (sg_entry_cnt != 0) {
10578 scsiq->q1.cntl |= QC_SG_HEAD;
10579 q_addr = ASC_QNO_TO_QADDR(q_no);
10580 sg_index = 1;
10581 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
10582 scsi_sg_q.sg_head_qp = q_no;
10583 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
10584 for (i = 0; i < sg_head->queue_cnt; i++) {
10585 scsi_sg_q.seq_no = i + 1;
10586 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
10587 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
10588 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
10589 if (i == 0) {
10590 scsi_sg_q.sg_list_cnt =
10591 ASC_SG_LIST_PER_Q;
10592 scsi_sg_q.sg_cur_list_cnt =
10593 ASC_SG_LIST_PER_Q;
10594 } else {
10595 scsi_sg_q.sg_list_cnt =
10596 ASC_SG_LIST_PER_Q - 1;
10597 scsi_sg_q.sg_cur_list_cnt =
10598 ASC_SG_LIST_PER_Q - 1;
10599 }
10600 } else {
10601#if CC_VERY_LONG_SG_LIST
10602 /*
10603 * This is the last SG queue in the list of
10604 * allocated SG queues. If there are more
10605 * SG elements than will fit in the allocated
10606 * queues, then set the QCSG_SG_XFER_MORE flag.
10607 */
10608 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10609 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
10610 } else {
10611#endif /* CC_VERY_LONG_SG_LIST */
10612 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
10613#if CC_VERY_LONG_SG_LIST
10614 }
10615#endif /* CC_VERY_LONG_SG_LIST */
10616 sg_list_dwords = sg_entry_cnt << 1;
10617 if (i == 0) {
10618 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
10619 scsi_sg_q.sg_cur_list_cnt =
10620 sg_entry_cnt;
10621 } else {
10622 scsi_sg_q.sg_list_cnt =
10623 sg_entry_cnt - 1;
10624 scsi_sg_q.sg_cur_list_cnt =
10625 sg_entry_cnt - 1;
10626 }
10627 sg_entry_cnt = 0;
10628 }
10629 next_qp = AscReadLramByte(iop_base,
10630 (ushort)(q_addr +
10631 ASC_SCSIQ_B_FWD));
10632 scsi_sg_q.q_no = next_qp;
10633 q_addr = ASC_QNO_TO_QADDR(next_qp);
10634 AscMemWordCopyPtrToLram(iop_base,
10635 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
10636 (uchar *)&scsi_sg_q,
10637 sizeof(ASC_SG_LIST_Q) >> 1);
10638 AscMemDWordCopyPtrToLram(iop_base,
10639 q_addr + ASC_SGQ_LIST_BEG,
10640 (uchar *)&sg_head->
10641 sg_list[sg_index],
10642 sg_list_dwords);
10643 sg_index += ASC_SG_LIST_PER_Q;
10644 scsiq->next_sg_index = sg_index;
10645 }
10646 } else {
10647 scsiq->q1.cntl &= ~QC_SG_HEAD;
10648 }
10649 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
10650 scsiq->q1.data_addr = saved_data_addr;
10651 scsiq->q1.data_cnt = saved_data_cnt;
10652 return (sta);
10653}
10654
10655static int
10656AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
10657{
10658 PortAddr iop_base;
10659 uchar free_q_head;
10660 uchar next_qp;
10661 uchar tid_no;
10662 uchar target_ix;
10663 int sta;
10664
10665 iop_base = asc_dvc->iop_base;
10666 target_ix = scsiq->q2.target_ix;
10667 tid_no = ASC_TIX_TO_TID(target_ix);
10668 sta = 0;
10669 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
10670 if (n_q_required > 1) {
10671 next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head,
10672 (uchar)n_q_required);
10673 if (next_qp != ASC_QLINK_END) {
10674 asc_dvc->last_q_shortage = 0;
10675 scsiq->sg_head->queue_cnt = n_q_required - 1;
10676 scsiq->q1.q_no = free_q_head;
10677 sta = AscPutReadySgListQueue(asc_dvc, scsiq,
10678 free_q_head);
10679 }
10680 } else if (n_q_required == 1) {
10681 next_qp = AscAllocFreeQueue(iop_base, free_q_head);
10682 if (next_qp != ASC_QLINK_END) {
10683 scsiq->q1.q_no = free_q_head;
10684 sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head);
10685 }
10686 }
10687 if (sta == 1) {
10688 AscPutVarFreeQHead(iop_base, next_qp);
10689 asc_dvc->cur_total_qng += n_q_required;
10690 asc_dvc->cur_dvc_qng[tid_no]++;
10691 }
10692 return sta;
10693}
10694
10695#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
10696static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
10697 INQUIRY,
10698 REQUEST_SENSE,
10699 READ_CAPACITY,
10700 READ_TOC,
10701 MODE_SELECT,
10702 MODE_SENSE,
10703 MODE_SELECT_10,
10704 MODE_SENSE_10,
10705 0xFF,
10706 0xFF,
10707 0xFF,
10708 0xFF,
10709 0xFF,
10710 0xFF,
10711 0xFF,
10712 0xFF
10713};
10714
10715static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
10716{
10717 PortAddr iop_base;
10718 int sta;
10719 int n_q_required;
10720 int disable_syn_offset_one_fix;
10721 int i;
10722 ASC_PADDR addr;
10723 ushort sg_entry_cnt = 0;
10724 ushort sg_entry_cnt_minus_one = 0;
10725 uchar target_ix;
10726 uchar tid_no;
10727 uchar sdtr_data;
10728 uchar extra_bytes;
10729 uchar scsi_cmd;
10730 uchar disable_cmd;
10731 ASC_SG_HEAD *sg_head;
10732 ASC_DCNT data_cnt;
10733
10734 iop_base = asc_dvc->iop_base;
10735 sg_head = scsiq->sg_head;
10736 if (asc_dvc->err_code != 0)
10737 return (ERR);
10738 scsiq->q1.q_no = 0;
10739 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
10740 scsiq->q1.extra_bytes = 0;
10741 }
10742 sta = 0;
10743 target_ix = scsiq->q2.target_ix;
10744 tid_no = ASC_TIX_TO_TID(target_ix);
10745 n_q_required = 1;
10746 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
10747 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
10748 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
10749 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10750 AscMsgOutSDTR(asc_dvc,
10751 asc_dvc->
10752 sdtr_period_tbl[(sdtr_data >> 4) &
10753 (uchar)(asc_dvc->
10754 max_sdtr_index -
10755 1)],
10756 (uchar)(sdtr_data & (uchar)
10757 ASC_SYN_MAX_OFFSET));
10758 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
10759 }
10760 }
10761 if (asc_dvc->in_critical_cnt != 0) {
10762 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
10763 return (ERR);
10764 }
10765 asc_dvc->in_critical_cnt++;
10766 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10767 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
10768 asc_dvc->in_critical_cnt--;
10769 return (ERR);
10770 }
10771#if !CC_VERY_LONG_SG_LIST
10772 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10773 asc_dvc->in_critical_cnt--;
10774 return (ERR);
10775 }
10776#endif /* !CC_VERY_LONG_SG_LIST */
10777 if (sg_entry_cnt == 1) {
10778 scsiq->q1.data_addr =
10779 (ADV_PADDR)sg_head->sg_list[0].addr;
10780 scsiq->q1.data_cnt =
10781 (ADV_DCNT)sg_head->sg_list[0].bytes;
10782 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
10783 }
10784 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
10785 }
10786 scsi_cmd = scsiq->cdbptr[0];
10787 disable_syn_offset_one_fix = FALSE;
10788 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
10789 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
10790 if (scsiq->q1.cntl & QC_SG_HEAD) {
10791 data_cnt = 0;
10792 for (i = 0; i < sg_entry_cnt; i++) {
10793 data_cnt +=
10794 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
10795 bytes);
10796 }
10797 } else {
10798 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
10799 }
10800 if (data_cnt != 0UL) {
10801 if (data_cnt < 512UL) {
10802 disable_syn_offset_one_fix = TRUE;
10803 } else {
10804 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
10805 i++) {
10806 disable_cmd =
10807 _syn_offset_one_disable_cmd[i];
10808 if (disable_cmd == 0xFF) {
10809 break;
10810 }
10811 if (scsi_cmd == disable_cmd) {
10812 disable_syn_offset_one_fix =
10813 TRUE;
10814 break;
10815 }
10816 }
10817 }
10818 }
10819 }
10820 if (disable_syn_offset_one_fix) {
10821 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10822 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
10823 ASC_TAG_FLAG_DISABLE_DISCONNECT);
10824 } else {
10825 scsiq->q2.tag_code &= 0x27;
10826 }
10827 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10828 if (asc_dvc->bug_fix_cntl) {
10829 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10830 if ((scsi_cmd == READ_6) ||
10831 (scsi_cmd == READ_10)) {
10832 addr =
10833 (ADV_PADDR)le32_to_cpu(sg_head->
10834 sg_list
10835 [sg_entry_cnt_minus_one].
10836 addr) +
10837 (ADV_DCNT)le32_to_cpu(sg_head->
10838 sg_list
10839 [sg_entry_cnt_minus_one].
10840 bytes);
10841 extra_bytes =
10842 (uchar)((ushort)addr & 0x0003);
10843 if ((extra_bytes != 0)
10844 &&
10845 ((scsiq->q2.
10846 tag_code &
10847 ASC_TAG_FLAG_EXTRA_BYTES)
10848 == 0)) {
10849 scsiq->q2.tag_code |=
10850 ASC_TAG_FLAG_EXTRA_BYTES;
10851 scsiq->q1.extra_bytes =
10852 extra_bytes;
10853 data_cnt =
10854 le32_to_cpu(sg_head->
10855 sg_list
10856 [sg_entry_cnt_minus_one].
10857 bytes);
10858 data_cnt -=
10859 (ASC_DCNT) extra_bytes;
10860 sg_head->
10861 sg_list
10862 [sg_entry_cnt_minus_one].
10863 bytes =
10864 cpu_to_le32(data_cnt);
10865 }
10866 }
10867 }
10868 }
10869 sg_head->entry_to_copy = sg_head->entry_cnt;
10870#if CC_VERY_LONG_SG_LIST
10871 /*
10872 * Set the sg_entry_cnt to the maximum possible. The rest of
10873 * the SG elements will be copied when the RISC completes the
10874 * SG elements that fit and halts.
10875 */
10876 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10877 sg_entry_cnt = ASC_MAX_SG_LIST;
10878 }
10879#endif /* CC_VERY_LONG_SG_LIST */
10880 n_q_required = AscSgListToQueue(sg_entry_cnt);
10881 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
10882 (uint) n_q_required)
10883 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
10884 if ((sta =
10885 AscSendScsiQueue(asc_dvc, scsiq,
10886 n_q_required)) == 1) {
10887 asc_dvc->in_critical_cnt--;
10888 return (sta);
10889 }
10890 }
10891 } else {
10892 if (asc_dvc->bug_fix_cntl) {
10893 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10894 if ((scsi_cmd == READ_6) ||
10895 (scsi_cmd == READ_10)) {
10896 addr =
10897 le32_to_cpu(scsiq->q1.data_addr) +
10898 le32_to_cpu(scsiq->q1.data_cnt);
10899 extra_bytes =
10900 (uchar)((ushort)addr & 0x0003);
10901 if ((extra_bytes != 0)
10902 &&
10903 ((scsiq->q2.
10904 tag_code &
10905 ASC_TAG_FLAG_EXTRA_BYTES)
10906 == 0)) {
10907 data_cnt =
10908 le32_to_cpu(scsiq->q1.
10909 data_cnt);
10910 if (((ushort)data_cnt & 0x01FF)
10911 == 0) {
10912 scsiq->q2.tag_code |=
10913 ASC_TAG_FLAG_EXTRA_BYTES;
10914 data_cnt -= (ASC_DCNT)
10915 extra_bytes;
10916 scsiq->q1.data_cnt =
10917 cpu_to_le32
10918 (data_cnt);
10919 scsiq->q1.extra_bytes =
10920 extra_bytes;
10921 }
10922 }
10923 }
10924 }
10925 }
10926 n_q_required = 1;
10927 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
10928 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
10929 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
10930 n_q_required)) == 1) {
10931 asc_dvc->in_critical_cnt--;
10932 return (sta);
10933 }
10934 }
10935 }
10936 asc_dvc->in_critical_cnt--;
10937 return (sta);
10938}
10939
10940/*
10941 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
10942 *
10943 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
10944 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
10945 * RISC to notify it a new command is ready to be executed.
10946 *
10947 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
10948 * set to SCSI_MAX_RETRY.
10949 *
10950 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
10951 * for DMA addresses or math operations are byte swapped to little-endian
10952 * order.
10953 *
10954 * Return:
10955 * ADV_SUCCESS(1) - The request was successfully queued.
10956 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
10957 * request completes.
10958 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
10959 * host IC error.
10960 */
10961static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
10962{
10963 AdvPortAddr iop_base;
10964 ADV_DCNT req_size;
10965 ADV_PADDR req_paddr;
10966 ADV_CARR_T *new_carrp;
10967
10968 /*
10969 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
10970 */
10971 if (scsiq->target_id > ADV_MAX_TID) {
10972 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
10973 scsiq->done_status = QD_WITH_ERROR;
10974 return ADV_ERROR;
10975 }
10976
10977 iop_base = asc_dvc->iop_base;
10978
10979 /*
10980 * Allocate a carrier ensuring at least one carrier always
10981 * remains on the freelist and initialize fields.
10982 */
10983 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
10984 return ADV_BUSY;
10985 }
10986 asc_dvc->carr_freelist = (ADV_CARR_T *)
10987 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
10988 asc_dvc->carr_pending_cnt++;
10989
10990 /*
10991 * Set the carrier to be a stopper by setting 'next_vpa'
10992 * to the stopper value. The current stopper will be changed
10993 * below to point to the new stopper.
10994 */
10995 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
10996
10997 /*
10998 * Clear the ADV_SCSI_REQ_Q done flag.
10999 */
11000 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
11001
11002 req_size = sizeof(ADV_SCSI_REQ_Q);
11003 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
11004 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
11005
11006 BUG_ON(req_paddr & 31);
11007 BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q));
11008
11009 /* Wait for assertion before making little-endian */
11010 req_paddr = cpu_to_le32(req_paddr);
11011
11012 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
11013 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
11014 scsiq->scsiq_rptr = req_paddr;
11015
11016 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
11017 /*
11018 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
11019 * order during initialization.
11020 */
11021 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
11022
11023 /*
11024 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
11025 * the microcode. The newly allocated stopper will become the new
11026 * stopper.
11027 */
11028 asc_dvc->icq_sp->areq_vpa = req_paddr;
11029
11030 /*
11031 * Set the 'next_vpa' pointer for the old stopper to be the
11032 * physical address of the new stopper. The RISC can only
11033 * follow physical addresses.
11034 */
11035 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
11036
11037 /*
11038 * Set the host adapter stopper pointer to point to the new carrier.
11039 */
11040 asc_dvc->icq_sp = new_carrp;
11041
11042 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
11043 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
11044 /*
11045 * Tickle the RISC to tell it to read its Command Queue Head pointer.
11046 */
11047 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
11048 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
11049 /*
11050 * Clear the tickle value. In the ASC-3550 the RISC flag
11051 * command 'clr_tickle_a' does not work unless the host
11052 * value is cleared.
11053 */
11054 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
11055 ADV_TICKLE_NOP);
11056 }
11057 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
11058 /*
11059 * Notify the RISC a carrier is ready by writing the physical
11060 * address of the new carrier stopper to the COMMA register.
11061 */
11062 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
11063 le32_to_cpu(new_carrp->carr_pa));
11064 }
11065
11066 return ADV_SUCCESS;
11067}
11068
11069/*
11070 * Execute a single 'Scsi_Cmnd'.
11071 *
11072 * The function 'done' is called when the request has been completed.
11073 *
11074 * Scsi_Cmnd:
11075 *
11076 * host - board controlling device
11077 * device - device to send command
11078 * target - target of device
11079 * lun - lun of device
11080 * cmd_len - length of SCSI CDB
11081 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
11082 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
11083 *
11084 * if (use_sg == 0) {
11085 * request_buffer - buffer address for request
11086 * request_bufflen - length of request buffer
11087 * } else {
11088 * request_buffer - pointer to scatterlist structure
11089 * }
11090 *
11091 * sense_buffer - sense command buffer
11092 *
11093 * result (4 bytes of an int):
11094 * Byte Meaning
11095 * 0 SCSI Status Byte Code
11096 * 1 SCSI One Byte Message Code
11097 * 2 Host Error Code
11098 * 3 Mid-Level Error Code
11099 *
11100 * host driver fields:
11101 * SCp - Scsi_Pointer used for command processing status
11102 * scsi_done - used to save caller's done function
11103 * host_scribble - used for pointer to another struct scsi_cmnd
11104 *
11105 * If this function returns ASC_NOERROR the request will be completed
11106 * from the interrupt handler.
11107 *
11108 * If this function returns ASC_ERROR the host error code has been set,
11109 * and the called must call asc_scsi_done.
11110 *
11111 * If ASC_BUSY is returned the request will be returned to the midlayer
11112 * and re-tried later.
11113 */
11114static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
11115{
Matthew Wilcox41d24932007-10-02 21:55:24 -040011116 int ret, err_code;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011117 struct asc_board *boardp = shost_priv(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040011118
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011119 ASC_DBG(1, "scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011120
11121 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011122 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox05848b62007-10-02 21:55:25 -040011123 struct asc_scsi_q asc_scsi_q;
Matthew Wilcox51219352007-10-02 21:55:22 -040011124
Matthew Wilcox41d24932007-10-02 21:55:24 -040011125 /* asc_build_req() can not return ASC_BUSY. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040011126 ret = asc_build_req(boardp, scp, &asc_scsi_q);
11127 if (ret == ASC_ERROR) {
Matthew Wilcox51219352007-10-02 21:55:22 -040011128 ASC_STATS(scp->device->host, build_error);
11129 return ASC_ERROR;
11130 }
11131
Matthew Wilcox41d24932007-10-02 21:55:24 -040011132 ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
Matthew Wilcox05848b62007-10-02 21:55:25 -040011133 kfree(asc_scsi_q.sg_head);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011134 err_code = asc_dvc->err_code;
Matthew Wilcox51219352007-10-02 21:55:22 -040011135 } else {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011136 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
11137 ADV_SCSI_REQ_Q *adv_scsiqp;
Matthew Wilcox51219352007-10-02 21:55:22 -040011138
Matthew Wilcox51219352007-10-02 21:55:22 -040011139 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
11140 case ASC_NOERROR:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011141 ASC_DBG(3, "adv_build_req ASC_NOERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011142 break;
11143 case ASC_BUSY:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011144 ASC_DBG(1, "adv_build_req ASC_BUSY\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011145 /*
11146 * The asc_stats fields 'adv_build_noreq' and
11147 * 'adv_build_nosg' count wide board busy conditions.
11148 * They are updated in adv_build_req and
11149 * adv_get_sglist, respectively.
11150 */
11151 return ASC_BUSY;
11152 case ASC_ERROR:
11153 default:
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011154 ASC_DBG(1, "adv_build_req ASC_ERROR\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011155 ASC_STATS(scp->device->host, build_error);
11156 return ASC_ERROR;
11157 }
11158
Matthew Wilcox41d24932007-10-02 21:55:24 -040011159 ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp);
11160 err_code = adv_dvc->err_code;
11161 }
11162
11163 switch (ret) {
11164 case ASC_NOERROR:
11165 ASC_STATS(scp->device->host, exe_noerror);
11166 /*
11167 * Increment monotonically increasing per device
11168 * successful request counter. Wrapping doesn't matter.
11169 */
11170 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011171 ASC_DBG(1, "ExeScsiQueue() ASC_NOERROR\n");
Matthew Wilcox41d24932007-10-02 21:55:24 -040011172 break;
11173 case ASC_BUSY:
11174 ASC_STATS(scp->device->host, exe_busy);
11175 break;
11176 case ASC_ERROR:
11177 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11178 "ASC_ERROR, err_code 0x%x\n", boardp->id, err_code);
11179 ASC_STATS(scp->device->host, exe_error);
11180 scp->result = HOST_BYTE(DID_ERROR);
11181 break;
11182 default:
11183 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11184 "unknown, err_code 0x%x\n", boardp->id, err_code);
11185 ASC_STATS(scp->device->host, exe_unknown);
11186 scp->result = HOST_BYTE(DID_ERROR);
11187 break;
Matthew Wilcox51219352007-10-02 21:55:22 -040011188 }
11189
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011190 ASC_DBG(1, "end\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011191 return ret;
11192}
11193
11194/*
11195 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
11196 *
11197 * This function always returns 0. Command return status is saved
11198 * in the 'scp' result field.
11199 */
11200static int
11201advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
11202{
11203 struct Scsi_Host *shost = scp->device->host;
Matthew Wilcox51219352007-10-02 21:55:22 -040011204 int asc_res, result = 0;
11205
11206 ASC_STATS(shost, queuecommand);
11207 scp->scsi_done = done;
11208
Matthew Wilcox51219352007-10-02 21:55:22 -040011209 asc_res = asc_execute_scsi_cmnd(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011210
11211 switch (asc_res) {
11212 case ASC_NOERROR:
11213 break;
11214 case ASC_BUSY:
11215 result = SCSI_MLQUEUE_HOST_BUSY;
11216 break;
11217 case ASC_ERROR:
11218 default:
11219 asc_scsi_done(scp);
11220 break;
11221 }
11222
11223 return result;
11224}
11225
11226static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
11227{
11228 PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11229 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
11230 return inpw(eisa_cfg_iop);
11231}
11232
11233/*
11234 * Return the BIOS address of the adapter at the specified
11235 * I/O port and with the specified bus type.
11236 */
11237static unsigned short __devinit
11238AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
11239{
11240 unsigned short cfg_lsw;
11241 unsigned short bios_addr;
11242
11243 /*
11244 * The PCI BIOS is re-located by the motherboard BIOS. Because
11245 * of this the driver can not determine where a PCI BIOS is
11246 * loaded and executes.
11247 */
11248 if (bus_type & ASC_IS_PCI)
11249 return 0;
11250
11251 if ((bus_type & ASC_IS_EISA) != 0) {
11252 cfg_lsw = AscGetEisaChipCfg(iop_base);
11253 cfg_lsw &= 0x000F;
11254 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
11255 return bios_addr;
11256 }
11257
11258 cfg_lsw = AscGetChipCfgLsw(iop_base);
11259
11260 /*
11261 * ISA PnP uses the top bit as the 32K BIOS flag
11262 */
11263 if (bus_type == ASC_IS_ISAPNP)
11264 cfg_lsw &= 0x7FFF;
11265 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
11266 return bios_addr;
11267}
11268
11269static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
11270{
11271 ushort cfg_lsw;
11272
11273 if (AscGetChipScsiID(iop_base) == new_host_id) {
11274 return (new_host_id);
11275 }
11276 cfg_lsw = AscGetChipCfgLsw(iop_base);
11277 cfg_lsw &= 0xF8FF;
11278 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
11279 AscSetChipCfgLsw(iop_base, cfg_lsw);
11280 return (AscGetChipScsiID(iop_base));
11281}
11282
11283static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
11284{
11285 unsigned char sc;
11286
11287 AscSetBank(iop_base, 1);
11288 sc = inp(iop_base + IOP_REG_SC);
11289 AscSetBank(iop_base, 0);
11290 return sc;
11291}
11292
11293static unsigned char __devinit
11294AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
11295{
11296 if (bus_type & ASC_IS_EISA) {
11297 PortAddr eisa_iop;
11298 unsigned char revision;
11299 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11300 (PortAddr) ASC_EISA_REV_IOP_MASK;
11301 revision = inp(eisa_iop);
11302 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
11303 }
11304 return AscGetChipVerNo(iop_base);
11305}
11306
Matthew Wilcox51219352007-10-02 21:55:22 -040011307#ifdef CONFIG_ISA
11308static void __devinit AscEnableIsaDma(uchar dma_channel)
11309{
11310 if (dma_channel < 4) {
11311 outp(0x000B, (ushort)(0xC0 | dma_channel));
11312 outp(0x000A, dma_channel);
11313 } else if (dma_channel < 8) {
11314 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
11315 outp(0x00D4, (ushort)(dma_channel - 4));
11316 }
11317 return;
11318}
11319#endif /* CONFIG_ISA */
11320
11321static int AscStopQueueExe(PortAddr iop_base)
11322{
11323 int count = 0;
11324
11325 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
11326 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
11327 ASC_STOP_REQ_RISC_STOP);
11328 do {
11329 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
11330 ASC_STOP_ACK_RISC_STOP) {
11331 return (1);
11332 }
11333 mdelay(100);
11334 } while (count++ < 20);
11335 }
11336 return (0);
11337}
11338
11339static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
11340{
11341 if (bus_type & ASC_IS_ISA)
11342 return ASC_MAX_ISA_DMA_COUNT;
11343 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
11344 return ASC_MAX_VL_DMA_COUNT;
11345 return ASC_MAX_PCI_DMA_COUNT;
11346}
11347
11348#ifdef CONFIG_ISA
11349static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
11350{
11351 ushort channel;
11352
11353 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
11354 if (channel == 0x03)
11355 return (0);
11356 else if (channel == 0x00)
11357 return (7);
11358 return (channel + 4);
11359}
11360
11361static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
11362{
11363 ushort cfg_lsw;
11364 uchar value;
11365
11366 if ((dma_channel >= 5) && (dma_channel <= 7)) {
11367 if (dma_channel == 7)
11368 value = 0x00;
11369 else
11370 value = dma_channel - 4;
11371 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
11372 cfg_lsw |= value;
11373 AscSetChipCfgLsw(iop_base, cfg_lsw);
11374 return (AscGetIsaDmaChannel(iop_base));
11375 }
11376 return 0;
11377}
11378
11379static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
11380{
11381 uchar speed_value;
11382
11383 AscSetBank(iop_base, 1);
11384 speed_value = AscReadChipDmaSpeed(iop_base);
11385 speed_value &= 0x07;
11386 AscSetBank(iop_base, 0);
11387 return speed_value;
11388}
11389
11390static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
11391{
11392 speed_value &= 0x07;
11393 AscSetBank(iop_base, 1);
11394 AscWriteChipDmaSpeed(iop_base, speed_value);
11395 AscSetBank(iop_base, 0);
11396 return AscGetIsaDmaSpeed(iop_base);
11397}
11398#endif /* CONFIG_ISA */
11399
11400static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
11401{
11402 int i;
11403 PortAddr iop_base;
11404 ushort warn_code;
11405 uchar chip_version;
11406
11407 iop_base = asc_dvc->iop_base;
11408 warn_code = 0;
11409 asc_dvc->err_code = 0;
11410 if ((asc_dvc->bus_type &
11411 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
11412 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
11413 }
11414 AscSetChipControl(iop_base, CC_HALT);
11415 AscSetChipStatus(iop_base, 0);
11416 asc_dvc->bug_fix_cntl = 0;
11417 asc_dvc->pci_fix_asyn_xfer = 0;
11418 asc_dvc->pci_fix_asyn_xfer_always = 0;
11419 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
11420 asc_dvc->sdtr_done = 0;
11421 asc_dvc->cur_total_qng = 0;
11422 asc_dvc->is_in_int = 0;
11423 asc_dvc->in_critical_cnt = 0;
11424 asc_dvc->last_q_shortage = 0;
11425 asc_dvc->use_tagged_qng = 0;
11426 asc_dvc->no_scam = 0;
11427 asc_dvc->unit_not_ready = 0;
11428 asc_dvc->queue_full_or_busy = 0;
11429 asc_dvc->redo_scam = 0;
11430 asc_dvc->res2 = 0;
11431 asc_dvc->host_init_sdtr_index = 0;
11432 asc_dvc->cfg->can_tagged_qng = 0;
11433 asc_dvc->cfg->cmd_qng_enabled = 0;
11434 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
11435 asc_dvc->init_sdtr = 0;
11436 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
11437 asc_dvc->scsi_reset_wait = 3;
11438 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
11439 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
11440 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
11441 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
11442 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
Matthew Wilcox51219352007-10-02 21:55:22 -040011443 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
11444 asc_dvc->cfg->chip_version = chip_version;
11445 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
11446 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
11447 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
11448 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
11449 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
11450 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
11451 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
11452 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
11453 asc_dvc->max_sdtr_index = 7;
11454 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
11455 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
11456 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
11457 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
11458 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
11459 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
11460 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
11461 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
11462 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
11463 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
11464 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
11465 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
11466 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
11467 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
11468 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
11469 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
11470 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
11471 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
11472 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
11473 asc_dvc->max_sdtr_index = 15;
11474 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
11475 AscSetExtraControl(iop_base,
11476 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11477 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
11478 AscSetExtraControl(iop_base,
11479 (SEC_ACTIVE_NEGATE |
11480 SEC_ENABLE_FILTER));
11481 }
11482 }
11483 if (asc_dvc->bus_type == ASC_IS_PCI) {
11484 AscSetExtraControl(iop_base,
11485 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11486 }
11487
11488 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
11489#ifdef CONFIG_ISA
11490 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
11491 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
11492 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
11493 asc_dvc->bus_type = ASC_IS_ISAPNP;
11494 }
11495 asc_dvc->cfg->isa_dma_channel =
11496 (uchar)AscGetIsaDmaChannel(iop_base);
11497 }
11498#endif /* CONFIG_ISA */
11499 for (i = 0; i <= ASC_MAX_TID; i++) {
11500 asc_dvc->cur_dvc_qng[i] = 0;
11501 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
11502 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
11503 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
11504 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
11505 }
11506 return warn_code;
11507}
11508
11509static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
11510{
11511 int retry;
11512
11513 for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) {
11514 unsigned char read_back;
11515 AscSetChipEEPCmd(iop_base, cmd_reg);
11516 mdelay(1);
11517 read_back = AscGetChipEEPCmd(iop_base);
11518 if (read_back == cmd_reg)
11519 return 1;
11520 }
11521 return 0;
11522}
11523
11524static void __devinit AscWaitEEPRead(void)
11525{
11526 mdelay(1);
11527}
11528
11529static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
11530{
11531 ushort read_wval;
11532 uchar cmd_reg;
11533
11534 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11535 AscWaitEEPRead();
11536 cmd_reg = addr | ASC_EEP_CMD_READ;
11537 AscWriteEEPCmdReg(iop_base, cmd_reg);
11538 AscWaitEEPRead();
11539 read_wval = AscGetChipEEPData(iop_base);
11540 AscWaitEEPRead();
11541 return read_wval;
11542}
11543
11544static ushort __devinit
11545AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11546{
11547 ushort wval;
11548 ushort sum;
11549 ushort *wbuf;
11550 int cfg_beg;
11551 int cfg_end;
11552 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11553 int s_addr;
11554
11555 wbuf = (ushort *)cfg_buf;
11556 sum = 0;
11557 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
11558 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11559 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11560 sum += *wbuf;
11561 }
11562 if (bus_type & ASC_IS_VL) {
11563 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11564 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11565 } else {
11566 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11567 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11568 }
11569 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11570 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11571 if (s_addr <= uchar_end_in_config) {
11572 /*
11573 * Swap all char fields - must unswap bytes already swapped
11574 * by AscReadEEPWord().
11575 */
11576 *wbuf = le16_to_cpu(wval);
11577 } else {
11578 /* Don't swap word field at the end - cntl field. */
11579 *wbuf = wval;
11580 }
11581 sum += wval; /* Checksum treats all EEPROM data as words. */
11582 }
11583 /*
11584 * Read the checksum word which will be compared against 'sum'
11585 * by the caller. Word field already swapped.
11586 */
11587 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11588 return sum;
11589}
11590
11591static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
11592{
11593 PortAddr iop_base;
11594 ushort q_addr;
11595 ushort saved_word;
11596 int sta;
11597
11598 iop_base = asc_dvc->iop_base;
11599 sta = 0;
11600 q_addr = ASC_QNO_TO_QADDR(241);
11601 saved_word = AscReadLramWord(iop_base, q_addr);
11602 AscSetChipLramAddr(iop_base, q_addr);
11603 AscSetChipLramData(iop_base, 0x55AA);
11604 mdelay(10);
11605 AscSetChipLramAddr(iop_base, q_addr);
11606 if (AscGetChipLramData(iop_base) == 0x55AA) {
11607 sta = 1;
11608 AscWriteLramWord(iop_base, q_addr, saved_word);
11609 }
11610 return (sta);
11611}
11612
11613static void __devinit AscWaitEEPWrite(void)
11614{
11615 mdelay(20);
11616 return;
11617}
11618
11619static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
11620{
11621 ushort read_back;
11622 int retry;
11623
11624 retry = 0;
11625 while (TRUE) {
11626 AscSetChipEEPData(iop_base, data_reg);
11627 mdelay(1);
11628 read_back = AscGetChipEEPData(iop_base);
11629 if (read_back == data_reg) {
11630 return (1);
11631 }
11632 if (retry++ > ASC_EEP_MAX_RETRY) {
11633 return (0);
11634 }
11635 }
11636}
11637
11638static ushort __devinit
11639AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
11640{
11641 ushort read_wval;
11642
11643 read_wval = AscReadEEPWord(iop_base, addr);
11644 if (read_wval != word_val) {
11645 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
11646 AscWaitEEPRead();
11647 AscWriteEEPDataReg(iop_base, word_val);
11648 AscWaitEEPRead();
11649 AscWriteEEPCmdReg(iop_base,
11650 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
11651 AscWaitEEPWrite();
11652 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11653 AscWaitEEPRead();
11654 return (AscReadEEPWord(iop_base, addr));
11655 }
11656 return (read_wval);
11657}
11658
11659static int __devinit
11660AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11661{
11662 int n_error;
11663 ushort *wbuf;
11664 ushort word;
11665 ushort sum;
11666 int s_addr;
11667 int cfg_beg;
11668 int cfg_end;
11669 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11670
11671 wbuf = (ushort *)cfg_buf;
11672 n_error = 0;
11673 sum = 0;
11674 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11675 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11676 sum += *wbuf;
11677 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11678 n_error++;
11679 }
11680 }
11681 if (bus_type & ASC_IS_VL) {
11682 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11683 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11684 } else {
11685 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11686 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11687 }
11688 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11689 if (s_addr <= uchar_end_in_config) {
11690 /*
11691 * This is a char field. Swap char fields before they are
11692 * swapped again by AscWriteEEPWord().
11693 */
11694 word = cpu_to_le16(*wbuf);
11695 if (word !=
11696 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11697 n_error++;
11698 }
11699 } else {
11700 /* Don't swap word field at the end - cntl field. */
11701 if (*wbuf !=
11702 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11703 n_error++;
11704 }
11705 }
11706 sum += *wbuf; /* Checksum calculated from word values. */
11707 }
11708 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11709 *wbuf = sum;
11710 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11711 n_error++;
11712 }
11713
11714 /* Read EEPROM back again. */
11715 wbuf = (ushort *)cfg_buf;
11716 /*
11717 * Read two config words; Byte-swapping done by AscReadEEPWord().
11718 */
11719 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11720 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11721 n_error++;
11722 }
11723 }
11724 if (bus_type & ASC_IS_VL) {
11725 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11726 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11727 } else {
11728 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11729 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11730 }
11731 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11732 if (s_addr <= uchar_end_in_config) {
11733 /*
11734 * Swap all char fields. Must unswap bytes already swapped
11735 * by AscReadEEPWord().
11736 */
11737 word =
11738 le16_to_cpu(AscReadEEPWord
11739 (iop_base, (uchar)s_addr));
11740 } else {
11741 /* Don't swap word field at the end - cntl field. */
11742 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11743 }
11744 if (*wbuf != word) {
11745 n_error++;
11746 }
11747 }
11748 /* Read checksum; Byte swapping not needed. */
11749 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11750 n_error++;
11751 }
11752 return n_error;
11753}
11754
11755static int __devinit
11756AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11757{
11758 int retry;
11759 int n_error;
11760
11761 retry = 0;
11762 while (TRUE) {
11763 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
11764 bus_type)) == 0) {
11765 break;
11766 }
11767 if (++retry > ASC_EEP_MAX_RETRY) {
11768 break;
11769 }
11770 }
11771 return n_error;
11772}
11773
11774static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
11775{
11776 ASCEEP_CONFIG eep_config_buf;
11777 ASCEEP_CONFIG *eep_config;
11778 PortAddr iop_base;
11779 ushort chksum;
11780 ushort warn_code;
11781 ushort cfg_msw, cfg_lsw;
11782 int i;
11783 int write_eep = 0;
11784
11785 iop_base = asc_dvc->iop_base;
11786 warn_code = 0;
11787 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
11788 AscStopQueueExe(iop_base);
11789 if ((AscStopChip(iop_base) == FALSE) ||
11790 (AscGetChipScsiCtrl(iop_base) != 0)) {
11791 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
11792 AscResetChipAndScsiBus(asc_dvc);
11793 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
11794 }
11795 if (AscIsChipHalted(iop_base) == FALSE) {
11796 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
11797 return (warn_code);
11798 }
11799 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11800 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11801 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
11802 return (warn_code);
11803 }
11804 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
11805 cfg_msw = AscGetChipCfgMsw(iop_base);
11806 cfg_lsw = AscGetChipCfgLsw(iop_base);
11807 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
11808 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11809 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
11810 AscSetChipCfgMsw(iop_base, cfg_msw);
11811 }
11812 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011813 ASC_DBG(1, "chksum 0x%x\n", chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -040011814 if (chksum == 0) {
11815 chksum = 0xaa55;
11816 }
11817 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
11818 warn_code |= ASC_WARN_AUTO_CONFIG;
11819 if (asc_dvc->cfg->chip_version == 3) {
11820 if (eep_config->cfg_lsw != cfg_lsw) {
11821 warn_code |= ASC_WARN_EEPROM_RECOVER;
11822 eep_config->cfg_lsw =
11823 AscGetChipCfgLsw(iop_base);
11824 }
11825 if (eep_config->cfg_msw != cfg_msw) {
11826 warn_code |= ASC_WARN_EEPROM_RECOVER;
11827 eep_config->cfg_msw =
11828 AscGetChipCfgMsw(iop_base);
11829 }
11830 }
11831 }
11832 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11833 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011834 ASC_DBG(1, "eep_config->chksum 0x%x\n", eep_config->chksum);
Matthew Wilcox51219352007-10-02 21:55:22 -040011835 if (chksum != eep_config->chksum) {
11836 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
11837 ASC_CHIP_VER_PCI_ULTRA_3050) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040011838 ASC_DBG(1, "chksum error ignored; EEPROM-less board\n");
Matthew Wilcox51219352007-10-02 21:55:22 -040011839 eep_config->init_sdtr = 0xFF;
11840 eep_config->disc_enable = 0xFF;
11841 eep_config->start_motor = 0xFF;
11842 eep_config->use_cmd_qng = 0;
11843 eep_config->max_total_qng = 0xF0;
11844 eep_config->max_tag_qng = 0x20;
11845 eep_config->cntl = 0xBFFF;
11846 ASC_EEP_SET_CHIP_ID(eep_config, 7);
11847 eep_config->no_scam = 0;
11848 eep_config->adapter_info[0] = 0;
11849 eep_config->adapter_info[1] = 0;
11850 eep_config->adapter_info[2] = 0;
11851 eep_config->adapter_info[3] = 0;
11852 eep_config->adapter_info[4] = 0;
11853 /* Indicate EEPROM-less board. */
11854 eep_config->adapter_info[5] = 0xBB;
11855 } else {
11856 ASC_PRINT
11857 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
11858 write_eep = 1;
11859 warn_code |= ASC_WARN_EEPROM_CHKSUM;
11860 }
11861 }
11862 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
11863 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
11864 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
11865 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
11866 asc_dvc->start_motor = eep_config->start_motor;
11867 asc_dvc->dvc_cntl = eep_config->cntl;
11868 asc_dvc->no_scam = eep_config->no_scam;
11869 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
11870 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
11871 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
11872 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
11873 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
11874 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
11875 if (!AscTestExternalLram(asc_dvc)) {
11876 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
11877 ASC_IS_PCI_ULTRA)) {
11878 eep_config->max_total_qng =
11879 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
11880 eep_config->max_tag_qng =
11881 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
11882 } else {
11883 eep_config->cfg_msw |= 0x0800;
11884 cfg_msw |= 0x0800;
11885 AscSetChipCfgMsw(iop_base, cfg_msw);
11886 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
11887 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
11888 }
11889 } else {
11890 }
11891 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
11892 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
11893 }
11894 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
11895 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
11896 }
11897 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
11898 eep_config->max_tag_qng = eep_config->max_total_qng;
11899 }
11900 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
11901 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
11902 }
11903 asc_dvc->max_total_qng = eep_config->max_total_qng;
11904 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
11905 eep_config->use_cmd_qng) {
11906 eep_config->disc_enable = eep_config->use_cmd_qng;
11907 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
11908 }
Matthew Wilcox51219352007-10-02 21:55:22 -040011909 ASC_EEP_SET_CHIP_ID(eep_config,
11910 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
11911 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
11912 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
11913 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
11914 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
11915 }
11916
11917 for (i = 0; i <= ASC_MAX_TID; i++) {
11918 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
11919 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
11920 asc_dvc->cfg->sdtr_period_offset[i] =
11921 (uchar)(ASC_DEF_SDTR_OFFSET |
11922 (asc_dvc->host_init_sdtr_index << 4));
11923 }
11924 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
11925 if (write_eep) {
11926 if ((i = AscSetEEPConfig(iop_base, eep_config,
11927 asc_dvc->bus_type)) != 0) {
11928 ASC_PRINT1
11929 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
11930 i);
11931 } else {
11932 ASC_PRINT
11933 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
11934 }
11935 }
11936 return (warn_code);
11937}
11938
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011939static int __devinit AscInitGetConfig(struct asc_board *boardp)
Matthew Wilcox51219352007-10-02 21:55:22 -040011940{
11941 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
11942 unsigned short warn_code = 0;
11943
11944 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
11945 if (asc_dvc->err_code != 0)
11946 return asc_dvc->err_code;
11947
11948 if (AscFindSignature(asc_dvc->iop_base)) {
11949 warn_code |= AscInitAscDvcVar(asc_dvc);
11950 warn_code |= AscInitFromEEP(asc_dvc);
11951 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
11952 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
11953 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
11954 } else {
11955 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11956 }
11957
11958 switch (warn_code) {
11959 case 0: /* No error */
11960 break;
11961 case ASC_WARN_IO_PORT_ROTATE:
11962 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
11963 "modified\n", boardp->id);
11964 break;
11965 case ASC_WARN_AUTO_CONFIG:
11966 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
11967 "switch enabled\n", boardp->id);
11968 break;
11969 case ASC_WARN_EEPROM_CHKSUM:
11970 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
11971 "error\n", boardp->id);
11972 break;
11973 case ASC_WARN_IRQ_MODIFIED:
11974 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
11975 boardp->id);
11976 break;
11977 case ASC_WARN_CMD_QNG_CONFLICT:
11978 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
11979 "w/o disconnects\n", boardp->id);
11980 break;
11981 default:
11982 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
11983 "0x%x\n", boardp->id, warn_code);
11984 break;
11985 }
11986
11987 if (asc_dvc->err_code != 0) {
11988 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
11989 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
11990 asc_dvc->err_code);
11991 }
11992
11993 return asc_dvc->err_code;
11994}
11995
Matthew Wilcoxd2411492007-10-02 21:55:31 -040011996static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct asc_board *boardp)
Matthew Wilcox51219352007-10-02 21:55:22 -040011997{
11998 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
11999 PortAddr iop_base = asc_dvc->iop_base;
12000 unsigned short cfg_msw;
12001 unsigned short warn_code = 0;
12002
12003 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12004 if (asc_dvc->err_code != 0)
12005 return asc_dvc->err_code;
12006 if (!AscFindSignature(asc_dvc->iop_base)) {
12007 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12008 return asc_dvc->err_code;
12009 }
12010
12011 cfg_msw = AscGetChipCfgMsw(iop_base);
12012 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12013 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
12014 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12015 AscSetChipCfgMsw(iop_base, cfg_msw);
12016 }
12017 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12018 asc_dvc->cfg->cmd_qng_enabled) {
12019 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12020 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12021 }
12022 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12023 warn_code |= ASC_WARN_AUTO_CONFIG;
12024 }
Matthew Wilcox51219352007-10-02 21:55:22 -040012025#ifdef CONFIG_PCI
12026 if (asc_dvc->bus_type & ASC_IS_PCI) {
12027 cfg_msw &= 0xFFC0;
12028 AscSetChipCfgMsw(iop_base, cfg_msw);
12029 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12030 } else {
12031 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
12032 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
12033 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12034 asc_dvc->bug_fix_cntl |=
12035 ASC_BUG_FIX_ASYN_USE_SYN;
12036 }
12037 }
12038 } else
12039#endif /* CONFIG_PCI */
12040 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12041 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12042 == ASC_CHIP_VER_ASYN_BUG) {
12043 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12044 }
12045 }
12046 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12047 asc_dvc->cfg->chip_scsi_id) {
12048 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12049 }
12050#ifdef CONFIG_ISA
12051 if (asc_dvc->bus_type & ASC_IS_ISA) {
12052 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12053 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12054 }
12055#endif /* CONFIG_ISA */
12056
12057 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12058
12059 switch (warn_code) {
12060 case 0: /* No error. */
12061 break;
12062 case ASC_WARN_IO_PORT_ROTATE:
12063 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
12064 "modified\n", boardp->id);
12065 break;
12066 case ASC_WARN_AUTO_CONFIG:
12067 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
12068 "switch enabled\n", boardp->id);
12069 break;
12070 case ASC_WARN_EEPROM_CHKSUM:
12071 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
12072 "error\n", boardp->id);
12073 break;
12074 case ASC_WARN_IRQ_MODIFIED:
12075 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
12076 boardp->id);
12077 break;
12078 case ASC_WARN_CMD_QNG_CONFLICT:
12079 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
12080 "disconnects\n",
12081 boardp->id);
12082 break;
12083 default:
12084 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
12085 "0x%x\n", boardp->id, warn_code);
12086 break;
12087 }
12088
12089 if (asc_dvc->err_code != 0) {
12090 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
12091 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12092 asc_dvc->err_code);
12093 }
12094
12095 return asc_dvc->err_code;
12096}
12097
12098/*
12099 * EEPROM Configuration.
12100 *
12101 * All drivers should use this structure to set the default EEPROM
12102 * configuration. The BIOS now uses this structure when it is built.
12103 * Additional structure information can be found in a_condor.h where
12104 * the structure is defined.
12105 *
12106 * The *_Field_IsChar structs are needed to correct for endianness.
12107 * These values are read from the board 16 bits at a time directly
12108 * into the structs. Because some fields are char, the values will be
12109 * in the wrong order. The *_Field_IsChar tells when to flip the
12110 * bytes. Data read and written to PCI memory is automatically swapped
12111 * on big-endian platforms so char fields read as words are actually being
12112 * unswapped on big-endian platforms.
12113 */
12114static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
12115 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
12116 0x0000, /* cfg_msw */
12117 0xFFFF, /* disc_enable */
12118 0xFFFF, /* wdtr_able */
12119 0xFFFF, /* sdtr_able */
12120 0xFFFF, /* start_motor */
12121 0xFFFF, /* tagqng_able */
12122 0xFFFF, /* bios_scan */
12123 0, /* scam_tolerant */
12124 7, /* adapter_scsi_id */
12125 0, /* bios_boot_delay */
12126 3, /* scsi_reset_delay */
12127 0, /* bios_id_lun */
12128 0, /* termination */
12129 0, /* reserved1 */
12130 0xFFE7, /* bios_ctrl */
12131 0xFFFF, /* ultra_able */
12132 0, /* reserved2 */
12133 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
12134 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12135 0, /* dvc_cntl */
12136 0, /* bug_fix */
12137 0, /* serial_number_word1 */
12138 0, /* serial_number_word2 */
12139 0, /* serial_number_word3 */
12140 0, /* check_sum */
12141 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12142 , /* oem_name[16] */
12143 0, /* dvc_err_code */
12144 0, /* adv_err_code */
12145 0, /* adv_err_addr */
12146 0, /* saved_dvc_err_code */
12147 0, /* saved_adv_err_code */
12148 0, /* saved_adv_err_addr */
12149 0 /* num_of_err */
12150};
12151
12152static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
12153 0, /* cfg_lsw */
12154 0, /* cfg_msw */
12155 0, /* -disc_enable */
12156 0, /* wdtr_able */
12157 0, /* sdtr_able */
12158 0, /* start_motor */
12159 0, /* tagqng_able */
12160 0, /* bios_scan */
12161 0, /* scam_tolerant */
12162 1, /* adapter_scsi_id */
12163 1, /* bios_boot_delay */
12164 1, /* scsi_reset_delay */
12165 1, /* bios_id_lun */
12166 1, /* termination */
12167 1, /* reserved1 */
12168 0, /* bios_ctrl */
12169 0, /* ultra_able */
12170 0, /* reserved2 */
12171 1, /* max_host_qng */
12172 1, /* max_dvc_qng */
12173 0, /* dvc_cntl */
12174 0, /* bug_fix */
12175 0, /* serial_number_word1 */
12176 0, /* serial_number_word2 */
12177 0, /* serial_number_word3 */
12178 0, /* check_sum */
12179 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12180 , /* oem_name[16] */
12181 0, /* dvc_err_code */
12182 0, /* adv_err_code */
12183 0, /* adv_err_addr */
12184 0, /* saved_dvc_err_code */
12185 0, /* saved_adv_err_code */
12186 0, /* saved_adv_err_addr */
12187 0 /* num_of_err */
12188};
12189
12190static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
12191 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12192 0x0000, /* 01 cfg_msw */
12193 0xFFFF, /* 02 disc_enable */
12194 0xFFFF, /* 03 wdtr_able */
12195 0x4444, /* 04 sdtr_speed1 */
12196 0xFFFF, /* 05 start_motor */
12197 0xFFFF, /* 06 tagqng_able */
12198 0xFFFF, /* 07 bios_scan */
12199 0, /* 08 scam_tolerant */
12200 7, /* 09 adapter_scsi_id */
12201 0, /* bios_boot_delay */
12202 3, /* 10 scsi_reset_delay */
12203 0, /* bios_id_lun */
12204 0, /* 11 termination_se */
12205 0, /* termination_lvd */
12206 0xFFE7, /* 12 bios_ctrl */
12207 0x4444, /* 13 sdtr_speed2 */
12208 0x4444, /* 14 sdtr_speed3 */
12209 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12210 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12211 0, /* 16 dvc_cntl */
12212 0x4444, /* 17 sdtr_speed4 */
12213 0, /* 18 serial_number_word1 */
12214 0, /* 19 serial_number_word2 */
12215 0, /* 20 serial_number_word3 */
12216 0, /* 21 check_sum */
12217 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12218 , /* 22-29 oem_name[16] */
12219 0, /* 30 dvc_err_code */
12220 0, /* 31 adv_err_code */
12221 0, /* 32 adv_err_addr */
12222 0, /* 33 saved_dvc_err_code */
12223 0, /* 34 saved_adv_err_code */
12224 0, /* 35 saved_adv_err_addr */
12225 0, /* 36 reserved */
12226 0, /* 37 reserved */
12227 0, /* 38 reserved */
12228 0, /* 39 reserved */
12229 0, /* 40 reserved */
12230 0, /* 41 reserved */
12231 0, /* 42 reserved */
12232 0, /* 43 reserved */
12233 0, /* 44 reserved */
12234 0, /* 45 reserved */
12235 0, /* 46 reserved */
12236 0, /* 47 reserved */
12237 0, /* 48 reserved */
12238 0, /* 49 reserved */
12239 0, /* 50 reserved */
12240 0, /* 51 reserved */
12241 0, /* 52 reserved */
12242 0, /* 53 reserved */
12243 0, /* 54 reserved */
12244 0, /* 55 reserved */
12245 0, /* 56 cisptr_lsw */
12246 0, /* 57 cisprt_msw */
12247 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12248 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
12249 0, /* 60 reserved */
12250 0, /* 61 reserved */
12251 0, /* 62 reserved */
12252 0 /* 63 reserved */
12253};
12254
12255static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
12256 0, /* 00 cfg_lsw */
12257 0, /* 01 cfg_msw */
12258 0, /* 02 disc_enable */
12259 0, /* 03 wdtr_able */
12260 0, /* 04 sdtr_speed1 */
12261 0, /* 05 start_motor */
12262 0, /* 06 tagqng_able */
12263 0, /* 07 bios_scan */
12264 0, /* 08 scam_tolerant */
12265 1, /* 09 adapter_scsi_id */
12266 1, /* bios_boot_delay */
12267 1, /* 10 scsi_reset_delay */
12268 1, /* bios_id_lun */
12269 1, /* 11 termination_se */
12270 1, /* termination_lvd */
12271 0, /* 12 bios_ctrl */
12272 0, /* 13 sdtr_speed2 */
12273 0, /* 14 sdtr_speed3 */
12274 1, /* 15 max_host_qng */
12275 1, /* max_dvc_qng */
12276 0, /* 16 dvc_cntl */
12277 0, /* 17 sdtr_speed4 */
12278 0, /* 18 serial_number_word1 */
12279 0, /* 19 serial_number_word2 */
12280 0, /* 20 serial_number_word3 */
12281 0, /* 21 check_sum */
12282 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12283 , /* 22-29 oem_name[16] */
12284 0, /* 30 dvc_err_code */
12285 0, /* 31 adv_err_code */
12286 0, /* 32 adv_err_addr */
12287 0, /* 33 saved_dvc_err_code */
12288 0, /* 34 saved_adv_err_code */
12289 0, /* 35 saved_adv_err_addr */
12290 0, /* 36 reserved */
12291 0, /* 37 reserved */
12292 0, /* 38 reserved */
12293 0, /* 39 reserved */
12294 0, /* 40 reserved */
12295 0, /* 41 reserved */
12296 0, /* 42 reserved */
12297 0, /* 43 reserved */
12298 0, /* 44 reserved */
12299 0, /* 45 reserved */
12300 0, /* 46 reserved */
12301 0, /* 47 reserved */
12302 0, /* 48 reserved */
12303 0, /* 49 reserved */
12304 0, /* 50 reserved */
12305 0, /* 51 reserved */
12306 0, /* 52 reserved */
12307 0, /* 53 reserved */
12308 0, /* 54 reserved */
12309 0, /* 55 reserved */
12310 0, /* 56 cisptr_lsw */
12311 0, /* 57 cisprt_msw */
12312 0, /* 58 subsysvid */
12313 0, /* 59 subsysid */
12314 0, /* 60 reserved */
12315 0, /* 61 reserved */
12316 0, /* 62 reserved */
12317 0 /* 63 reserved */
12318};
12319
12320static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
12321 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12322 0x0000, /* 01 cfg_msw */
12323 0xFFFF, /* 02 disc_enable */
12324 0xFFFF, /* 03 wdtr_able */
12325 0x5555, /* 04 sdtr_speed1 */
12326 0xFFFF, /* 05 start_motor */
12327 0xFFFF, /* 06 tagqng_able */
12328 0xFFFF, /* 07 bios_scan */
12329 0, /* 08 scam_tolerant */
12330 7, /* 09 adapter_scsi_id */
12331 0, /* bios_boot_delay */
12332 3, /* 10 scsi_reset_delay */
12333 0, /* bios_id_lun */
12334 0, /* 11 termination_se */
12335 0, /* termination_lvd */
12336 0xFFE7, /* 12 bios_ctrl */
12337 0x5555, /* 13 sdtr_speed2 */
12338 0x5555, /* 14 sdtr_speed3 */
12339 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12340 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12341 0, /* 16 dvc_cntl */
12342 0x5555, /* 17 sdtr_speed4 */
12343 0, /* 18 serial_number_word1 */
12344 0, /* 19 serial_number_word2 */
12345 0, /* 20 serial_number_word3 */
12346 0, /* 21 check_sum */
12347 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12348 , /* 22-29 oem_name[16] */
12349 0, /* 30 dvc_err_code */
12350 0, /* 31 adv_err_code */
12351 0, /* 32 adv_err_addr */
12352 0, /* 33 saved_dvc_err_code */
12353 0, /* 34 saved_adv_err_code */
12354 0, /* 35 saved_adv_err_addr */
12355 0, /* 36 reserved */
12356 0, /* 37 reserved */
12357 0, /* 38 reserved */
12358 0, /* 39 reserved */
12359 0, /* 40 reserved */
12360 0, /* 41 reserved */
12361 0, /* 42 reserved */
12362 0, /* 43 reserved */
12363 0, /* 44 reserved */
12364 0, /* 45 reserved */
12365 0, /* 46 reserved */
12366 0, /* 47 reserved */
12367 0, /* 48 reserved */
12368 0, /* 49 reserved */
12369 0, /* 50 reserved */
12370 0, /* 51 reserved */
12371 0, /* 52 reserved */
12372 0, /* 53 reserved */
12373 0, /* 54 reserved */
12374 0, /* 55 reserved */
12375 0, /* 56 cisptr_lsw */
12376 0, /* 57 cisprt_msw */
12377 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12378 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
12379 0, /* 60 reserved */
12380 0, /* 61 reserved */
12381 0, /* 62 reserved */
12382 0 /* 63 reserved */
12383};
12384
12385static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
12386 0, /* 00 cfg_lsw */
12387 0, /* 01 cfg_msw */
12388 0, /* 02 disc_enable */
12389 0, /* 03 wdtr_able */
12390 0, /* 04 sdtr_speed1 */
12391 0, /* 05 start_motor */
12392 0, /* 06 tagqng_able */
12393 0, /* 07 bios_scan */
12394 0, /* 08 scam_tolerant */
12395 1, /* 09 adapter_scsi_id */
12396 1, /* bios_boot_delay */
12397 1, /* 10 scsi_reset_delay */
12398 1, /* bios_id_lun */
12399 1, /* 11 termination_se */
12400 1, /* termination_lvd */
12401 0, /* 12 bios_ctrl */
12402 0, /* 13 sdtr_speed2 */
12403 0, /* 14 sdtr_speed3 */
12404 1, /* 15 max_host_qng */
12405 1, /* max_dvc_qng */
12406 0, /* 16 dvc_cntl */
12407 0, /* 17 sdtr_speed4 */
12408 0, /* 18 serial_number_word1 */
12409 0, /* 19 serial_number_word2 */
12410 0, /* 20 serial_number_word3 */
12411 0, /* 21 check_sum */
12412 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12413 , /* 22-29 oem_name[16] */
12414 0, /* 30 dvc_err_code */
12415 0, /* 31 adv_err_code */
12416 0, /* 32 adv_err_addr */
12417 0, /* 33 saved_dvc_err_code */
12418 0, /* 34 saved_adv_err_code */
12419 0, /* 35 saved_adv_err_addr */
12420 0, /* 36 reserved */
12421 0, /* 37 reserved */
12422 0, /* 38 reserved */
12423 0, /* 39 reserved */
12424 0, /* 40 reserved */
12425 0, /* 41 reserved */
12426 0, /* 42 reserved */
12427 0, /* 43 reserved */
12428 0, /* 44 reserved */
12429 0, /* 45 reserved */
12430 0, /* 46 reserved */
12431 0, /* 47 reserved */
12432 0, /* 48 reserved */
12433 0, /* 49 reserved */
12434 0, /* 50 reserved */
12435 0, /* 51 reserved */
12436 0, /* 52 reserved */
12437 0, /* 53 reserved */
12438 0, /* 54 reserved */
12439 0, /* 55 reserved */
12440 0, /* 56 cisptr_lsw */
12441 0, /* 57 cisprt_msw */
12442 0, /* 58 subsysvid */
12443 0, /* 59 subsysid */
12444 0, /* 60 reserved */
12445 0, /* 61 reserved */
12446 0, /* 62 reserved */
12447 0 /* 63 reserved */
12448};
12449
12450#ifdef CONFIG_PCI
12451/*
12452 * Wait for EEPROM command to complete
12453 */
12454static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
12455{
12456 int eep_delay_ms;
12457
12458 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
12459 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
12460 ASC_EEP_CMD_DONE) {
12461 break;
12462 }
12463 mdelay(1);
12464 }
12465 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
12466 0)
12467 BUG();
12468}
12469
12470/*
12471 * Read the EEPROM from specified location
12472 */
12473static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
12474{
12475 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12476 ASC_EEP_CMD_READ | eep_word_addr);
12477 AdvWaitEEPCmd(iop_base);
12478 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
12479}
12480
12481/*
12482 * Write the EEPROM from 'cfg_buf'.
12483 */
12484void __devinit
12485AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12486{
12487 ushort *wbuf;
12488 ushort addr, chksum;
12489 ushort *charfields;
12490
12491 wbuf = (ushort *)cfg_buf;
12492 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12493 chksum = 0;
12494
12495 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12496 AdvWaitEEPCmd(iop_base);
12497
12498 /*
12499 * Write EEPROM from word 0 to word 20.
12500 */
12501 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12502 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12503 ushort word;
12504
12505 if (*charfields++) {
12506 word = cpu_to_le16(*wbuf);
12507 } else {
12508 word = *wbuf;
12509 }
12510 chksum += *wbuf; /* Checksum is calculated from word values. */
12511 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12512 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12513 ASC_EEP_CMD_WRITE | addr);
12514 AdvWaitEEPCmd(iop_base);
12515 mdelay(ADV_EEP_DELAY_MS);
12516 }
12517
12518 /*
12519 * Write EEPROM checksum at word 21.
12520 */
12521 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12522 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12523 AdvWaitEEPCmd(iop_base);
12524 wbuf++;
12525 charfields++;
12526
12527 /*
12528 * Write EEPROM OEM name at words 22 to 29.
12529 */
12530 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12531 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12532 ushort word;
12533
12534 if (*charfields++) {
12535 word = cpu_to_le16(*wbuf);
12536 } else {
12537 word = *wbuf;
12538 }
12539 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12540 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12541 ASC_EEP_CMD_WRITE | addr);
12542 AdvWaitEEPCmd(iop_base);
12543 }
12544 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12545 AdvWaitEEPCmd(iop_base);
12546}
12547
12548/*
12549 * Write the EEPROM from 'cfg_buf'.
12550 */
12551void __devinit
12552AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12553{
12554 ushort *wbuf;
12555 ushort *charfields;
12556 ushort addr, chksum;
12557
12558 wbuf = (ushort *)cfg_buf;
12559 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12560 chksum = 0;
12561
12562 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12563 AdvWaitEEPCmd(iop_base);
12564
12565 /*
12566 * Write EEPROM from word 0 to word 20.
12567 */
12568 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12569 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12570 ushort word;
12571
12572 if (*charfields++) {
12573 word = cpu_to_le16(*wbuf);
12574 } else {
12575 word = *wbuf;
12576 }
12577 chksum += *wbuf; /* Checksum is calculated from word values. */
12578 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12579 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12580 ASC_EEP_CMD_WRITE | addr);
12581 AdvWaitEEPCmd(iop_base);
12582 mdelay(ADV_EEP_DELAY_MS);
12583 }
12584
12585 /*
12586 * Write EEPROM checksum at word 21.
12587 */
12588 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12589 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12590 AdvWaitEEPCmd(iop_base);
12591 wbuf++;
12592 charfields++;
12593
12594 /*
12595 * Write EEPROM OEM name at words 22 to 29.
12596 */
12597 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12598 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12599 ushort word;
12600
12601 if (*charfields++) {
12602 word = cpu_to_le16(*wbuf);
12603 } else {
12604 word = *wbuf;
12605 }
12606 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12607 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12608 ASC_EEP_CMD_WRITE | addr);
12609 AdvWaitEEPCmd(iop_base);
12610 }
12611 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12612 AdvWaitEEPCmd(iop_base);
12613}
12614
12615/*
12616 * Write the EEPROM from 'cfg_buf'.
12617 */
12618void __devinit
12619AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12620{
12621 ushort *wbuf;
12622 ushort *charfields;
12623 ushort addr, chksum;
12624
12625 wbuf = (ushort *)cfg_buf;
12626 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12627 chksum = 0;
12628
12629 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12630 AdvWaitEEPCmd(iop_base);
12631
12632 /*
12633 * Write EEPROM from word 0 to word 20.
12634 */
12635 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12636 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12637 ushort word;
12638
12639 if (*charfields++) {
12640 word = cpu_to_le16(*wbuf);
12641 } else {
12642 word = *wbuf;
12643 }
12644 chksum += *wbuf; /* Checksum is calculated from word values. */
12645 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12646 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12647 ASC_EEP_CMD_WRITE | addr);
12648 AdvWaitEEPCmd(iop_base);
12649 mdelay(ADV_EEP_DELAY_MS);
12650 }
12651
12652 /*
12653 * Write EEPROM checksum at word 21.
12654 */
12655 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12656 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12657 AdvWaitEEPCmd(iop_base);
12658 wbuf++;
12659 charfields++;
12660
12661 /*
12662 * Write EEPROM OEM name at words 22 to 29.
12663 */
12664 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12665 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12666 ushort word;
12667
12668 if (*charfields++) {
12669 word = cpu_to_le16(*wbuf);
12670 } else {
12671 word = *wbuf;
12672 }
12673 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12674 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12675 ASC_EEP_CMD_WRITE | addr);
12676 AdvWaitEEPCmd(iop_base);
12677 }
12678 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12679 AdvWaitEEPCmd(iop_base);
12680}
12681
12682/*
12683 * Read EEPROM configuration into the specified buffer.
12684 *
12685 * Return a checksum based on the EEPROM configuration read.
12686 */
12687static ushort __devinit
12688AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12689{
12690 ushort wval, chksum;
12691 ushort *wbuf;
12692 int eep_addr;
12693 ushort *charfields;
12694
12695 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12696 wbuf = (ushort *)cfg_buf;
12697 chksum = 0;
12698
12699 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12700 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12701 wval = AdvReadEEPWord(iop_base, eep_addr);
12702 chksum += wval; /* Checksum is calculated from word values. */
12703 if (*charfields++) {
12704 *wbuf = le16_to_cpu(wval);
12705 } else {
12706 *wbuf = wval;
12707 }
12708 }
12709 /* Read checksum word. */
12710 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12711 wbuf++;
12712 charfields++;
12713
12714 /* Read rest of EEPROM not covered by the checksum. */
12715 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12716 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12717 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12718 if (*charfields++) {
12719 *wbuf = le16_to_cpu(*wbuf);
12720 }
12721 }
12722 return chksum;
12723}
12724
12725/*
12726 * Read EEPROM configuration into the specified buffer.
12727 *
12728 * Return a checksum based on the EEPROM configuration read.
12729 */
12730static ushort __devinit
12731AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12732{
12733 ushort wval, chksum;
12734 ushort *wbuf;
12735 int eep_addr;
12736 ushort *charfields;
12737
12738 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12739 wbuf = (ushort *)cfg_buf;
12740 chksum = 0;
12741
12742 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12743 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12744 wval = AdvReadEEPWord(iop_base, eep_addr);
12745 chksum += wval; /* Checksum is calculated from word values. */
12746 if (*charfields++) {
12747 *wbuf = le16_to_cpu(wval);
12748 } else {
12749 *wbuf = wval;
12750 }
12751 }
12752 /* Read checksum word. */
12753 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12754 wbuf++;
12755 charfields++;
12756
12757 /* Read rest of EEPROM not covered by the checksum. */
12758 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12759 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12760 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12761 if (*charfields++) {
12762 *wbuf = le16_to_cpu(*wbuf);
12763 }
12764 }
12765 return chksum;
12766}
12767
12768/*
12769 * Read EEPROM configuration into the specified buffer.
12770 *
12771 * Return a checksum based on the EEPROM configuration read.
12772 */
12773static ushort __devinit
12774AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12775{
12776 ushort wval, chksum;
12777 ushort *wbuf;
12778 int eep_addr;
12779 ushort *charfields;
12780
12781 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12782 wbuf = (ushort *)cfg_buf;
12783 chksum = 0;
12784
12785 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12786 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12787 wval = AdvReadEEPWord(iop_base, eep_addr);
12788 chksum += wval; /* Checksum is calculated from word values. */
12789 if (*charfields++) {
12790 *wbuf = le16_to_cpu(wval);
12791 } else {
12792 *wbuf = wval;
12793 }
12794 }
12795 /* Read checksum word. */
12796 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12797 wbuf++;
12798 charfields++;
12799
12800 /* Read rest of EEPROM not covered by the checksum. */
12801 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12802 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12803 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12804 if (*charfields++) {
12805 *wbuf = le16_to_cpu(*wbuf);
12806 }
12807 }
12808 return chksum;
12809}
12810
12811/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070012812 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12813 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12814 * all of this is done.
12815 *
12816 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12817 *
12818 * For a non-fatal error return a warning code. If there are no warnings
12819 * then 0 is returned.
12820 *
12821 * Note: Chip is stopped on entry.
12822 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012823static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012824{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012825 AdvPortAddr iop_base;
12826 ushort warn_code;
12827 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012828
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012829 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012831 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012832
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012833 /*
12834 * Read the board's EEPROM configuration.
12835 *
12836 * Set default values if a bad checksum is found.
12837 */
12838 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12839 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012841 /*
12842 * Set EEPROM default values.
12843 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012844 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12845 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012847 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012848 * Assume the 6 byte board serial number that was read from
12849 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012850 */
12851 eep_config.serial_number_word3 =
12852 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012853
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012854 eep_config.serial_number_word2 =
12855 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012857 eep_config.serial_number_word1 =
12858 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012859
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012860 AdvSet3550EEPConfig(iop_base, &eep_config);
12861 }
12862 /*
12863 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
12864 * EEPROM configuration that was read.
12865 *
12866 * This is the mapping of EEPROM fields to Adv Library fields.
12867 */
12868 asc_dvc->wdtr_able = eep_config.wdtr_able;
12869 asc_dvc->sdtr_able = eep_config.sdtr_able;
12870 asc_dvc->ultra_able = eep_config.ultra_able;
12871 asc_dvc->tagqng_able = eep_config.tagqng_able;
12872 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
12873 asc_dvc->max_host_qng = eep_config.max_host_qng;
12874 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
12875 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
12876 asc_dvc->start_motor = eep_config.start_motor;
12877 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
12878 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
12879 asc_dvc->no_scam = eep_config.scam_tolerant;
12880 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
12881 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
12882 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012883
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012884 /*
12885 * Set the host maximum queuing (max. 253, min. 16) and the per device
12886 * maximum queuing (max. 63, min. 4).
12887 */
12888 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
12889 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12890 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
12891 /* If the value is zero, assume it is uninitialized. */
12892 if (eep_config.max_host_qng == 0) {
12893 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12894 } else {
12895 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
12896 }
12897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012898
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012899 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
12900 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12901 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
12902 /* If the value is zero, assume it is uninitialized. */
12903 if (eep_config.max_dvc_qng == 0) {
12904 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12905 } else {
12906 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
12907 }
12908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012909
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012910 /*
12911 * If 'max_dvc_qng' is greater than 'max_host_qng', then
12912 * set 'max_dvc_qng' to 'max_host_qng'.
12913 */
12914 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
12915 eep_config.max_dvc_qng = eep_config.max_host_qng;
12916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012917
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012918 /*
12919 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
12920 * values based on possibly adjusted EEPROM values.
12921 */
12922 asc_dvc->max_host_qng = eep_config.max_host_qng;
12923 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012924
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012925 /*
12926 * If the EEPROM 'termination' field is set to automatic (0), then set
12927 * the ADV_DVC_CFG 'termination' field to automatic also.
12928 *
12929 * If the termination is specified with a non-zero 'termination'
12930 * value check that a legal value is set and set the ADV_DVC_CFG
12931 * 'termination' field appropriately.
12932 */
12933 if (eep_config.termination == 0) {
12934 asc_dvc->cfg->termination = 0; /* auto termination */
12935 } else {
12936 /* Enable manual control with low off / high off. */
12937 if (eep_config.termination == 1) {
12938 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012939
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012940 /* Enable manual control with low off / high on. */
12941 } else if (eep_config.termination == 2) {
12942 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012943
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012944 /* Enable manual control with low on / high on. */
12945 } else if (eep_config.termination == 3) {
12946 asc_dvc->cfg->termination =
12947 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
12948 } else {
12949 /*
12950 * The EEPROM 'termination' field contains a bad value. Use
12951 * automatic termination instead.
12952 */
12953 asc_dvc->cfg->termination = 0;
12954 warn_code |= ASC_WARN_EEPROM_TERMINATION;
12955 }
12956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012957
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012958 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012959}
12960
12961/*
12962 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12963 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12964 * all of this is done.
12965 *
12966 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12967 *
12968 * For a non-fatal error return a warning code. If there are no warnings
12969 * then 0 is returned.
12970 *
12971 * Note: Chip is stopped on entry.
12972 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012973static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012974{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012975 AdvPortAddr iop_base;
12976 ushort warn_code;
12977 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012978 uchar tid, termination;
12979 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012980
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012981 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012982
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012983 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012984
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012985 /*
12986 * Read the board's EEPROM configuration.
12987 *
12988 * Set default values if a bad checksum is found.
12989 */
12990 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
12991 eep_config.check_sum) {
12992 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012993
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012994 /*
12995 * Set EEPROM default values.
12996 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012997 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
12998 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012999
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013000 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013001 * Assume the 6 byte board serial number that was read from
13002 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013003 */
13004 eep_config.serial_number_word3 =
13005 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013006
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013007 eep_config.serial_number_word2 =
13008 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013009
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013010 eep_config.serial_number_word1 =
13011 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013012
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013013 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13014 }
13015 /*
13016 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13017 * EEPROM configuration that was read.
13018 *
13019 * This is the mapping of EEPROM fields to Adv Library fields.
13020 */
13021 asc_dvc->wdtr_able = eep_config.wdtr_able;
13022 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13023 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13024 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13025 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13026 asc_dvc->tagqng_able = eep_config.tagqng_able;
13027 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13028 asc_dvc->max_host_qng = eep_config.max_host_qng;
13029 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13030 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13031 asc_dvc->start_motor = eep_config.start_motor;
13032 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13033 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13034 asc_dvc->no_scam = eep_config.scam_tolerant;
13035 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13036 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13037 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013038
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013039 /*
13040 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13041 * are set, then set an 'sdtr_able' bit for it.
13042 */
13043 asc_dvc->sdtr_able = 0;
13044 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13045 if (tid == 0) {
13046 sdtr_speed = asc_dvc->sdtr_speed1;
13047 } else if (tid == 4) {
13048 sdtr_speed = asc_dvc->sdtr_speed2;
13049 } else if (tid == 8) {
13050 sdtr_speed = asc_dvc->sdtr_speed3;
13051 } else if (tid == 12) {
13052 sdtr_speed = asc_dvc->sdtr_speed4;
13053 }
13054 if (sdtr_speed & ADV_MAX_TID) {
13055 asc_dvc->sdtr_able |= (1 << tid);
13056 }
13057 sdtr_speed >>= 4;
13058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013059
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013060 /*
13061 * Set the host maximum queuing (max. 253, min. 16) and the per device
13062 * maximum queuing (max. 63, min. 4).
13063 */
13064 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13065 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13066 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13067 /* If the value is zero, assume it is uninitialized. */
13068 if (eep_config.max_host_qng == 0) {
13069 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13070 } else {
13071 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13072 }
13073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013074
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013075 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13076 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13077 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13078 /* If the value is zero, assume it is uninitialized. */
13079 if (eep_config.max_dvc_qng == 0) {
13080 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13081 } else {
13082 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13083 }
13084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013085
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013086 /*
13087 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13088 * set 'max_dvc_qng' to 'max_host_qng'.
13089 */
13090 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13091 eep_config.max_dvc_qng = eep_config.max_host_qng;
13092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013093
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013094 /*
13095 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13096 * values based on possibly adjusted EEPROM values.
13097 */
13098 asc_dvc->max_host_qng = eep_config.max_host_qng;
13099 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013100
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013101 /*
13102 * If the EEPROM 'termination' field is set to automatic (0), then set
13103 * the ADV_DVC_CFG 'termination' field to automatic also.
13104 *
13105 * If the termination is specified with a non-zero 'termination'
13106 * value check that a legal value is set and set the ADV_DVC_CFG
13107 * 'termination' field appropriately.
13108 */
13109 if (eep_config.termination_se == 0) {
13110 termination = 0; /* auto termination for SE */
13111 } else {
13112 /* Enable manual control with low off / high off. */
13113 if (eep_config.termination_se == 1) {
13114 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013115
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013116 /* Enable manual control with low off / high on. */
13117 } else if (eep_config.termination_se == 2) {
13118 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013119
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013120 /* Enable manual control with low on / high on. */
13121 } else if (eep_config.termination_se == 3) {
13122 termination = TERM_SE;
13123 } else {
13124 /*
13125 * The EEPROM 'termination_se' field contains a bad value.
13126 * Use automatic termination instead.
13127 */
13128 termination = 0;
13129 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13130 }
13131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013132
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013133 if (eep_config.termination_lvd == 0) {
13134 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13135 } else {
13136 /* Enable manual control with low off / high off. */
13137 if (eep_config.termination_lvd == 1) {
13138 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013140 /* Enable manual control with low off / high on. */
13141 } else if (eep_config.termination_lvd == 2) {
13142 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013144 /* Enable manual control with low on / high on. */
13145 } else if (eep_config.termination_lvd == 3) {
13146 asc_dvc->cfg->termination = termination | TERM_LVD;
13147 } else {
13148 /*
13149 * The EEPROM 'termination_lvd' field contains a bad value.
13150 * Use automatic termination instead.
13151 */
13152 asc_dvc->cfg->termination = termination;
13153 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13154 }
13155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013156
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013157 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013158}
13159
13160/*
13161 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13162 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13163 * all of this is done.
13164 *
13165 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13166 *
13167 * For a non-fatal error return a warning code. If there are no warnings
13168 * then 0 is returned.
13169 *
13170 * Note: Chip is stopped on entry.
13171 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013172static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013173{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013174 AdvPortAddr iop_base;
13175 ushort warn_code;
13176 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013177 uchar tid, termination;
13178 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013179
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013180 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013181
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013182 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013183
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013184 /*
13185 * Read the board's EEPROM configuration.
13186 *
13187 * Set default values if a bad checksum is found.
13188 */
13189 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13190 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013191 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013192 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013193
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013194 /*
13195 * Set EEPROM default values.
13196 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013197 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13198 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013199
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013200 if (PCI_FUNC(pdev->devfn) != 0) {
13201 u8 ints;
13202 /*
13203 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13204 * and old Mac system booting problem. The Expansion
13205 * ROM must be disabled in Function 1 for these systems
13206 */
13207 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13208 /*
13209 * Clear the INTAB (bit 11) if the GPIO 0 input
13210 * indicates the Function 1 interrupt line is wired
13211 * to INTB.
13212 *
13213 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13214 * 1 - Function 1 interrupt line wired to INT A.
13215 * 0 - Function 1 interrupt line wired to INT B.
13216 *
13217 * Note: Function 0 is always wired to INTA.
13218 * Put all 5 GPIO bits in input mode and then read
13219 * their input values.
13220 */
13221 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13222 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13223 if ((ints & 0x01) == 0)
13224 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013226
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013227 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013228 * Assume the 6 byte board serial number that was read from
13229 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013230 */
13231 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013232 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013233 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013234 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013235 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013236 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013237
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013238 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013240
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013241 /*
13242 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13243 * EEPROM configuration that was read.
13244 *
13245 * This is the mapping of EEPROM fields to Adv Library fields.
13246 */
13247 asc_dvc->wdtr_able = eep_config.wdtr_able;
13248 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13249 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13250 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13251 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13252 asc_dvc->ppr_able = 0;
13253 asc_dvc->tagqng_able = eep_config.tagqng_able;
13254 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13255 asc_dvc->max_host_qng = eep_config.max_host_qng;
13256 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13257 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13258 asc_dvc->start_motor = eep_config.start_motor;
13259 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13260 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13261 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013262
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013263 /*
13264 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13265 * are set, then set an 'sdtr_able' bit for it.
13266 */
13267 asc_dvc->sdtr_able = 0;
13268 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13269 if (tid == 0) {
13270 sdtr_speed = asc_dvc->sdtr_speed1;
13271 } else if (tid == 4) {
13272 sdtr_speed = asc_dvc->sdtr_speed2;
13273 } else if (tid == 8) {
13274 sdtr_speed = asc_dvc->sdtr_speed3;
13275 } else if (tid == 12) {
13276 sdtr_speed = asc_dvc->sdtr_speed4;
13277 }
13278 if (sdtr_speed & ASC_MAX_TID) {
13279 asc_dvc->sdtr_able |= (1 << tid);
13280 }
13281 sdtr_speed >>= 4;
13282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013283
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013284 /*
13285 * Set the host maximum queuing (max. 253, min. 16) and the per device
13286 * maximum queuing (max. 63, min. 4).
13287 */
13288 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13289 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13290 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13291 /* If the value is zero, assume it is uninitialized. */
13292 if (eep_config.max_host_qng == 0) {
13293 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13294 } else {
13295 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13296 }
13297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013298
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013299 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13300 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13301 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13302 /* If the value is zero, assume it is uninitialized. */
13303 if (eep_config.max_dvc_qng == 0) {
13304 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13305 } else {
13306 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13307 }
13308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013309
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013310 /*
13311 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13312 * set 'max_dvc_qng' to 'max_host_qng'.
13313 */
13314 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13315 eep_config.max_dvc_qng = eep_config.max_host_qng;
13316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013317
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013318 /*
13319 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13320 * values based on possibly adjusted EEPROM values.
13321 */
13322 asc_dvc->max_host_qng = eep_config.max_host_qng;
13323 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013324
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013325 /*
13326 * If the EEPROM 'termination' field is set to automatic (0), then set
13327 * the ASC_DVC_CFG 'termination' field to automatic also.
13328 *
13329 * If the termination is specified with a non-zero 'termination'
13330 * value check that a legal value is set and set the ASC_DVC_CFG
13331 * 'termination' field appropriately.
13332 */
13333 if (eep_config.termination_se == 0) {
13334 termination = 0; /* auto termination for SE */
13335 } else {
13336 /* Enable manual control with low off / high off. */
13337 if (eep_config.termination_se == 1) {
13338 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013339
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013340 /* Enable manual control with low off / high on. */
13341 } else if (eep_config.termination_se == 2) {
13342 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013343
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013344 /* Enable manual control with low on / high on. */
13345 } else if (eep_config.termination_se == 3) {
13346 termination = TERM_SE;
13347 } else {
13348 /*
13349 * The EEPROM 'termination_se' field contains a bad value.
13350 * Use automatic termination instead.
13351 */
13352 termination = 0;
13353 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13354 }
13355 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013356
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013357 if (eep_config.termination_lvd == 0) {
13358 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13359 } else {
13360 /* Enable manual control with low off / high off. */
13361 if (eep_config.termination_lvd == 1) {
13362 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013363
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013364 /* Enable manual control with low off / high on. */
13365 } else if (eep_config.termination_lvd == 2) {
13366 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013367
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013368 /* Enable manual control with low on / high on. */
13369 } else if (eep_config.termination_lvd == 3) {
13370 asc_dvc->cfg->termination = termination | TERM_LVD;
13371 } else {
13372 /*
13373 * The EEPROM 'termination_lvd' field contains a bad value.
13374 * Use automatic termination instead.
13375 */
13376 asc_dvc->cfg->termination = termination;
13377 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13378 }
13379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013380
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013381 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013382}
13383
13384/*
Matthew Wilcox51219352007-10-02 21:55:22 -040013385 * Initialize the ADV_DVC_VAR structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013386 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013387 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013388 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013389 * For a non-fatal error return a warning code. If there are no warnings
13390 * then 0 is returned.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013391 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013392static int __devinit
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013393AdvInitGetConfig(struct pci_dev *pdev, struct asc_board *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013394{
Matthew Wilcox51219352007-10-02 21:55:22 -040013395 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
13396 unsigned short warn_code = 0;
13397 AdvPortAddr iop_base = asc_dvc->iop_base;
13398 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013399 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013400
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013401 asc_dvc->err_code = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040013402
13403 /*
13404 * Save the state of the PCI Configuration Command Register
13405 * "Parity Error Response Control" Bit. If the bit is clear (0),
13406 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13407 * DMA parity errors.
13408 */
13409 asc_dvc->cfg->control_flag = 0;
13410 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
13411 if ((cmd & PCI_COMMAND_PARITY) == 0)
13412 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
13413
Matthew Wilcox51219352007-10-02 21:55:22 -040013414 asc_dvc->cfg->chip_version =
13415 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
13416
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013417 ASC_DBG(1, "iopb_chip_id_1: 0x%x 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -040013418 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13419 (ushort)ADV_CHIP_ID_BYTE);
13420
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013421 ASC_DBG(1, "iopw_chip_id_0: 0x%x 0x%x\n",
Matthew Wilcox51219352007-10-02 21:55:22 -040013422 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13423 (ushort)ADV_CHIP_ID_WORD);
13424
13425 /*
13426 * Reset the chip to start and allow register writes.
13427 */
13428 if (AdvFindSignature(iop_base) == 0) {
13429 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13430 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013431 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013432 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013433 * The caller must set 'chip_type' to a valid setting.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013434 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013435 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13436 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13437 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13438 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13439 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013442 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013443 * Reset Chip.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013444 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013445 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13446 ADV_CTRL_REG_CMD_RESET);
13447 mdelay(100);
13448 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13449 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013450
Matthew Wilcox51219352007-10-02 21:55:22 -040013451 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13452 status = AdvInitFrom38C1600EEP(asc_dvc);
13453 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13454 status = AdvInitFrom38C0800EEP(asc_dvc);
13455 } else {
13456 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013457 }
Matthew Wilcox51219352007-10-02 21:55:22 -040013458 warn_code |= status;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013459 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013460
Matthew Wilcox51219352007-10-02 21:55:22 -040013461 if (warn_code != 0) {
13462 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
13463 boardp->id, warn_code);
13464 }
13465
13466 if (asc_dvc->err_code) {
13467 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
13468 boardp->id, asc_dvc->err_code);
13469 }
13470
13471 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013472}
Matthew Wilcox51219352007-10-02 21:55:22 -040013473#endif
13474
13475static struct scsi_host_template advansys_template = {
13476 .proc_name = DRV_NAME,
13477#ifdef CONFIG_PROC_FS
13478 .proc_info = advansys_proc_info,
13479#endif
13480 .name = DRV_NAME,
13481 .info = advansys_info,
13482 .queuecommand = advansys_queuecommand,
13483 .eh_bus_reset_handler = advansys_reset,
13484 .bios_param = advansys_biosparam,
13485 .slave_configure = advansys_slave_configure,
13486 /*
13487 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
13488 * must be set. The flag will be cleared in advansys_board_found
13489 * for non-ISA adapters.
13490 */
13491 .unchecked_isa_dma = 1,
13492 /*
13493 * All adapters controlled by this driver are capable of large
13494 * scatter-gather lists. According to the mid-level SCSI documentation
13495 * this obviates any performance gain provided by setting
13496 * 'use_clustering'. But empirically while CPU utilization is increased
13497 * by enabling clustering, I/O throughput increases as well.
13498 */
13499 .use_clustering = ENABLE_CLUSTERING,
13500};
Linus Torvalds1da177e2005-04-16 15:20:36 -070013501
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013502static int __devinit
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013503advansys_wide_init_chip(struct asc_board *boardp, ADV_DVC_VAR *adv_dvc_varp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013504{
13505 int req_cnt = 0;
13506 adv_req_t *reqp = NULL;
13507 int sg_cnt = 0;
13508 adv_sgblk_t *sgp;
13509 int warn_code, err_code;
13510
13511 /*
13512 * Allocate buffer carrier structures. The total size
13513 * is about 4 KB, so allocate all at once.
13514 */
13515 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013516 ASC_DBG(1, "carrp 0x%p\n", boardp->carrp);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013517
13518 if (!boardp->carrp)
13519 goto kmalloc_failed;
13520
13521 /*
13522 * Allocate up to 'max_host_qng' request structures for the Wide
13523 * board. The total size is about 16 KB, so allocate all at once.
13524 * If the allocation fails decrement and try again.
13525 */
13526 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
13527 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
13528
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013529 ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt,
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013530 (ulong)sizeof(adv_req_t) * req_cnt);
13531
13532 if (reqp)
13533 break;
13534 }
13535
13536 if (!reqp)
13537 goto kmalloc_failed;
13538
13539 boardp->orig_reqp = reqp;
13540
13541 /*
13542 * Allocate up to ADV_TOT_SG_BLOCK request structures for
13543 * the Wide board. Each structure is about 136 bytes.
13544 */
13545 boardp->adv_sgblkp = NULL;
13546 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
13547 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
13548
13549 if (!sgp)
13550 break;
13551
13552 sgp->next_sgblkp = boardp->adv_sgblkp;
13553 boardp->adv_sgblkp = sgp;
13554
13555 }
13556
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013557 ASC_DBG(1, "sg_cnt %d * %u = %u bytes\n", sg_cnt, sizeof(adv_sgblk_t),
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013558 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
13559
13560 if (!boardp->adv_sgblkp)
13561 goto kmalloc_failed;
13562
13563 adv_dvc_varp->carrier_buf = boardp->carrp;
13564
13565 /*
13566 * Point 'adv_reqp' to the request structures and
13567 * link them together.
13568 */
13569 req_cnt--;
13570 reqp[req_cnt].next_reqp = NULL;
13571 for (; req_cnt > 0; req_cnt--) {
13572 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
13573 }
13574 boardp->adv_reqp = &reqp[0];
13575
13576 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013577 ASC_DBG(2, "AdvInitAsc3550Driver()\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013578 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
13579 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013580 ASC_DBG(2, "AdvInitAsc38C0800Driver()\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013581 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
13582 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013583 ASC_DBG(2, "AdvInitAsc38C1600Driver()\n");
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013584 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
13585 }
13586 err_code = adv_dvc_varp->err_code;
13587
13588 if (warn_code || err_code) {
13589 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
13590 " error 0x%x\n", boardp->id, warn_code, err_code);
13591 }
13592
13593 goto exit;
13594
13595 kmalloc_failed:
13596 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
13597 "failed\n", boardp->id);
13598 err_code = ADV_ERROR;
13599 exit:
13600 return err_code;
13601}
13602
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013603static void advansys_wide_free_mem(struct asc_board *boardp)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013604{
13605 kfree(boardp->carrp);
13606 boardp->carrp = NULL;
13607 kfree(boardp->orig_reqp);
13608 boardp->orig_reqp = boardp->adv_reqp = NULL;
13609 while (boardp->adv_sgblkp) {
13610 adv_sgblk_t *sgp = boardp->adv_sgblkp;
13611 boardp->adv_sgblkp = sgp->next_sgblkp;
13612 kfree(sgp);
13613 }
13614}
13615
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013616static int __devinit advansys_board_found(struct Scsi_Host *shost,
13617 unsigned int iop, int bus_type)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013618{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013619 struct pci_dev *pdev;
Matthew Wilcoxd2411492007-10-02 21:55:31 -040013620 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013621 ASC_DVC_VAR *asc_dvc_varp = NULL;
13622 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013623 int share_irq, warn_code, ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013624
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013625 boardp->id = asc_board_count++;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013626 pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013627
13628 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013629 ASC_DBG(1, "narrow board\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013630 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
13631 asc_dvc_varp->bus_type = bus_type;
13632 asc_dvc_varp->drv_ptr = boardp;
13633 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
13634 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
13635 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013636 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013637#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013638 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
13639 adv_dvc_varp->drv_ptr = boardp;
13640 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013641 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013642 ASC_DBG(1, "wide board ASC-3550\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013643 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
13644 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013645 ASC_DBG(1, "wide board ASC-38C0800\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013646 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
13647 } else {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013648 ASC_DBG(1, "wide board ASC-38C1600\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013649 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
13650 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013651
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013652 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
13653 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
13654 boardp->asc_n_io_port);
13655 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013656 ASC_PRINT3
13657 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013658 boardp->id, pci_resource_start(pdev, 1),
13659 boardp->asc_n_io_port);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013660 ret = -ENODEV;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013661 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013662 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013663 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr;
13664 ASC_DBG(1, "iop_base: 0x%p\n", adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013665
13666 /*
13667 * Even though it isn't used to access wide boards, other
13668 * than for the debug line below, save I/O Port address so
13669 * that it can be reported.
13670 */
13671 boardp->ioport = iop;
13672
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013673 ASC_DBG(1, "iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
13674 (ushort)inp(iop + 1), (ushort)inpw(iop));
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013675#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013676 }
13677
13678#ifdef CONFIG_PROC_FS
13679 /*
13680 * Allocate buffer for printing information from
13681 * /proc/scsi/advansys/[0...].
13682 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013683 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
13684 if (!boardp->prtbuf) {
13685 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
13686 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013687 ret = -ENOMEM;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013688 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013689 }
13690#endif /* CONFIG_PROC_FS */
13691
13692 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013693 /*
13694 * Set the board bus type and PCI IRQ before
13695 * calling AscInitGetConfig().
13696 */
13697 switch (asc_dvc_varp->bus_type) {
13698#ifdef CONFIG_ISA
13699 case ASC_IS_ISA:
13700 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013701 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013702 break;
13703 case ASC_IS_VL:
13704 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013705 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013706 break;
13707 case ASC_IS_EISA:
13708 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013709 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013710 break;
13711#endif /* CONFIG_ISA */
13712#ifdef CONFIG_PCI
13713 case ASC_IS_PCI:
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013714 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013715 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013716 break;
13717#endif /* CONFIG_PCI */
13718 default:
13719 ASC_PRINT2
13720 ("advansys_board_found: board %d: unknown adapter type: %d\n",
13721 boardp->id, asc_dvc_varp->bus_type);
13722 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013723 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013724 break;
13725 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013726
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013727 /*
13728 * NOTE: AscInitGetConfig() may change the board's
13729 * bus_type value. The bus_type value should no
13730 * longer be used. If the bus_type field must be
13731 * referenced only use the bit-wise AND operator "&".
13732 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013733 ASC_DBG(2, "AscInitGetConfig()\n");
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013734 ret = AscInitGetConfig(boardp) ? -ENODEV : 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013735 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013736#ifdef CONFIG_PCI
13737 /*
13738 * For Wide boards set PCI information before calling
13739 * AdvInitGetConfig().
13740 */
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013741 shost->unchecked_isa_dma = FALSE;
13742 share_irq = IRQF_SHARED;
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013743 ASC_DBG(2, "AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040013744
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013745 ret = AdvInitGetConfig(pdev, boardp) ? -ENODEV : 0;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013746#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013747 }
13748
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013749 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013750 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013751
13752 /*
13753 * Save the EEPROM configuration so that it can be displayed
13754 * from /proc/scsi/advansys/[0...].
13755 */
13756 if (ASC_NARROW_BOARD(boardp)) {
13757
13758 ASCEEP_CONFIG *ep;
13759
13760 /*
13761 * Set the adapter's target id bit in the 'init_tidmask' field.
13762 */
13763 boardp->init_tidmask |=
13764 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
13765
13766 /*
13767 * Save EEPROM settings for the board.
13768 */
13769 ep = &boardp->eep_config.asc_eep;
13770
13771 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
13772 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
13773 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
13774 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
13775 ep->start_motor = asc_dvc_varp->start_motor;
13776 ep->cntl = asc_dvc_varp->dvc_cntl;
13777 ep->no_scam = asc_dvc_varp->no_scam;
13778 ep->max_total_qng = asc_dvc_varp->max_total_qng;
13779 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
13780 /* 'max_tag_qng' is set to the same value for every device. */
13781 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
13782 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
13783 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
13784 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
13785 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
13786 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
13787 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
13788
13789 /*
13790 * Modify board configuration.
13791 */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013792 ASC_DBG(2, "AscInitSetConfig()\n");
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013793 ret = AscInitSetConfig(pdev, boardp) ? -ENODEV : 0;
13794 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013795 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013796 } else {
13797 ADVEEP_3550_CONFIG *ep_3550;
13798 ADVEEP_38C0800_CONFIG *ep_38C0800;
13799 ADVEEP_38C1600_CONFIG *ep_38C1600;
13800
13801 /*
13802 * Save Wide EEP Configuration Information.
13803 */
13804 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
13805 ep_3550 = &boardp->eep_config.adv_3550_eep;
13806
13807 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
13808 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
13809 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13810 ep_3550->termination = adv_dvc_varp->cfg->termination;
13811 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
13812 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
13813 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
13814 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
13815 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
13816 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
13817 ep_3550->start_motor = adv_dvc_varp->start_motor;
13818 ep_3550->scsi_reset_delay =
13819 adv_dvc_varp->scsi_reset_wait;
13820 ep_3550->serial_number_word1 =
13821 adv_dvc_varp->cfg->serial1;
13822 ep_3550->serial_number_word2 =
13823 adv_dvc_varp->cfg->serial2;
13824 ep_3550->serial_number_word3 =
13825 adv_dvc_varp->cfg->serial3;
13826 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
13827 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
13828
13829 ep_38C0800->adapter_scsi_id =
13830 adv_dvc_varp->chip_scsi_id;
13831 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
13832 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13833 ep_38C0800->termination_lvd =
13834 adv_dvc_varp->cfg->termination;
13835 ep_38C0800->disc_enable =
13836 adv_dvc_varp->cfg->disc_enable;
13837 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
13838 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
13839 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
13840 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
13841 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
13842 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
13843 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
13844 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
13845 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
13846 ep_38C0800->scsi_reset_delay =
13847 adv_dvc_varp->scsi_reset_wait;
13848 ep_38C0800->serial_number_word1 =
13849 adv_dvc_varp->cfg->serial1;
13850 ep_38C0800->serial_number_word2 =
13851 adv_dvc_varp->cfg->serial2;
13852 ep_38C0800->serial_number_word3 =
13853 adv_dvc_varp->cfg->serial3;
13854 } else {
13855 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
13856
13857 ep_38C1600->adapter_scsi_id =
13858 adv_dvc_varp->chip_scsi_id;
13859 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
13860 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13861 ep_38C1600->termination_lvd =
13862 adv_dvc_varp->cfg->termination;
13863 ep_38C1600->disc_enable =
13864 adv_dvc_varp->cfg->disc_enable;
13865 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
13866 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
13867 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
13868 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
13869 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
13870 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
13871 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
13872 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
13873 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
13874 ep_38C1600->scsi_reset_delay =
13875 adv_dvc_varp->scsi_reset_wait;
13876 ep_38C1600->serial_number_word1 =
13877 adv_dvc_varp->cfg->serial1;
13878 ep_38C1600->serial_number_word2 =
13879 adv_dvc_varp->cfg->serial2;
13880 ep_38C1600->serial_number_word3 =
13881 adv_dvc_varp->cfg->serial3;
13882 }
13883
13884 /*
13885 * Set the adapter's target id bit in the 'init_tidmask' field.
13886 */
13887 boardp->init_tidmask |=
13888 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013889 }
13890
13891 /*
13892 * Channels are numbered beginning with 0. For AdvanSys one host
13893 * structure supports one channel. Multi-channel boards have a
13894 * separate host structure for each channel.
13895 */
13896 shost->max_channel = 0;
13897 if (ASC_NARROW_BOARD(boardp)) {
13898 shost->max_id = ASC_MAX_TID + 1;
13899 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060013900 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013901
13902 shost->io_port = asc_dvc_varp->iop_base;
13903 boardp->asc_n_io_port = ASC_IOADR_GAP;
13904 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
13905
13906 /* Set maximum number of queues the adapter can handle. */
13907 shost->can_queue = asc_dvc_varp->max_total_qng;
13908 } else {
13909 shost->max_id = ADV_MAX_TID + 1;
13910 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060013911 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013912
13913 /*
13914 * Save the I/O Port address and length even though
13915 * I/O ports are not used to access Wide boards.
13916 * Instead the Wide boards are accessed with
13917 * PCI Memory Mapped I/O.
13918 */
13919 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013920
13921 shost->this_id = adv_dvc_varp->chip_scsi_id;
13922
13923 /* Set maximum number of queues the adapter can handle. */
13924 shost->can_queue = adv_dvc_varp->max_host_qng;
13925 }
13926
13927 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013928 * Following v1.3.89, 'cmd_per_lun' is no longer needed
13929 * and should be set to zero.
13930 *
13931 * But because of a bug introduced in v1.3.89 if the driver is
13932 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
13933 * SCSI function 'allocate_device' will panic. To allow the driver
13934 * to work as a module in these kernels set 'cmd_per_lun' to 1.
13935 *
13936 * Note: This is wrong. cmd_per_lun should be set to the depth
13937 * you want on untagged devices always.
13938 #ifdef MODULE
13939 */
13940 shost->cmd_per_lun = 1;
13941/* #else
13942 shost->cmd_per_lun = 0;
13943#endif */
13944
13945 /*
13946 * Set the maximum number of scatter-gather elements the
13947 * adapter can handle.
13948 */
13949 if (ASC_NARROW_BOARD(boardp)) {
13950 /*
13951 * Allow two commands with 'sg_tablesize' scatter-gather
13952 * elements to be executed simultaneously. This value is
13953 * the theoretical hardware limit. It may be decreased
13954 * below.
13955 */
13956 shost->sg_tablesize =
13957 (((asc_dvc_varp->max_total_qng - 2) / 2) *
13958 ASC_SG_LIST_PER_Q) + 1;
13959 } else {
13960 shost->sg_tablesize = ADV_MAX_SG_LIST;
13961 }
13962
13963 /*
13964 * The value of 'sg_tablesize' can not exceed the SCSI
13965 * mid-level driver definition of SG_ALL. SG_ALL also
13966 * must not be exceeded, because it is used to define the
13967 * size of the scatter-gather table in 'struct asc_sg_head'.
13968 */
13969 if (shost->sg_tablesize > SG_ALL) {
13970 shost->sg_tablesize = SG_ALL;
13971 }
13972
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013973 ASC_DBG(1, "sg_tablesize: %d\n", shost->sg_tablesize);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013974
13975 /* BIOS start address. */
13976 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013977 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
13978 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013979 } else {
13980 /*
13981 * Fill-in BIOS board variables. The Wide BIOS saves
13982 * information in LRAM that is used by the driver.
13983 */
13984 AdvReadWordLram(adv_dvc_varp->iop_base,
13985 BIOS_SIGNATURE, boardp->bios_signature);
13986 AdvReadWordLram(adv_dvc_varp->iop_base,
13987 BIOS_VERSION, boardp->bios_version);
13988 AdvReadWordLram(adv_dvc_varp->iop_base,
13989 BIOS_CODESEG, boardp->bios_codeseg);
13990 AdvReadWordLram(adv_dvc_varp->iop_base,
13991 BIOS_CODELEN, boardp->bios_codelen);
13992
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013993 ASC_DBG(1, "bios_signature 0x%x, bios_version 0x%x\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013994 boardp->bios_signature, boardp->bios_version);
13995
Matthew Wilcoxb352f922007-10-02 21:55:33 -040013996 ASC_DBG(1, "bios_codeseg 0x%x, bios_codelen 0x%x\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013997 boardp->bios_codeseg, boardp->bios_codelen);
13998
13999 /*
14000 * If the BIOS saved a valid signature, then fill in
14001 * the BIOS code segment base address.
14002 */
14003 if (boardp->bios_signature == 0x55AA) {
14004 /*
14005 * Convert x86 realmode code segment to a linear
14006 * address by shifting left 4.
14007 */
14008 shost->base = ((ulong)boardp->bios_codeseg << 4);
14009 } else {
14010 shost->base = 0;
14011 }
14012 }
14013
14014 /*
14015 * Register Board Resources - I/O Port, DMA, IRQ
14016 */
14017
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014018 /* Register DMA Channel for Narrow boards. */
14019 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14020#ifdef CONFIG_ISA
14021 if (ASC_NARROW_BOARD(boardp)) {
14022 /* Register DMA channel for ISA bus. */
14023 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14024 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014025 ret = request_dma(shost->dma_channel, DRV_NAME);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014026 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014027 ASC_PRINT3
14028 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14029 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014030 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014031 }
14032 AscEnableIsaDma(shost->dma_channel);
14033 }
14034 }
14035#endif /* CONFIG_ISA */
14036
14037 /* Register IRQ Number. */
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014038 ASC_DBG(2, "request_irq(%d, %p)\n", boardp->irq, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014039
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014040 ret = request_irq(boardp->irq, advansys_interrupt, share_irq,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014041 DRV_NAME, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014042
14043 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014044 if (ret == -EBUSY) {
14045 ASC_PRINT2
14046 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014047 boardp->id, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014048 } else if (ret == -EINVAL) {
14049 ASC_PRINT2
14050 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014051 boardp->id, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014052 } else {
14053 ASC_PRINT3
14054 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014055 boardp->id, boardp->irq, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014056 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014057 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014058 }
14059
14060 /*
14061 * Initialize board RISC chip and enable interrupts.
14062 */
14063 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014064 ASC_DBG(2, "AscInitAsc1000Driver()\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014065 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014066
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014067 if (warn_code || asc_dvc_varp->err_code) {
14068 ASC_PRINT4("advansys_board_found: board %d error: "
14069 "init_state 0x%x, warn 0x%x, error 0x%x\n",
14070 boardp->id, asc_dvc_varp->init_state,
14071 warn_code, asc_dvc_varp->err_code);
14072 if (asc_dvc_varp->err_code)
14073 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014074 }
14075 } else {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014076 if (advansys_wide_init_chip(boardp, adv_dvc_varp))
14077 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014078 }
14079
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014080 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014081 goto err_free_wide_mem;
14082
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014083 ASC_DBG_PRT_SCSI_HOST(2, shost);
14084
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014085 ret = scsi_add_host(shost, boardp->dev);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014086 if (ret)
14087 goto err_free_wide_mem;
14088
14089 scsi_scan_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014090 return 0;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014091
14092 err_free_wide_mem:
14093 advansys_wide_free_mem(boardp);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014094 free_irq(boardp->irq, shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014095 err_free_dma:
14096 if (shost->dma_channel != NO_ISA_DMA)
14097 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014098 err_free_proc:
14099 kfree(boardp->prtbuf);
14100 err_unmap:
14101 if (boardp->ioremap_addr)
14102 iounmap(boardp->ioremap_addr);
14103 err_shost:
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014104 return ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014105}
14106
14107/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014108 * advansys_release()
14109 *
14110 * Release resources allocated for a single AdvanSys adapter.
14111 */
14112static int advansys_release(struct Scsi_Host *shost)
14113{
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014114 struct asc_board *boardp = shost_priv(shost);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014115 ASC_DBG(1, "begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014116 scsi_remove_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014117 free_irq(boardp->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014118 if (shost->dma_channel != NO_ISA_DMA) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014119 ASC_DBG(1, "free_dma()\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014120 free_dma(shost->dma_channel);
14121 }
Matthew Wilcox9a256fa2007-10-02 21:55:28 -040014122 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014123 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014124 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014125 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014126 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014127 scsi_host_put(shost);
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014128 ASC_DBG(1, "end\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014129 return 0;
14130}
14131
Matthew Wilcox95c9f162007-09-09 08:56:39 -060014132#define ASC_IOADR_TABLE_MAX_IX 11
14133
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014134static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
14135 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
14136 0x0210, 0x0230, 0x0250, 0x0330
14137};
14138
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014139/*
14140 * The ISA IRQ number is found in bits 2 and 3 of the CfgLsw. It decodes as:
14141 * 00: 10
14142 * 01: 11
14143 * 10: 12
14144 * 11: 15
14145 */
14146static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
14147{
14148 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14149 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
14150 if (chip_irq == 13)
14151 chip_irq = 15;
14152 return chip_irq;
14153}
14154
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014155static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
14156{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014157 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014158 PortAddr iop_base = _asc_def_iop_base[id];
14159 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014160 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014161
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014162 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014163 ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014164 return -ENODEV;
14165 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014166 ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014167 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014168 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014169 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014170 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014171
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014172 err = -ENOMEM;
14173 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014174 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014175 goto release_region;
14176
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014177 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014178 board->irq = advansys_isa_irq_no(iop_base);
14179 board->dev = dev;
14180
14181 err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
14182 if (err)
14183 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014184
14185 dev_set_drvdata(dev, shost);
14186 return 0;
14187
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014188 free_host:
14189 scsi_host_put(shost);
14190 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014191 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014192 return err;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014193}
14194
14195static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
14196{
Matthew Wilcox71f36112007-07-30 08:04:53 -060014197 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014198 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014199 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014200 return 0;
14201}
14202
14203static struct isa_driver advansys_isa_driver = {
14204 .probe = advansys_isa_probe,
14205 .remove = __devexit_p(advansys_isa_remove),
14206 .driver = {
14207 .owner = THIS_MODULE,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014208 .name = DRV_NAME,
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014209 },
14210};
14211
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014212/*
14213 * The VLB IRQ number is found in bits 2 to 4 of the CfgLsw. It decodes as:
14214 * 000: invalid
14215 * 001: 10
14216 * 010: 11
14217 * 011: 12
14218 * 100: invalid
14219 * 101: 14
14220 * 110: 15
14221 * 111: invalid
14222 */
14223static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
14224{
14225 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14226 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
14227 if ((chip_irq < 10) || (chip_irq == 13) || (chip_irq > 15))
14228 return 0;
14229 return chip_irq;
14230}
14231
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014232static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
14233{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014234 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014235 PortAddr iop_base = _asc_def_iop_base[id];
14236 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014237 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014238
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014239 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014240 ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014241 return -ENODEV;
14242 }
Matthew Wilcoxb352f922007-10-02 21:55:33 -040014243 ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014244 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014245 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014246 /*
14247 * I don't think this condition can actually happen, but the old
14248 * driver did it, and the chances of finding a VLB setup in 2007
14249 * to do testing with is slight to none.
14250 */
14251 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014252 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014253
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014254 err = -ENOMEM;
14255 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014256 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014257 goto release_region;
14258
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014259 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014260 board->irq = advansys_vlb_irq_no(iop_base);
14261 board->dev = dev;
14262
14263 err = advansys_board_found(shost, iop_base, ASC_IS_VL);
14264 if (err)
14265 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014266
14267 dev_set_drvdata(dev, shost);
14268 return 0;
14269
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014270 free_host:
14271 scsi_host_put(shost);
14272 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014273 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014274 return -ENODEV;
14275}
14276
14277static struct isa_driver advansys_vlb_driver = {
14278 .probe = advansys_vlb_probe,
14279 .remove = __devexit_p(advansys_isa_remove),
14280 .driver = {
14281 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060014282 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014283 },
14284};
14285
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014286static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
14287 { "ABP7401" },
14288 { "ABP7501" },
14289 { "" }
14290};
14291
14292MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
14293
14294/*
14295 * EISA is a little more tricky than PCI; each EISA device may have two
14296 * channels, and this driver is written to make each channel its own Scsi_Host
14297 */
14298struct eisa_scsi_data {
14299 struct Scsi_Host *host[2];
14300};
14301
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014302/*
14303 * The EISA IRQ number is found in bits 8 to 10 of the CfgLsw. It decodes as:
14304 * 000: 10
14305 * 001: 11
14306 * 010: 12
14307 * 011: invalid
14308 * 100: 14
14309 * 101: 15
14310 * 110: invalid
14311 * 111: invalid
14312 */
14313static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
14314{
14315 unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
14316 unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
14317 if ((chip_irq == 13) || (chip_irq > 15))
14318 return 0;
14319 return chip_irq;
14320}
14321
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014322static int __devinit advansys_eisa_probe(struct device *dev)
14323{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014324 int i, ioport, irq = 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014325 int err;
14326 struct eisa_device *edev = to_eisa_device(dev);
14327 struct eisa_scsi_data *data;
14328
14329 err = -ENOMEM;
14330 data = kzalloc(sizeof(*data), GFP_KERNEL);
14331 if (!data)
14332 goto fail;
14333 ioport = edev->base_addr + 0xc30;
14334
14335 err = -ENODEV;
14336 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014337 struct asc_board *board;
14338 struct Scsi_Host *shost;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014339 if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014340 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
14341 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014342 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014343 }
14344 if (!AscFindSignature(ioport)) {
14345 release_region(ioport, ASC_IOADR_GAP);
14346 continue;
14347 }
14348
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014349 /*
14350 * I don't know why we need to do this for EISA chips, but
14351 * not for any others. It looks to be equivalent to
14352 * AscGetChipCfgMsw, but I may have overlooked something,
14353 * so I'm not converting it until I get an EISA board to
14354 * test with.
14355 */
14356 inw(ioport + 4);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014357
14358 if (!irq)
14359 irq = advansys_eisa_irq_no(edev);
14360
14361 err = -ENOMEM;
14362 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
14363 if (!shost)
14364 goto release_region;
14365
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014366 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014367 board->irq = irq;
14368 board->dev = dev;
14369
14370 err = advansys_board_found(shost, ioport, ASC_IS_EISA);
14371 if (!err) {
14372 data->host[i] = shost;
14373 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014374 }
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014375
14376 scsi_host_put(shost);
14377 release_region:
14378 release_region(ioport, ASC_IOADR_GAP);
14379 break;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014380 }
14381
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014382 if (err)
14383 goto free_data;
14384 dev_set_drvdata(dev, data);
14385 return 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014386
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014387 free_data:
14388 kfree(data->host[0]);
14389 kfree(data->host[1]);
14390 kfree(data);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014391 fail:
14392 return err;
14393}
14394
14395static __devexit int advansys_eisa_remove(struct device *dev)
14396{
14397 int i;
14398 struct eisa_scsi_data *data = dev_get_drvdata(dev);
14399
14400 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014401 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014402 struct Scsi_Host *shost = data->host[i];
14403 if (!shost)
14404 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014405 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014406 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014407 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014408 }
14409
14410 kfree(data);
14411 return 0;
14412}
14413
14414static struct eisa_driver advansys_eisa_driver = {
14415 .id_table = advansys_eisa_table,
14416 .driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014417 .name = DRV_NAME,
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014418 .probe = advansys_eisa_probe,
14419 .remove = __devexit_p(advansys_eisa_remove),
14420 }
14421};
14422
Dave Jones2672ea82006-08-02 17:11:49 -040014423/* PCI Devices supported by this driver */
14424static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014425 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
14426 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14427 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
14428 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14429 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
14430 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14431 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
14432 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14433 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
14434 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14435 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
14436 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14437 {}
Dave Jones2672ea82006-08-02 17:11:49 -040014438};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014439
Dave Jones2672ea82006-08-02 17:11:49 -040014440MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014441
Matthew Wilcox9649af32007-07-26 21:51:47 -060014442static void __devinit advansys_set_latency(struct pci_dev *pdev)
14443{
14444 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
14445 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
14446 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
14447 } else {
14448 u8 latency;
14449 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
14450 if (latency < 0x20)
14451 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
14452 }
14453}
14454
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014455static int __devinit
14456advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14457{
14458 int err, ioport;
14459 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014460 struct asc_board *board;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014461
14462 err = pci_enable_device(pdev);
14463 if (err)
14464 goto fail;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014465 err = pci_request_regions(pdev, DRV_NAME);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014466 if (err)
14467 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060014468 pci_set_master(pdev);
14469 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014470
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014471 err = -ENODEV;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014472 if (pci_resource_len(pdev, 0) == 0)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014473 goto release_region;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014474
14475 ioport = pci_resource_start(pdev, 0);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014476
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014477 err = -ENOMEM;
14478 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014479 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014480 goto release_region;
14481
Matthew Wilcoxd2411492007-10-02 21:55:31 -040014482 board = shost_priv(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014483 board->irq = pdev->irq;
14484 board->dev = &pdev->dev;
14485
14486 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14487 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14488 pdev->device == PCI_DEVICE_ID_38C1600_REV1) {
14489 board->flags |= ASC_IS_WIDE_BOARD;
14490 }
14491
14492 err = advansys_board_found(shost, ioport, ASC_IS_PCI);
14493 if (err)
14494 goto free_host;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014495
14496 pci_set_drvdata(pdev, shost);
14497 return 0;
14498
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014499 free_host:
14500 scsi_host_put(shost);
14501 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014502 pci_release_regions(pdev);
14503 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014504 pci_disable_device(pdev);
14505 fail:
14506 return err;
14507}
14508
14509static void __devexit advansys_pci_remove(struct pci_dev *pdev)
14510{
14511 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014512 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014513 pci_disable_device(pdev);
14514}
14515
14516static struct pci_driver advansys_pci_driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014517 .name = DRV_NAME,
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014518 .id_table = advansys_pci_tbl,
14519 .probe = advansys_pci_probe,
14520 .remove = __devexit_p(advansys_pci_remove),
14521};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014522
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014523static int __init advansys_init(void)
14524{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014525 int error;
14526
14527 error = isa_register_driver(&advansys_isa_driver,
14528 ASC_IOADR_TABLE_MAX_IX);
14529 if (error)
14530 goto fail;
14531
14532 error = isa_register_driver(&advansys_vlb_driver,
14533 ASC_IOADR_TABLE_MAX_IX);
14534 if (error)
14535 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014536
14537 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014538 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014539 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014540
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014541 error = pci_register_driver(&advansys_pci_driver);
14542 if (error)
14543 goto unregister_eisa;
14544
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014545 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014546
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014547 unregister_eisa:
14548 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014549 unregister_vlb:
14550 isa_unregister_driver(&advansys_vlb_driver);
14551 unregister_isa:
14552 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014553 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014554 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014555}
14556
14557static void __exit advansys_exit(void)
14558{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014559 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014560 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014561 isa_unregister_driver(&advansys_vlb_driver);
14562 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014563}
14564
14565module_init(advansys_init);
14566module_exit(advansys_exit);
14567
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014568MODULE_LICENSE("GPL");