blob: 0f309e80aaad1c9f80ed57a238fccef81f185d9d [file] [log] [blame]
Matthew Wilcox01fbfe02007-09-09 08:56:40 -06001#define DRV_NAME "advansys"
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04002#define ASC_VERSION "3.4" /* AdvanSys Driver Version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003
4/*
5 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
6 *
7 * Copyright (c) 1995-2000 Advanced System Products, Inc.
8 * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04009 * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * All Rights Reserved.
11 *
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
20 * changed its name to ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040021 * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/string.h>
26#include <linux/kernel.h>
27#include <linux/types.h>
28#include <linux/ioport.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <linux/slab.h>
32#include <linux/mm.h>
33#include <linux/proc_fs.h>
34#include <linux/init.h>
35#include <linux/blkdev.h>
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060036#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060037#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040038#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/spinlock.h>
40#include <linux/dma-mapping.h>
41
42#include <asm/io.h>
43#include <asm/system.h>
44#include <asm/dma.h>
45
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040046#include <scsi/scsi_cmnd.h>
47#include <scsi/scsi_device.h>
48#include <scsi/scsi_tcq.h>
49#include <scsi/scsi.h>
50#include <scsi/scsi_host.h>
51
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060052/* FIXME:
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 *
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060054 * 1. Although all of the necessary command mapping places have the
55 * appropriate dma_map.. APIs, the driver still processes its internal
56 * queue using bus_to_virt() and virt_to_bus() which are illegal under
57 * the API. The entire queue processing structure will need to be
58 * altered to fix this.
59 * 2. Need to add memory mapping workaround. Test the memory mapping.
60 * If it doesn't work revert to I/O port access. Can a test be done
61 * safely?
62 * 3. Handle an interrupt not working. Keep an interrupt counter in
63 * the interrupt handler. In the timeout function if the interrupt
64 * has not occurred then print a message and run in polled mode.
65 * 4. Need to add support for target mode commands, cf. CAM XPT.
66 * 5. check DMA mapping functions for failure
Matthew Wilcox349d2c42007-09-09 08:56:34 -060067 * 6. Use scsi_transport_spi
68 * 7. advansys_info is not safe against multiple simultaneous callers
69 * 8. Kill boardp->id
70 * 9. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 */
72#warning this driver is still not properly converted to the DMA API
73
Linus Torvalds1da177e2005-04-16 15:20:36 -070074/* Enable driver /proc statistics. */
75#define ADVANSYS_STATS
76
77/* Enable driver tracing. */
78/* #define ADVANSYS_DEBUG */
79
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#define ASC_LIB_VERSION_MAJOR 1
81#define ASC_LIB_VERSION_MINOR 24
82#define ASC_LIB_SERIAL_NUMBER 123
83
84/*
85 * Portable Data Types
86 *
87 * Any instance where a 32-bit long or pointer type is assumed
88 * for precision or HW defined structures, the following define
89 * types must be used. In Linux the char, short, and int types
90 * are all consistent at 8, 16, and 32 bits respectively. Pointers
91 * and long types are 64 bits on Alpha and UltraSPARC.
92 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040093#define ASC_PADDR __u32 /* Physical/Bus address data type. */
94#define ASC_VADDR __u32 /* Virtual address data type. */
95#define ASC_DCNT __u32 /* Unsigned Data count type. */
96#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
98/*
99 * These macros are used to convert a virtual address to a
100 * 32-bit value. This currently can be used on Linux Alpha
101 * which uses 64-bit virtual address but a 32-bit bus address.
102 * This is likely to break in the future, but doing this now
103 * will give us time to change the HW and FW to handle 64-bit
104 * addresses.
105 */
106#define ASC_VADDR_TO_U32 virt_to_bus
107#define ASC_U32_TO_VADDR bus_to_virt
108
109typedef unsigned char uchar;
110
111#ifndef TRUE
112#define TRUE (1)
113#endif
114#ifndef FALSE
115#define FALSE (0)
116#endif
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118#define ERR (-1)
119#define UW_ERR (uint)(0xFFFF)
120#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Dave Jones2672ea82006-08-02 17:11:49 -0400122#define PCI_VENDOR_ID_ASP 0x10cd
123#define PCI_DEVICE_ID_ASP_1200A 0x1100
124#define PCI_DEVICE_ID_ASP_ABP940 0x1200
125#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
126#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
127#define PCI_DEVICE_ID_38C0800_REV1 0x2500
128#define PCI_DEVICE_ID_38C1600_REV1 0x2700
129
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130/*
131 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
132 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
133 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
134 * SRB structure.
135 */
136#define CC_VERY_LONG_SG_LIST 0
137#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
138
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400139#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140#define inp(port) inb(port)
141#define outp(port, byte) outb((byte), (port))
142
143#define inpw(port) inw(port)
144#define outpw(port, word) outw((word), (port))
145
146#define ASC_MAX_SG_QUEUE 7
147#define ASC_MAX_SG_LIST 255
148
149#define ASC_CS_TYPE unsigned short
150
151#define ASC_IS_ISA (0x0001)
152#define ASC_IS_ISAPNP (0x0081)
153#define ASC_IS_EISA (0x0002)
154#define ASC_IS_PCI (0x0004)
155#define ASC_IS_PCI_ULTRA (0x0104)
156#define ASC_IS_PCMCIA (0x0008)
157#define ASC_IS_MCA (0x0020)
158#define ASC_IS_VL (0x0040)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159#define ASC_IS_WIDESCSI_16 (0x0100)
160#define ASC_IS_WIDESCSI_32 (0x0200)
161#define ASC_IS_BIG_ENDIAN (0x8000)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163#define ASC_CHIP_MIN_VER_VL (0x01)
164#define ASC_CHIP_MAX_VER_VL (0x07)
165#define ASC_CHIP_MIN_VER_PCI (0x09)
166#define ASC_CHIP_MAX_VER_PCI (0x0F)
167#define ASC_CHIP_VER_PCI_BIT (0x08)
168#define ASC_CHIP_MIN_VER_ISA (0x11)
169#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
170#define ASC_CHIP_MAX_VER_ISA (0x27)
171#define ASC_CHIP_VER_ISA_BIT (0x30)
172#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
173#define ASC_CHIP_VER_ASYN_BUG (0x21)
174#define ASC_CHIP_VER_PCI 0x08
175#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
176#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
177#define ASC_CHIP_MIN_VER_EISA (0x41)
178#define ASC_CHIP_MAX_VER_EISA (0x47)
179#define ASC_CHIP_VER_EISA_BIT (0x40)
180#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
185#define ASC_SCSI_ID_BITS 3
186#define ASC_SCSI_TIX_TYPE uchar
187#define ASC_ALL_DEVICE_BIT_SET 0xFF
188#define ASC_SCSI_BIT_ID_TYPE uchar
189#define ASC_MAX_TID 7
190#define ASC_MAX_LUN 7
191#define ASC_SCSI_WIDTH_BIT_SET 0xFF
192#define ASC_MAX_SENSE_LEN 32
193#define ASC_MIN_SENSE_LEN 14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#define ASC_SCSI_RESET_HOLD_TIME_US 60
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196/*
Matthew Wilcoxf05ec592007-09-09 08:56:36 -0600197 * Narrow boards only support 12-byte commands, while wide boards
198 * extend to 16-byte commands.
199 */
200#define ASC_MAX_CDB_LEN 12
201#define ADV_MAX_CDB_LEN 16
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
206#define ASC_SG_LIST_PER_Q 7
207#define QS_FREE 0x00
208#define QS_READY 0x01
209#define QS_DISC1 0x02
210#define QS_DISC2 0x04
211#define QS_BUSY 0x08
212#define QS_ABORTED 0x40
213#define QS_DONE 0x80
214#define QC_NO_CALLBACK 0x01
215#define QC_SG_SWAP_QUEUE 0x02
216#define QC_SG_HEAD 0x04
217#define QC_DATA_IN 0x08
218#define QC_DATA_OUT 0x10
219#define QC_URGENT 0x20
220#define QC_MSG_OUT 0x40
221#define QC_REQ_SENSE 0x80
222#define QCSG_SG_XFER_LIST 0x02
223#define QCSG_SG_XFER_MORE 0x04
224#define QCSG_SG_XFER_END 0x08
225#define QD_IN_PROGRESS 0x00
226#define QD_NO_ERROR 0x01
227#define QD_ABORTED_BY_HOST 0x02
228#define QD_WITH_ERROR 0x04
229#define QD_INVALID_REQUEST 0x80
230#define QD_INVALID_HOST_NUM 0x81
231#define QD_INVALID_DEVICE 0x82
232#define QD_ERR_INTERNAL 0xFF
233#define QHSTA_NO_ERROR 0x00
234#define QHSTA_M_SEL_TIMEOUT 0x11
235#define QHSTA_M_DATA_OVER_RUN 0x12
236#define QHSTA_M_DATA_UNDER_RUN 0x12
237#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
238#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
239#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
240#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
241#define QHSTA_D_HOST_ABORT_FAILED 0x23
242#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
243#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
244#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
245#define QHSTA_M_WTM_TIMEOUT 0x41
246#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
247#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
248#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
249#define QHSTA_M_TARGET_STATUS_BUSY 0x45
250#define QHSTA_M_BAD_TAG_CODE 0x46
251#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
252#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
253#define QHSTA_D_LRAM_CMP_ERROR 0x81
254#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
255#define ASC_FLAG_SCSIQ_REQ 0x01
256#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
257#define ASC_FLAG_BIOS_ASYNC_IO 0x04
258#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
259#define ASC_FLAG_WIN16 0x10
260#define ASC_FLAG_WIN32 0x20
261#define ASC_FLAG_ISA_OVER_16MB 0x40
262#define ASC_FLAG_DOS_VM_CALLBACK 0x80
263#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
264#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
265#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
266#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
267#define ASC_SCSIQ_CPY_BEG 4
268#define ASC_SCSIQ_SGHD_CPY_BEG 2
269#define ASC_SCSIQ_B_FWD 0
270#define ASC_SCSIQ_B_BWD 1
271#define ASC_SCSIQ_B_STATUS 2
272#define ASC_SCSIQ_B_QNO 3
273#define ASC_SCSIQ_B_CNTL 4
274#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
275#define ASC_SCSIQ_D_DATA_ADDR 8
276#define ASC_SCSIQ_D_DATA_CNT 12
277#define ASC_SCSIQ_B_SENSE_LEN 20
278#define ASC_SCSIQ_DONE_INFO_BEG 22
279#define ASC_SCSIQ_D_SRBPTR 22
280#define ASC_SCSIQ_B_TARGET_IX 26
281#define ASC_SCSIQ_B_CDB_LEN 28
282#define ASC_SCSIQ_B_TAG_CODE 29
283#define ASC_SCSIQ_W_VM_ID 30
284#define ASC_SCSIQ_DONE_STATUS 32
285#define ASC_SCSIQ_HOST_STATUS 33
286#define ASC_SCSIQ_SCSI_STATUS 34
287#define ASC_SCSIQ_CDB_BEG 36
288#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
289#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
290#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
291#define ASC_SCSIQ_B_SG_WK_QP 49
292#define ASC_SCSIQ_B_SG_WK_IX 50
293#define ASC_SCSIQ_W_ALT_DC1 52
294#define ASC_SCSIQ_B_LIST_CNT 6
295#define ASC_SCSIQ_B_CUR_LIST_CNT 7
296#define ASC_SGQ_B_SG_CNTL 4
297#define ASC_SGQ_B_SG_HEAD_QP 5
298#define ASC_SGQ_B_SG_LIST_CNT 6
299#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
300#define ASC_SGQ_LIST_BEG 8
301#define ASC_DEF_SCSI1_QNG 4
302#define ASC_MAX_SCSI1_QNG 4
303#define ASC_DEF_SCSI2_QNG 16
304#define ASC_MAX_SCSI2_QNG 32
305#define ASC_TAG_CODE_MASK 0x23
306#define ASC_STOP_REQ_RISC_STOP 0x01
307#define ASC_STOP_ACK_RISC_STOP 0x03
308#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
309#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
310#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
311#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
312#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
313#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
314#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
315#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
316#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
317#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
318
319typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400320 uchar status;
321 uchar q_no;
322 uchar cntl;
323 uchar sg_queue_cnt;
324 uchar target_id;
325 uchar target_lun;
326 ASC_PADDR data_addr;
327 ASC_DCNT data_cnt;
328 ASC_PADDR sense_addr;
329 uchar sense_len;
330 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331} ASC_SCSIQ_1;
332
333typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400334 ASC_VADDR srb_ptr;
335 uchar target_ix;
336 uchar flag;
337 uchar cdb_len;
338 uchar tag_code;
339 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340} ASC_SCSIQ_2;
341
342typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400343 uchar done_stat;
344 uchar host_stat;
345 uchar scsi_stat;
346 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347} ASC_SCSIQ_3;
348
349typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400350 uchar cdb[ASC_MAX_CDB_LEN];
351 uchar y_first_sg_list_qp;
352 uchar y_working_sg_qp;
353 uchar y_working_sg_ix;
354 uchar y_res;
355 ushort x_req_count;
356 ushort x_reconnect_rtn;
357 ASC_PADDR x_saved_data_addr;
358 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359} ASC_SCSIQ_4;
360
361typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400362 ASC_SCSIQ_2 d2;
363 ASC_SCSIQ_3 d3;
364 uchar q_status;
365 uchar q_no;
366 uchar cntl;
367 uchar sense_len;
368 uchar extra_bytes;
369 uchar res;
370 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371} ASC_QDONE_INFO;
372
373typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400374 ASC_PADDR addr;
375 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376} ASC_SG_LIST;
377
378typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400379 ushort entry_cnt;
380 ushort queue_cnt;
381 ushort entry_to_copy;
382 ushort res;
Matthew Wilcox05848b62007-10-02 21:55:25 -0400383 ASC_SG_LIST sg_list[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384} ASC_SG_HEAD;
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400387 ASC_SCSIQ_1 q1;
388 ASC_SCSIQ_2 q2;
389 uchar *cdbptr;
390 ASC_SG_HEAD *sg_head;
391 ushort remain_sg_entry_cnt;
392 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393} ASC_SCSI_Q;
394
395typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400396 ASC_SCSIQ_1 r1;
397 ASC_SCSIQ_2 r2;
398 uchar *cdbptr;
399 ASC_SG_HEAD *sg_head;
400 uchar *sense_ptr;
401 ASC_SCSIQ_3 r3;
402 uchar cdb[ASC_MAX_CDB_LEN];
403 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404} ASC_SCSI_REQ_Q;
405
406typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400407 ASC_SCSIQ_1 r1;
408 ASC_SCSIQ_2 r2;
409 uchar *cdbptr;
410 ASC_SG_HEAD *sg_head;
411 uchar *sense_ptr;
412 ASC_SCSIQ_3 r3;
413 uchar cdb[ASC_MAX_CDB_LEN];
414 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415} ASC_SCSI_BIOS_REQ_Q;
416
417typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400418 uchar fwd;
419 uchar bwd;
420 ASC_SCSIQ_1 i1;
421 ASC_SCSIQ_2 i2;
422 ASC_SCSIQ_3 i3;
423 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424} ASC_RISC_Q;
425
426typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400427 uchar seq_no;
428 uchar q_no;
429 uchar cntl;
430 uchar sg_head_qp;
431 uchar sg_list_cnt;
432 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433} ASC_SG_LIST_Q;
434
435typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400436 uchar fwd;
437 uchar bwd;
438 ASC_SG_LIST_Q sg;
439 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440} ASC_RISC_SG_LIST_Q;
441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442#define ASCQ_ERR_Q_STATUS 0x0D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443#define ASCQ_ERR_CUR_QNG 0x17
444#define ASCQ_ERR_SG_Q_LINKS 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
446#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
447#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449/*
450 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
451 */
452#define ASC_WARN_NO_ERROR 0x0000
453#define ASC_WARN_IO_PORT_ROTATE 0x0001
454#define ASC_WARN_EEPROM_CHKSUM 0x0002
455#define ASC_WARN_IRQ_MODIFIED 0x0004
456#define ASC_WARN_AUTO_CONFIG 0x0008
457#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
458#define ASC_WARN_EEPROM_RECOVER 0x0020
459#define ASC_WARN_CFG_MSW_RECOVER 0x0040
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461/*
Matthew Wilcox720349a2007-10-02 21:55:30 -0400462 * Error code values are set in {ASC/ADV}_DVC_VAR 'err_code'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 */
Matthew Wilcox720349a2007-10-02 21:55:30 -0400464#define ASC_IERR_NO_CARRIER 0x0001 /* No more carrier memory */
465#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
466#define ASC_IERR_SET_PC_ADDR 0x0004
467#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
468#define ASC_IERR_ILLEGAL_CONNECTION 0x0010 /* Illegal cable connection */
469#define ASC_IERR_SINGLE_END_DEVICE 0x0020 /* SE device on DIFF bus */
470#define ASC_IERR_REVERSED_CABLE 0x0040 /* Narrow flat cable reversed */
471#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
472#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD device on LVD port */
473#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
474#define ASC_IERR_NO_BUS_TYPE 0x0400
475#define ASC_IERR_BIST_PRE_TEST 0x0800 /* BIST pre-test error */
476#define ASC_IERR_BIST_RAM_TEST 0x1000 /* BIST RAM test error */
477#define ASC_IERR_BAD_CHIPTYPE 0x2000 /* Invalid chip_type setting */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
480#define ASC_MIN_TAG_Q_PER_DVC (0x04)
Matthew Wilcox95c9f162007-09-09 08:56:39 -0600481#define ASC_MIN_FREE_Q (0x02)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
483#define ASC_MAX_TOTAL_QNG 240
484#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
485#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
486#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
487#define ASC_MAX_INRAM_TAG_QNG 16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489#define ASC_MAX_SYN_XFER_NO 16
490#define ASC_SYN_MAX_OFFSET 0x0F
491#define ASC_DEF_SDTR_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
493#define SYN_XFER_NS_0 25
494#define SYN_XFER_NS_1 30
495#define SYN_XFER_NS_2 35
496#define SYN_XFER_NS_3 40
497#define SYN_XFER_NS_4 50
498#define SYN_XFER_NS_5 60
499#define SYN_XFER_NS_6 70
500#define SYN_XFER_NS_7 85
501#define SYN_ULTRA_XFER_NS_0 12
502#define SYN_ULTRA_XFER_NS_1 19
503#define SYN_ULTRA_XFER_NS_2 25
504#define SYN_ULTRA_XFER_NS_3 32
505#define SYN_ULTRA_XFER_NS_4 38
506#define SYN_ULTRA_XFER_NS_5 44
507#define SYN_ULTRA_XFER_NS_6 50
508#define SYN_ULTRA_XFER_NS_7 57
509#define SYN_ULTRA_XFER_NS_8 63
510#define SYN_ULTRA_XFER_NS_9 69
511#define SYN_ULTRA_XFER_NS_10 75
512#define SYN_ULTRA_XFER_NS_11 82
513#define SYN_ULTRA_XFER_NS_12 88
514#define SYN_ULTRA_XFER_NS_13 94
515#define SYN_ULTRA_XFER_NS_14 100
516#define SYN_ULTRA_XFER_NS_15 107
517
518typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400519 uchar msg_type;
520 uchar msg_len;
521 uchar msg_req;
522 union {
523 struct {
524 uchar sdtr_xfer_period;
525 uchar sdtr_req_ack_offset;
526 } sdtr;
527 struct {
528 uchar wdtr_width;
529 } wdtr;
530 struct {
531 uchar mdp_b3;
532 uchar mdp_b2;
533 uchar mdp_b1;
534 uchar mdp_b0;
535 } mdp;
536 } u_ext_msg;
537 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538} EXT_MSG;
539
540#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
541#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
542#define wdtr_width u_ext_msg.wdtr.wdtr_width
543#define mdp_b3 u_ext_msg.mdp_b3
544#define mdp_b2 u_ext_msg.mdp_b2
545#define mdp_b1 u_ext_msg.mdp_b1
546#define mdp_b0 u_ext_msg.mdp_b0
547
548typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400549 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
550 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
551 ASC_SCSI_BIT_ID_TYPE disc_enable;
552 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
553 uchar chip_scsi_id;
554 uchar isa_dma_speed;
555 uchar isa_dma_channel;
556 uchar chip_version;
557 ushort lib_serial_no;
558 ushort lib_version;
559 ushort mcode_date;
560 ushort mcode_version;
561 uchar max_tag_qng[ASC_MAX_TID + 1];
562 uchar *overrun_buf;
563 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400564 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565} ASC_DVC_CFG;
566
567#define ASC_DEF_DVC_CNTL 0xFFFF
568#define ASC_DEF_CHIP_SCSI_ID 7
569#define ASC_DEF_ISA_DMA_SPEED 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
571#define ASC_INIT_STATE_END_GET_CFG 0x0002
572#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
573#define ASC_INIT_STATE_END_SET_CFG 0x0008
574#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
575#define ASC_INIT_STATE_END_LOAD_MC 0x0020
576#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
577#define ASC_INIT_STATE_END_INQUIRY 0x0080
578#define ASC_INIT_RESET_SCSI_DONE 0x0100
579#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
581#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
582#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
583#define ASC_MIN_TAGGED_CMD 7
584#define ASC_MAX_SCSI_RESET_WAIT 30
585
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400586struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400589 PortAddr iop_base;
590 ushort err_code;
591 ushort dvc_cntl;
592 ushort bug_fix_cntl;
593 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400594 ASC_SCSI_BIT_ID_TYPE init_sdtr;
595 ASC_SCSI_BIT_ID_TYPE sdtr_done;
596 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
597 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
598 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
599 ASC_SCSI_BIT_ID_TYPE start_motor;
600 uchar scsi_reset_wait;
601 uchar chip_no;
602 char is_in_int;
603 uchar max_total_qng;
604 uchar cur_total_qng;
605 uchar in_critical_cnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400606 uchar last_q_shortage;
607 ushort init_state;
608 uchar cur_dvc_qng[ASC_MAX_TID + 1];
609 uchar max_dvc_qng[ASC_MAX_TID + 1];
610 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
611 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
612 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
613 ASC_DVC_CFG *cfg;
614 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
615 char redo_scam;
616 ushort res2;
617 uchar dos_int13_table[ASC_MAX_TID + 1];
618 ASC_DCNT max_dma_count;
619 ASC_SCSI_BIT_ID_TYPE no_scam;
620 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
621 uchar max_sdtr_index;
622 uchar host_init_sdtr_index;
623 struct asc_board *drv_ptr;
624 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625} ASC_DVC_VAR;
626
627typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400628 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629} ASC_DVC_INQ_INFO;
630
631typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400632 ASC_DCNT lba;
633 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634} ASC_CAP_INFO;
635
636typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400637 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638} ASC_CAP_INFO_ARRAY;
639
640#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
641#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
642#define ASC_CNTL_INITIATOR (ushort)0x0001
643#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
644#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
645#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
646#define ASC_CNTL_NO_SCAM (ushort)0x0010
647#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
648#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
649#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
650#define ASC_CNTL_RESET_SCSI (ushort)0x0200
651#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
652#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
653#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
654#define ASC_CNTL_BURST_MODE (ushort)0x2000
655#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
656#define ASC_EEP_DVC_CFG_BEG_VL 2
657#define ASC_EEP_MAX_DVC_ADDR_VL 15
658#define ASC_EEP_DVC_CFG_BEG 32
659#define ASC_EEP_MAX_DVC_ADDR 45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660#define ASC_EEP_MAX_RETRY 20
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
662/*
663 * These macros keep the chip SCSI id and ISA DMA speed
664 * bitfields in board order. C bitfields aren't portable
665 * between big and little-endian platforms so they are
666 * not used.
667 */
668
669#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
670#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
671#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
672 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
673#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
674 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
675
676typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400677 ushort cfg_lsw;
678 ushort cfg_msw;
679 uchar init_sdtr;
680 uchar disc_enable;
681 uchar use_cmd_qng;
682 uchar start_motor;
683 uchar max_total_qng;
684 uchar max_tag_qng;
685 uchar bios_scan;
686 uchar power_up_wait;
687 uchar no_scam;
688 uchar id_speed; /* low order 4 bits is chip scsi id */
689 /* high order 4 bits is isa dma speed */
690 uchar dos_int13_table[ASC_MAX_TID + 1];
691 uchar adapter_info[6];
692 ushort cntl;
693 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694} ASCEEP_CONFIG;
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696#define ASC_EEP_CMD_READ 0x80
697#define ASC_EEP_CMD_WRITE 0x40
698#define ASC_EEP_CMD_WRITE_ABLE 0x30
699#define ASC_EEP_CMD_WRITE_DISABLE 0x00
700#define ASC_OVERRUN_BSIZE 0x00000048UL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701#define ASCV_MSGOUT_BEG 0x0000
702#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
703#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
704#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
705#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
706#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
707#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
708#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
709#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
710#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
711#define ASCV_BREAK_ADDR (ushort)0x0028
712#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
713#define ASCV_BREAK_CONTROL (ushort)0x002C
714#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
715
716#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
717#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
718#define ASCV_MCODE_SIZE_W (ushort)0x0034
719#define ASCV_STOP_CODE_B (ushort)0x0036
720#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
721#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
722#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
723#define ASCV_HALTCODE_W (ushort)0x0040
724#define ASCV_CHKSUM_W (ushort)0x0042
725#define ASCV_MC_DATE_W (ushort)0x0044
726#define ASCV_MC_VER_W (ushort)0x0046
727#define ASCV_NEXTRDY_B (ushort)0x0048
728#define ASCV_DONENEXT_B (ushort)0x0049
729#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
730#define ASCV_SCSIBUSY_B (ushort)0x004B
731#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
732#define ASCV_CURCDB_B (ushort)0x004D
733#define ASCV_RCLUN_B (ushort)0x004E
734#define ASCV_BUSY_QHEAD_B (ushort)0x004F
735#define ASCV_DISC1_QHEAD_B (ushort)0x0050
736#define ASCV_DISC_ENABLE_B (ushort)0x0052
737#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
738#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
739#define ASCV_MCODE_CNTL_B (ushort)0x0056
740#define ASCV_NULL_TARGET_B (ushort)0x0057
741#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
742#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
743#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
744#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
745#define ASCV_HOST_FLAG_B (ushort)0x005D
746#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
747#define ASCV_VER_SERIAL_B (ushort)0x0065
748#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
749#define ASCV_WTM_FLAG_B (ushort)0x0068
750#define ASCV_RISC_FLAG_B (ushort)0x006A
751#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
752#define ASC_HOST_FLAG_IN_ISR 0x01
753#define ASC_HOST_FLAG_ACK_INT 0x02
754#define ASC_RISC_FLAG_GEN_INT 0x01
755#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
756#define IOP_CTRL (0x0F)
757#define IOP_STATUS (0x0E)
758#define IOP_INT_ACK IOP_STATUS
759#define IOP_REG_IFC (0x0D)
760#define IOP_SYN_OFFSET (0x0B)
761#define IOP_EXTRA_CONTROL (0x0D)
762#define IOP_REG_PC (0x0C)
763#define IOP_RAM_ADDR (0x0A)
764#define IOP_RAM_DATA (0x08)
765#define IOP_EEP_DATA (0x06)
766#define IOP_EEP_CMD (0x07)
767#define IOP_VERSION (0x03)
768#define IOP_CONFIG_HIGH (0x04)
769#define IOP_CONFIG_LOW (0x02)
770#define IOP_SIG_BYTE (0x01)
771#define IOP_SIG_WORD (0x00)
772#define IOP_REG_DC1 (0x0E)
773#define IOP_REG_DC0 (0x0C)
774#define IOP_REG_SB (0x0B)
775#define IOP_REG_DA1 (0x0A)
776#define IOP_REG_DA0 (0x08)
777#define IOP_REG_SC (0x09)
778#define IOP_DMA_SPEED (0x07)
779#define IOP_REG_FLAG (0x07)
780#define IOP_FIFO_H (0x06)
781#define IOP_FIFO_L (0x04)
782#define IOP_REG_ID (0x05)
783#define IOP_REG_QP (0x03)
784#define IOP_REG_IH (0x02)
785#define IOP_REG_IX (0x01)
786#define IOP_REG_AX (0x00)
787#define IFC_REG_LOCK (0x00)
788#define IFC_REG_UNLOCK (0x09)
789#define IFC_WR_EN_FILTER (0x10)
790#define IFC_RD_NO_EEPROM (0x10)
791#define IFC_SLEW_RATE (0x20)
792#define IFC_ACT_NEG (0x40)
793#define IFC_INP_FILTER (0x80)
794#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
795#define SC_SEL (uchar)(0x80)
796#define SC_BSY (uchar)(0x40)
797#define SC_ACK (uchar)(0x20)
798#define SC_REQ (uchar)(0x10)
799#define SC_ATN (uchar)(0x08)
800#define SC_IO (uchar)(0x04)
801#define SC_CD (uchar)(0x02)
802#define SC_MSG (uchar)(0x01)
803#define SEC_SCSI_CTL (uchar)(0x80)
804#define SEC_ACTIVE_NEGATE (uchar)(0x40)
805#define SEC_SLEW_RATE (uchar)(0x20)
806#define SEC_ENABLE_FILTER (uchar)(0x10)
807#define ASC_HALT_EXTMSG_IN (ushort)0x8000
808#define ASC_HALT_CHK_CONDITION (ushort)0x8100
809#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
810#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
811#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
812#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
813#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
814#define ASC_MAX_QNO 0xF8
815#define ASC_DATA_SEC_BEG (ushort)0x0080
816#define ASC_DATA_SEC_END (ushort)0x0080
817#define ASC_CODE_SEC_BEG (ushort)0x0080
818#define ASC_CODE_SEC_END (ushort)0x0080
819#define ASC_QADR_BEG (0x4000)
820#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
821#define ASC_QADR_END (ushort)0x7FFF
822#define ASC_QLAST_ADR (ushort)0x7FC0
823#define ASC_QBLK_SIZE 0x40
824#define ASC_BIOS_DATA_QBEG 0xF8
825#define ASC_MIN_ACTIVE_QNO 0x01
826#define ASC_QLINK_END 0xFF
827#define ASC_EEPROM_WORDS 0x10
828#define ASC_MAX_MGS_LEN 0x10
829#define ASC_BIOS_ADDR_DEF 0xDC00
830#define ASC_BIOS_SIZE 0x3800
831#define ASC_BIOS_RAM_OFF 0x3800
832#define ASC_BIOS_RAM_SIZE 0x800
833#define ASC_BIOS_MIN_ADDR 0xC000
834#define ASC_BIOS_MAX_ADDR 0xEC00
835#define ASC_BIOS_BANK_SIZE 0x0400
836#define ASC_MCODE_START_ADDR 0x0080
837#define ASC_CFG0_HOST_INT_ON 0x0020
838#define ASC_CFG0_BIOS_ON 0x0040
839#define ASC_CFG0_VERA_BURST_ON 0x0080
840#define ASC_CFG0_SCSI_PARITY_ON 0x0800
841#define ASC_CFG1_SCSI_TARGET_ON 0x0080
842#define ASC_CFG1_LRAM_8BITS_ON 0x0800
843#define ASC_CFG_MSW_CLR_MASK 0x3080
844#define CSW_TEST1 (ASC_CS_TYPE)0x8000
845#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
846#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
847#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
848#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
849#define CSW_TEST2 (ASC_CS_TYPE)0x0400
850#define CSW_TEST3 (ASC_CS_TYPE)0x0200
851#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
852#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
853#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
854#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
855#define CSW_HALTED (ASC_CS_TYPE)0x0010
856#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
857#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
858#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
859#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
860#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
861#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
862#define CIW_TEST1 (ASC_CS_TYPE)0x0200
863#define CIW_TEST2 (ASC_CS_TYPE)0x0400
864#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
865#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
866#define CC_CHIP_RESET (uchar)0x80
867#define CC_SCSI_RESET (uchar)0x40
868#define CC_HALT (uchar)0x20
869#define CC_SINGLE_STEP (uchar)0x10
870#define CC_DMA_ABLE (uchar)0x08
871#define CC_TEST (uchar)0x04
872#define CC_BANK_ONE (uchar)0x02
873#define CC_DIAG (uchar)0x01
874#define ASC_1000_ID0W 0x04C1
875#define ASC_1000_ID0W_FIX 0x00C1
876#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877#define ASC_EISA_REV_IOP_MASK (0x0C83)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878#define ASC_EISA_CFG_IOP_MASK (0x0C86)
879#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880#define INS_HALTINT (ushort)0x6281
881#define INS_HALT (ushort)0x6280
882#define INS_SINT (ushort)0x6200
883#define INS_RFLAG_WTM (ushort)0x7380
884#define ASC_MC_SAVE_CODE_WSIZE 0x500
885#define ASC_MC_SAVE_DATA_WSIZE 0x40
886
887typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400888 ushort data[ASC_MC_SAVE_DATA_WSIZE];
889 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890} ASC_MC_SAVED;
891
892#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
893#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
894#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
895#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
896#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
897#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
898#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
899#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
900#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
901#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
Matthew Wilcox51219352007-10-02 21:55:22 -0400902#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data))
903#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id))
904#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data)
905#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
907#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
908#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
909#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
910#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
911#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
912#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
913#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
914#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
915#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
916#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
917#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
918#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
919#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
920#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
921#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
922#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
923#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
924#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
925#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
926#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
927#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
928#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
929#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
930#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
931#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
932#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
933#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
934#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
935#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
936#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
937#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
938#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
939#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
940#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
941#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
942#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
943#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
944#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
945#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
946#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
947#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
948#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
949#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
950#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
951#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
952#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
953#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
954#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
955#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
956#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
957#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
958#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
959#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
960
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961#define ADV_LIB_VERSION_MAJOR 5
962#define ADV_LIB_VERSION_MINOR 14
963
964/*
965 * Define Adv Library required special types.
966 */
967
968/*
969 * Portable Data Types
970 *
971 * Any instance where a 32-bit long or pointer type is assumed
972 * for precision or HW defined structures, the following define
973 * types must be used. In Linux the char, short, and int types
974 * are all consistent at 8, 16, and 32 bits respectively. Pointers
975 * and long types are 64 bits on Alpha and UltraSPARC.
976 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400977#define ADV_PADDR __u32 /* Physical address data type. */
978#define ADV_VADDR __u32 /* Virtual address data type. */
979#define ADV_DCNT __u32 /* Unsigned Data count type. */
980#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
982/*
983 * These macros are used to convert a virtual address to a
984 * 32-bit value. This currently can be used on Linux Alpha
985 * which uses 64-bit virtual address but a 32-bit bus address.
986 * This is likely to break in the future, but doing this now
987 * will give us time to change the HW and FW to handle 64-bit
988 * addresses.
989 */
990#define ADV_VADDR_TO_U32 virt_to_bus
991#define ADV_U32_TO_VADDR bus_to_virt
992
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400993#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
995/*
996 * Define Adv Library required memory access macros.
997 */
998#define ADV_MEM_READB(addr) readb(addr)
999#define ADV_MEM_READW(addr) readw(addr)
1000#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1001#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1002#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1003
1004#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1005
1006/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 * Define total number of simultaneous maximum element scatter-gather
1008 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1009 * maximum number of outstanding commands per wide host adapter. Each
1010 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1011 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1012 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1013 * structures or 255 scatter-gather elements.
1014 *
1015 */
1016#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1017
1018/*
1019 * Define Adv Library required maximum number of scatter-gather
1020 * elements per request.
1021 */
1022#define ADV_MAX_SG_LIST 255
1023
1024/* Number of SG blocks needed. */
1025#define ADV_NUM_SG_BLOCK \
1026 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1027
1028/* Total contiguous memory needed for SG blocks. */
1029#define ADV_SG_TOTAL_MEM_SIZE \
1030 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1031
1032#define ADV_PAGE_SIZE PAGE_SIZE
1033
1034#define ADV_NUM_PAGE_CROSSING \
1035 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1036
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1038#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001039#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1041
1042#define ADV_EEP_DELAY_MS 100
1043
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001044#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1045#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046/*
1047 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1048 * For later ICs Bit 13 controls whether the CIS (Card Information
1049 * Service Section) is loaded from EEPROM.
1050 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001051#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1052#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053/*
1054 * ASC38C1600 Bit 11
1055 *
1056 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1057 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1058 * Function 0 will specify INT B.
1059 *
1060 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1061 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1062 * Function 1 will specify INT A.
1063 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001064#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001066typedef struct adveep_3550_config {
1067 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001069 ushort cfg_lsw; /* 00 power up initialization */
1070 /* bit 13 set - Term Polarity Control */
1071 /* bit 14 set - BIOS Enable */
1072 /* bit 15 set - Big Endian Mode */
1073 ushort cfg_msw; /* 01 unused */
1074 ushort disc_enable; /* 02 disconnect enable */
1075 ushort wdtr_able; /* 03 Wide DTR able */
1076 ushort sdtr_able; /* 04 Synchronous DTR able */
1077 ushort start_motor; /* 05 send start up motor */
1078 ushort tagqng_able; /* 06 tag queuing able */
1079 ushort bios_scan; /* 07 BIOS device control */
1080 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001082 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1083 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001085 uchar scsi_reset_delay; /* 10 reset delay */
1086 uchar bios_id_lun; /* first boot device scsi id & lun */
1087 /* high nibble is lun */
1088 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001090 uchar termination; /* 11 0 - automatic */
1091 /* 1 - low off / high off */
1092 /* 2 - low off / high on */
1093 /* 3 - low on / high on */
1094 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001096 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001098 ushort bios_ctrl; /* 12 BIOS control bits */
1099 /* bit 0 BIOS don't act as initiator. */
1100 /* bit 1 BIOS > 1 GB support */
1101 /* bit 2 BIOS > 2 Disk Support */
1102 /* bit 3 BIOS don't support removables */
1103 /* bit 4 BIOS support bootable CD */
1104 /* bit 5 BIOS scan enabled */
1105 /* bit 6 BIOS support multiple LUNs */
1106 /* bit 7 BIOS display of message */
1107 /* bit 8 SCAM disabled */
1108 /* bit 9 Reset SCSI bus during init. */
1109 /* bit 10 */
1110 /* bit 11 No verbose initialization. */
1111 /* bit 12 SCSI parity enabled */
1112 /* bit 13 */
1113 /* bit 14 */
1114 /* bit 15 */
1115 ushort ultra_able; /* 13 ULTRA speed able */
1116 ushort reserved2; /* 14 reserved */
1117 uchar max_host_qng; /* 15 maximum host queuing */
1118 uchar max_dvc_qng; /* maximum per device queuing */
1119 ushort dvc_cntl; /* 16 control bit for driver */
1120 ushort bug_fix; /* 17 control bit for bug fix */
1121 ushort serial_number_word1; /* 18 Board serial number word 1 */
1122 ushort serial_number_word2; /* 19 Board serial number word 2 */
1123 ushort serial_number_word3; /* 20 Board serial number word 3 */
1124 ushort check_sum; /* 21 EEP check sum */
1125 uchar oem_name[16]; /* 22 OEM name */
1126 ushort dvc_err_code; /* 30 last device driver error code */
1127 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1128 ushort adv_err_addr; /* 32 last uc error address */
1129 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1130 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1131 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1132 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133} ADVEEP_3550_CONFIG;
1134
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001135typedef struct adveep_38C0800_config {
1136 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001138 ushort cfg_lsw; /* 00 power up initialization */
1139 /* bit 13 set - Load CIS */
1140 /* bit 14 set - BIOS Enable */
1141 /* bit 15 set - Big Endian Mode */
1142 ushort cfg_msw; /* 01 unused */
1143 ushort disc_enable; /* 02 disconnect enable */
1144 ushort wdtr_able; /* 03 Wide DTR able */
1145 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1146 ushort start_motor; /* 05 send start up motor */
1147 ushort tagqng_able; /* 06 tag queuing able */
1148 ushort bios_scan; /* 07 BIOS device control */
1149 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001151 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1152 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001154 uchar scsi_reset_delay; /* 10 reset delay */
1155 uchar bios_id_lun; /* first boot device scsi id & lun */
1156 /* high nibble is lun */
1157 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001159 uchar termination_se; /* 11 0 - automatic */
1160 /* 1 - low off / high off */
1161 /* 2 - low off / high on */
1162 /* 3 - low on / high on */
1163 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001165 uchar termination_lvd; /* 11 0 - automatic */
1166 /* 1 - low off / high off */
1167 /* 2 - low off / high on */
1168 /* 3 - low on / high on */
1169 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001171 ushort bios_ctrl; /* 12 BIOS control bits */
1172 /* bit 0 BIOS don't act as initiator. */
1173 /* bit 1 BIOS > 1 GB support */
1174 /* bit 2 BIOS > 2 Disk Support */
1175 /* bit 3 BIOS don't support removables */
1176 /* bit 4 BIOS support bootable CD */
1177 /* bit 5 BIOS scan enabled */
1178 /* bit 6 BIOS support multiple LUNs */
1179 /* bit 7 BIOS display of message */
1180 /* bit 8 SCAM disabled */
1181 /* bit 9 Reset SCSI bus during init. */
1182 /* bit 10 */
1183 /* bit 11 No verbose initialization. */
1184 /* bit 12 SCSI parity enabled */
1185 /* bit 13 */
1186 /* bit 14 */
1187 /* bit 15 */
1188 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1189 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1190 uchar max_host_qng; /* 15 maximum host queueing */
1191 uchar max_dvc_qng; /* maximum per device queuing */
1192 ushort dvc_cntl; /* 16 control bit for driver */
1193 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1194 ushort serial_number_word1; /* 18 Board serial number word 1 */
1195 ushort serial_number_word2; /* 19 Board serial number word 2 */
1196 ushort serial_number_word3; /* 20 Board serial number word 3 */
1197 ushort check_sum; /* 21 EEP check sum */
1198 uchar oem_name[16]; /* 22 OEM name */
1199 ushort dvc_err_code; /* 30 last device driver error code */
1200 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1201 ushort adv_err_addr; /* 32 last uc error address */
1202 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1203 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1204 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1205 ushort reserved36; /* 36 reserved */
1206 ushort reserved37; /* 37 reserved */
1207 ushort reserved38; /* 38 reserved */
1208 ushort reserved39; /* 39 reserved */
1209 ushort reserved40; /* 40 reserved */
1210 ushort reserved41; /* 41 reserved */
1211 ushort reserved42; /* 42 reserved */
1212 ushort reserved43; /* 43 reserved */
1213 ushort reserved44; /* 44 reserved */
1214 ushort reserved45; /* 45 reserved */
1215 ushort reserved46; /* 46 reserved */
1216 ushort reserved47; /* 47 reserved */
1217 ushort reserved48; /* 48 reserved */
1218 ushort reserved49; /* 49 reserved */
1219 ushort reserved50; /* 50 reserved */
1220 ushort reserved51; /* 51 reserved */
1221 ushort reserved52; /* 52 reserved */
1222 ushort reserved53; /* 53 reserved */
1223 ushort reserved54; /* 54 reserved */
1224 ushort reserved55; /* 55 reserved */
1225 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1226 ushort cisprt_msw; /* 57 CIS PTR MSW */
1227 ushort subsysvid; /* 58 SubSystem Vendor ID */
1228 ushort subsysid; /* 59 SubSystem ID */
1229 ushort reserved60; /* 60 reserved */
1230 ushort reserved61; /* 61 reserved */
1231 ushort reserved62; /* 62 reserved */
1232 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233} ADVEEP_38C0800_CONFIG;
1234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001235typedef struct adveep_38C1600_config {
1236 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001238 ushort cfg_lsw; /* 00 power up initialization */
1239 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1240 /* clear - Func. 0 INTA, Func. 1 INTB */
1241 /* bit 13 set - Load CIS */
1242 /* bit 14 set - BIOS Enable */
1243 /* bit 15 set - Big Endian Mode */
1244 ushort cfg_msw; /* 01 unused */
1245 ushort disc_enable; /* 02 disconnect enable */
1246 ushort wdtr_able; /* 03 Wide DTR able */
1247 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1248 ushort start_motor; /* 05 send start up motor */
1249 ushort tagqng_able; /* 06 tag queuing able */
1250 ushort bios_scan; /* 07 BIOS device control */
1251 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001253 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1254 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001256 uchar scsi_reset_delay; /* 10 reset delay */
1257 uchar bios_id_lun; /* first boot device scsi id & lun */
1258 /* high nibble is lun */
1259 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001261 uchar termination_se; /* 11 0 - automatic */
1262 /* 1 - low off / high off */
1263 /* 2 - low off / high on */
1264 /* 3 - low on / high on */
1265 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001267 uchar termination_lvd; /* 11 0 - automatic */
1268 /* 1 - low off / high off */
1269 /* 2 - low off / high on */
1270 /* 3 - low on / high on */
1271 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001273 ushort bios_ctrl; /* 12 BIOS control bits */
1274 /* bit 0 BIOS don't act as initiator. */
1275 /* bit 1 BIOS > 1 GB support */
1276 /* bit 2 BIOS > 2 Disk Support */
1277 /* bit 3 BIOS don't support removables */
1278 /* bit 4 BIOS support bootable CD */
1279 /* bit 5 BIOS scan enabled */
1280 /* bit 6 BIOS support multiple LUNs */
1281 /* bit 7 BIOS display of message */
1282 /* bit 8 SCAM disabled */
1283 /* bit 9 Reset SCSI bus during init. */
1284 /* bit 10 Basic Integrity Checking disabled */
1285 /* bit 11 No verbose initialization. */
1286 /* bit 12 SCSI parity enabled */
1287 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1288 /* bit 14 */
1289 /* bit 15 */
1290 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1291 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1292 uchar max_host_qng; /* 15 maximum host queueing */
1293 uchar max_dvc_qng; /* maximum per device queuing */
1294 ushort dvc_cntl; /* 16 control bit for driver */
1295 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1296 ushort serial_number_word1; /* 18 Board serial number word 1 */
1297 ushort serial_number_word2; /* 19 Board serial number word 2 */
1298 ushort serial_number_word3; /* 20 Board serial number word 3 */
1299 ushort check_sum; /* 21 EEP check sum */
1300 uchar oem_name[16]; /* 22 OEM name */
1301 ushort dvc_err_code; /* 30 last device driver error code */
1302 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1303 ushort adv_err_addr; /* 32 last uc error address */
1304 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1305 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1306 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1307 ushort reserved36; /* 36 reserved */
1308 ushort reserved37; /* 37 reserved */
1309 ushort reserved38; /* 38 reserved */
1310 ushort reserved39; /* 39 reserved */
1311 ushort reserved40; /* 40 reserved */
1312 ushort reserved41; /* 41 reserved */
1313 ushort reserved42; /* 42 reserved */
1314 ushort reserved43; /* 43 reserved */
1315 ushort reserved44; /* 44 reserved */
1316 ushort reserved45; /* 45 reserved */
1317 ushort reserved46; /* 46 reserved */
1318 ushort reserved47; /* 47 reserved */
1319 ushort reserved48; /* 48 reserved */
1320 ushort reserved49; /* 49 reserved */
1321 ushort reserved50; /* 50 reserved */
1322 ushort reserved51; /* 51 reserved */
1323 ushort reserved52; /* 52 reserved */
1324 ushort reserved53; /* 53 reserved */
1325 ushort reserved54; /* 54 reserved */
1326 ushort reserved55; /* 55 reserved */
1327 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1328 ushort cisprt_msw; /* 57 CIS PTR MSW */
1329 ushort subsysvid; /* 58 SubSystem Vendor ID */
1330 ushort subsysid; /* 59 SubSystem ID */
1331 ushort reserved60; /* 60 reserved */
1332 ushort reserved61; /* 61 reserved */
1333 ushort reserved62; /* 62 reserved */
1334 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335} ADVEEP_38C1600_CONFIG;
1336
1337/*
1338 * EEPROM Commands
1339 */
1340#define ASC_EEP_CMD_DONE 0x0200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
1342/* bios_ctrl */
1343#define BIOS_CTRL_BIOS 0x0001
1344#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1345#define BIOS_CTRL_GT_2_DISK 0x0004
1346#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1347#define BIOS_CTRL_BOOTABLE_CD 0x0010
1348#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1349#define BIOS_CTRL_DISPLAY_MSG 0x0080
1350#define BIOS_CTRL_NO_SCAM 0x0100
1351#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1352#define BIOS_CTRL_INIT_VERBOSE 0x0800
1353#define BIOS_CTRL_SCSI_PARITY 0x1000
1354#define BIOS_CTRL_AIPP_DIS 0x2000
1355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001356#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001358#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360/*
1361 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1362 * a special 16K Adv Library and Microcode version. After the issue is
1363 * resolved, should restore 32K support.
1364 *
1365 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1366 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001367#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
1369/*
1370 * Byte I/O register address from base of 'iop_base'.
1371 */
1372#define IOPB_INTR_STATUS_REG 0x00
1373#define IOPB_CHIP_ID_1 0x01
1374#define IOPB_INTR_ENABLES 0x02
1375#define IOPB_CHIP_TYPE_REV 0x03
1376#define IOPB_RES_ADDR_4 0x04
1377#define IOPB_RES_ADDR_5 0x05
1378#define IOPB_RAM_DATA 0x06
1379#define IOPB_RES_ADDR_7 0x07
1380#define IOPB_FLAG_REG 0x08
1381#define IOPB_RES_ADDR_9 0x09
1382#define IOPB_RISC_CSR 0x0A
1383#define IOPB_RES_ADDR_B 0x0B
1384#define IOPB_RES_ADDR_C 0x0C
1385#define IOPB_RES_ADDR_D 0x0D
1386#define IOPB_SOFT_OVER_WR 0x0E
1387#define IOPB_RES_ADDR_F 0x0F
1388#define IOPB_MEM_CFG 0x10
1389#define IOPB_RES_ADDR_11 0x11
1390#define IOPB_GPIO_DATA 0x12
1391#define IOPB_RES_ADDR_13 0x13
1392#define IOPB_FLASH_PAGE 0x14
1393#define IOPB_RES_ADDR_15 0x15
1394#define IOPB_GPIO_CNTL 0x16
1395#define IOPB_RES_ADDR_17 0x17
1396#define IOPB_FLASH_DATA 0x18
1397#define IOPB_RES_ADDR_19 0x19
1398#define IOPB_RES_ADDR_1A 0x1A
1399#define IOPB_RES_ADDR_1B 0x1B
1400#define IOPB_RES_ADDR_1C 0x1C
1401#define IOPB_RES_ADDR_1D 0x1D
1402#define IOPB_RES_ADDR_1E 0x1E
1403#define IOPB_RES_ADDR_1F 0x1F
1404#define IOPB_DMA_CFG0 0x20
1405#define IOPB_DMA_CFG1 0x21
1406#define IOPB_TICKLE 0x22
1407#define IOPB_DMA_REG_WR 0x23
1408#define IOPB_SDMA_STATUS 0x24
1409#define IOPB_SCSI_BYTE_CNT 0x25
1410#define IOPB_HOST_BYTE_CNT 0x26
1411#define IOPB_BYTE_LEFT_TO_XFER 0x27
1412#define IOPB_BYTE_TO_XFER_0 0x28
1413#define IOPB_BYTE_TO_XFER_1 0x29
1414#define IOPB_BYTE_TO_XFER_2 0x2A
1415#define IOPB_BYTE_TO_XFER_3 0x2B
1416#define IOPB_ACC_GRP 0x2C
1417#define IOPB_RES_ADDR_2D 0x2D
1418#define IOPB_DEV_ID 0x2E
1419#define IOPB_RES_ADDR_2F 0x2F
1420#define IOPB_SCSI_DATA 0x30
1421#define IOPB_RES_ADDR_31 0x31
1422#define IOPB_RES_ADDR_32 0x32
1423#define IOPB_SCSI_DATA_HSHK 0x33
1424#define IOPB_SCSI_CTRL 0x34
1425#define IOPB_RES_ADDR_35 0x35
1426#define IOPB_RES_ADDR_36 0x36
1427#define IOPB_RES_ADDR_37 0x37
1428#define IOPB_RAM_BIST 0x38
1429#define IOPB_PLL_TEST 0x39
1430#define IOPB_PCI_INT_CFG 0x3A
1431#define IOPB_RES_ADDR_3B 0x3B
1432#define IOPB_RFIFO_CNT 0x3C
1433#define IOPB_RES_ADDR_3D 0x3D
1434#define IOPB_RES_ADDR_3E 0x3E
1435#define IOPB_RES_ADDR_3F 0x3F
1436
1437/*
1438 * Word I/O register address from base of 'iop_base'.
1439 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001440#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1441#define IOPW_CTRL_REG 0x02 /* CC */
1442#define IOPW_RAM_ADDR 0x04 /* LA */
1443#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001445#define IOPW_RISC_CSR 0x0A /* CSR */
1446#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1447#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001449#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001451#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001453#define IOPW_EE_CMD 0x1A /* EC */
1454#define IOPW_EE_DATA 0x1C /* ED */
1455#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001457#define IOPW_Q_BASE 0x22 /* QB */
1458#define IOPW_QP 0x24 /* QP */
1459#define IOPW_IX 0x26 /* IX */
1460#define IOPW_SP 0x28 /* SP */
1461#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462#define IOPW_RES_ADDR_2C 0x2C
1463#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001464#define IOPW_SCSI_DATA 0x30 /* SD */
1465#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1466#define IOPW_SCSI_CTRL 0x34 /* SC */
1467#define IOPW_HSHK_CFG 0x36 /* HCFG */
1468#define IOPW_SXFR_STATUS 0x36 /* SXS */
1469#define IOPW_SXFR_CNTL 0x38 /* SXL */
1470#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001472#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474/*
1475 * Doubleword I/O register address from base of 'iop_base'.
1476 */
1477#define IOPDW_RES_ADDR_0 0x00
1478#define IOPDW_RAM_DATA 0x04
1479#define IOPDW_RES_ADDR_8 0x08
1480#define IOPDW_RES_ADDR_C 0x0C
1481#define IOPDW_RES_ADDR_10 0x10
1482#define IOPDW_COMMA 0x14
1483#define IOPDW_COMMB 0x18
1484#define IOPDW_RES_ADDR_1C 0x1C
1485#define IOPDW_SDMA_ADDR0 0x20
1486#define IOPDW_SDMA_ADDR1 0x24
1487#define IOPDW_SDMA_COUNT 0x28
1488#define IOPDW_SDMA_ERROR 0x2C
1489#define IOPDW_RDMA_ADDR0 0x30
1490#define IOPDW_RDMA_ADDR1 0x34
1491#define IOPDW_RDMA_COUNT 0x38
1492#define IOPDW_RDMA_ERROR 0x3C
1493
1494#define ADV_CHIP_ID_BYTE 0x25
1495#define ADV_CHIP_ID_WORD 0x04C1
1496
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497#define ADV_INTR_ENABLE_HOST_INTR 0x01
1498#define ADV_INTR_ENABLE_SEL_INTR 0x02
1499#define ADV_INTR_ENABLE_DPR_INTR 0x04
1500#define ADV_INTR_ENABLE_RTA_INTR 0x08
1501#define ADV_INTR_ENABLE_RMA_INTR 0x10
1502#define ADV_INTR_ENABLE_RST_INTR 0x20
1503#define ADV_INTR_ENABLE_DPE_INTR 0x40
1504#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1505
1506#define ADV_INTR_STATUS_INTRA 0x01
1507#define ADV_INTR_STATUS_INTRB 0x02
1508#define ADV_INTR_STATUS_INTRC 0x04
1509
1510#define ADV_RISC_CSR_STOP (0x0000)
1511#define ADV_RISC_TEST_COND (0x2000)
1512#define ADV_RISC_CSR_RUN (0x4000)
1513#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1514
1515#define ADV_CTRL_REG_HOST_INTR 0x0100
1516#define ADV_CTRL_REG_SEL_INTR 0x0200
1517#define ADV_CTRL_REG_DPR_INTR 0x0400
1518#define ADV_CTRL_REG_RTA_INTR 0x0800
1519#define ADV_CTRL_REG_RMA_INTR 0x1000
1520#define ADV_CTRL_REG_RES_BIT14 0x2000
1521#define ADV_CTRL_REG_DPE_INTR 0x4000
1522#define ADV_CTRL_REG_POWER_DONE 0x8000
1523#define ADV_CTRL_REG_ANY_INTR 0xFF00
1524
1525#define ADV_CTRL_REG_CMD_RESET 0x00C6
1526#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1527#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1528#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1529#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1530
1531#define ADV_TICKLE_NOP 0x00
1532#define ADV_TICKLE_A 0x01
1533#define ADV_TICKLE_B 0x02
1534#define ADV_TICKLE_C 0x03
1535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536#define AdvIsIntPending(port) \
1537 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1538
1539/*
1540 * SCSI_CFG0 Register bit definitions
1541 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001542#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1543#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1544#define EVEN_PARITY 0x1000 /* Select Even Parity */
1545#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1546#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1547#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1548#define SCAM_EN 0x0080 /* Enable SCAM selection */
1549#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1550#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1551#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1552#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
1554/*
1555 * SCSI_CFG1 Register bit definitions
1556 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001557#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1558#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1559#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1560#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1561#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1562#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1563#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1564#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1565#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1566#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1567#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1568#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1569#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1570#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1571#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
1573/*
1574 * Addendum for ASC-38C0800 Chip
1575 *
1576 * The ASC-38C1600 Chip uses the same definitions except that the
1577 * bus mode override bits [12:10] have been moved to byte register
1578 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1579 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1580 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1581 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1582 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1583 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001584#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1585#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1586#define HVD 0x1000 /* HVD Device Detect */
1587#define LVD 0x0800 /* LVD Device Detect */
1588#define SE 0x0400 /* SE Device Detect */
1589#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1590#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1591#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1592#define TERM_SE 0x0030 /* SE Termination Bits */
1593#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1594#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1595#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1596#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1597#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1598#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1599#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1600#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602#define CABLE_ILLEGAL_A 0x7
1603 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1604
1605#define CABLE_ILLEGAL_B 0xB
1606 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1607
1608/*
1609 * MEM_CFG Register bit definitions
1610 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001611#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1612#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1613#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1614#define RAM_SZ_2KB 0x00 /* 2 KB */
1615#define RAM_SZ_4KB 0x04 /* 4 KB */
1616#define RAM_SZ_8KB 0x08 /* 8 KB */
1617#define RAM_SZ_16KB 0x0C /* 16 KB */
1618#define RAM_SZ_32KB 0x10 /* 32 KB */
1619#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
1621/*
1622 * DMA_CFG0 Register bit definitions
1623 *
1624 * This register is only accessible to the host.
1625 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001626#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1627#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1628#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1629#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1630#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1631#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1632#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1633#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1634#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1635#define START_CTL 0x0C /* DMA start conditions */
1636#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1637#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1638#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1639#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1640#define READ_CMD 0x03 /* Memory Read Method */
1641#define READ_CMD_MR 0x00 /* Memory Read */
1642#define READ_CMD_MRL 0x02 /* Memory Read Long */
1643#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645/*
1646 * ASC-38C0800 RAM BIST Register bit definitions
1647 */
1648#define RAM_TEST_MODE 0x80
1649#define PRE_TEST_MODE 0x40
1650#define NORMAL_MODE 0x00
1651#define RAM_TEST_DONE 0x10
1652#define RAM_TEST_STATUS 0x0F
1653#define RAM_TEST_HOST_ERROR 0x08
1654#define RAM_TEST_INTRAM_ERROR 0x04
1655#define RAM_TEST_RISC_ERROR 0x02
1656#define RAM_TEST_SCSI_ERROR 0x01
1657#define RAM_TEST_SUCCESS 0x00
1658#define PRE_TEST_VALUE 0x05
1659#define NORMAL_VALUE 0x00
1660
1661/*
1662 * ASC38C1600 Definitions
1663 *
1664 * IOPB_PCI_INT_CFG Bit Field Definitions
1665 */
1666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001667#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669/*
1670 * Bit 1 can be set to change the interrupt for the Function to operate in
1671 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1672 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1673 * mode, otherwise the operating mode is undefined.
1674 */
1675#define TOTEMPOLE 0x02
1676
1677/*
1678 * Bit 0 can be used to change the Int Pin for the Function. The value is
1679 * 0 by default for both Functions with Function 0 using INT A and Function
1680 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1681 * INT A is used.
1682 *
1683 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1684 * value specified in the PCI Configuration Space.
1685 */
1686#define INTAB 0x01
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688/*
1689 * Adv Library Status Definitions
1690 */
1691#define ADV_TRUE 1
1692#define ADV_FALSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693#define ADV_SUCCESS 1
1694#define ADV_BUSY 0
1695#define ADV_ERROR (-1)
1696
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697/*
1698 * ADV_DVC_VAR 'warn_code' values
1699 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001700#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1701#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1702#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001703#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001705#define ADV_MAX_TID 15 /* max. target identifier */
1706#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
1708/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 * Fixed locations of microcode operating variables.
1710 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001711#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1712#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1713#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1714#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1715#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1716#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1717#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1718#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1719#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1720#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1721#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1722#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1723#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724#define ASC_MC_CHIP_TYPE 0x009A
1725#define ASC_MC_INTRB_CODE 0x009B
1726#define ASC_MC_WDTR_ABLE 0x009C
1727#define ASC_MC_SDTR_ABLE 0x009E
1728#define ASC_MC_TAGQNG_ABLE 0x00A0
1729#define ASC_MC_DISC_ENABLE 0x00A2
1730#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1731#define ASC_MC_IDLE_CMD 0x00A6
1732#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1733#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1734#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1735#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1736#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1737#define ASC_MC_SDTR_DONE 0x00B6
1738#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1739#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1740#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001741#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001743#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744#define ASC_MC_ICQ 0x0160
1745#define ASC_MC_IRQ 0x0164
1746#define ASC_MC_PPR_ABLE 0x017A
1747
1748/*
1749 * BIOS LRAM variable absolute offsets.
1750 */
1751#define BIOS_CODESEG 0x54
1752#define BIOS_CODELEN 0x56
1753#define BIOS_SIGNATURE 0x58
1754#define BIOS_VERSION 0x5A
1755
1756/*
1757 * Microcode Control Flags
1758 *
1759 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1760 * and handled by the microcode.
1761 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001762#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1763#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
1765/*
1766 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1767 */
1768#define HSHK_CFG_WIDE_XFR 0x8000
1769#define HSHK_CFG_RATE 0x0F00
1770#define HSHK_CFG_OFFSET 0x001F
1771
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001772#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1773#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1774#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1775#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001777#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
1778#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
1779#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
1780#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
1781#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001783#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
1784#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
1785#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
1786#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
1787#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788/*
1789 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
1790 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
1791 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001792#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
1793#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
1795/*
1796 * All fields here are accessed by the board microcode and need to be
1797 * little-endian.
1798 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001799typedef struct adv_carr_t {
1800 ADV_VADDR carr_va; /* Carrier Virtual Address */
1801 ADV_PADDR carr_pa; /* Carrier Physical Address */
1802 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
1803 /*
1804 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
1805 *
1806 * next_vpa [3:1] Reserved Bits
1807 * next_vpa [0] Done Flag set in Response Queue.
1808 */
1809 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810} ADV_CARR_T;
1811
1812/*
1813 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
1814 */
1815#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
1816
1817#define ASC_RQ_DONE 0x00000001
1818#define ASC_RQ_GOOD 0x00000002
1819#define ASC_CQ_STOPPER 0x00000000
1820
1821#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
1822
1823#define ADV_CARRIER_NUM_PAGE_CROSSING \
1824 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
1825 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1826
1827#define ADV_CARRIER_BUFSIZE \
1828 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
1829
1830/*
1831 * ASC_SCSI_REQ_Q 'a_flag' definitions
1832 *
1833 * The Adv Library should limit use to the lower nibble (4 bits) of
1834 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
1835 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001836#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
1837#define ADV_SCSIQ_DONE 0x02 /* request done */
1838#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001840#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
1841#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
1842#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
1844/*
1845 * Adapter temporary configuration structure
1846 *
1847 * This structure can be discarded after initialization. Don't add
1848 * fields here needed after initialization.
1849 *
1850 * Field naming convention:
1851 *
1852 * *_enable indicates the field enables or disables a feature. The
1853 * value of the field is never reset.
1854 */
1855typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001856 ushort disc_enable; /* enable disconnection */
1857 uchar chip_version; /* chip version */
1858 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
1859 ushort lib_version; /* Adv Library version number */
1860 ushort control_flag; /* Microcode Control Flag */
1861 ushort mcode_date; /* Microcode date */
1862 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001863 ushort serial1; /* EEPROM serial number word 1 */
1864 ushort serial2; /* EEPROM serial number word 2 */
1865 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866} ADV_DVC_CFG;
1867
1868struct adv_dvc_var;
1869struct adv_scsi_req_q;
1870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871/*
1872 * Adapter operation variable structure.
1873 *
1874 * One structure is required per host adapter.
1875 *
1876 * Field naming convention:
1877 *
1878 * *_able indicates both whether a feature should be enabled or disabled
1879 * and whether a device isi capable of the feature. At initialization
1880 * this field may be set, but later if a device is found to be incapable
1881 * of the feature, the field is cleared.
1882 */
1883typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001884 AdvPortAddr iop_base; /* I/O port address */
1885 ushort err_code; /* fatal error code */
1886 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001887 ushort wdtr_able; /* try WDTR for a device */
1888 ushort sdtr_able; /* try SDTR for a device */
1889 ushort ultra_able; /* try SDTR Ultra speed for a device */
1890 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
1891 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
1892 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
1893 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
1894 ushort tagqng_able; /* try tagged queuing with a device */
1895 ushort ppr_able; /* PPR message capable per TID bitmask. */
1896 uchar max_dvc_qng; /* maximum number of tagged commands per device */
1897 ushort start_motor; /* start motor command allowed */
1898 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
1899 uchar chip_no; /* should be assigned by caller */
1900 uchar max_host_qng; /* maximum number of Q'ed command allowed */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001901 ushort no_scam; /* scam_tolerant of EEPROM */
1902 struct asc_board *drv_ptr; /* driver pointer to private structure */
1903 uchar chip_scsi_id; /* chip SCSI target ID */
1904 uchar chip_type;
1905 uchar bist_err_code;
1906 ADV_CARR_T *carrier_buf;
1907 ADV_CARR_T *carr_freelist; /* Carrier free list. */
1908 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
1909 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
1910 ushort carr_pending_cnt; /* Count of pending carriers. */
1911 /*
1912 * Note: The following fields will not be used after initialization. The
1913 * driver may discard the buffer after initialization is done.
1914 */
1915 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916} ADV_DVC_VAR;
1917
1918#define NO_OF_SG_PER_BLOCK 15
1919
1920typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001921 uchar reserved1;
1922 uchar reserved2;
1923 uchar reserved3;
1924 uchar sg_cnt; /* Valid entries in block. */
1925 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
1926 struct {
1927 ADV_PADDR sg_addr; /* SG element address. */
1928 ADV_DCNT sg_count; /* SG element count. */
1929 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930} ADV_SG_BLOCK;
1931
1932/*
1933 * ADV_SCSI_REQ_Q - microcode request structure
1934 *
1935 * All fields in this structure up to byte 60 are used by the microcode.
1936 * The microcode makes assumptions about the size and ordering of fields
1937 * in this structure. Do not change the structure definition here without
1938 * coordinating the change with the microcode.
1939 *
1940 * All fields accessed by microcode must be maintained in little_endian
1941 * order.
1942 */
1943typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001944 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
1945 uchar target_cmd;
1946 uchar target_id; /* Device target identifier. */
1947 uchar target_lun; /* Device target logical unit number. */
1948 ADV_PADDR data_addr; /* Data buffer physical address. */
1949 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
1950 ADV_PADDR sense_addr;
1951 ADV_PADDR carr_pa;
1952 uchar mflag;
1953 uchar sense_len;
1954 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
1955 uchar scsi_cntl;
1956 uchar done_status; /* Completion status. */
1957 uchar scsi_status; /* SCSI status byte. */
1958 uchar host_status; /* Ucode host status. */
1959 uchar sg_working_ix;
1960 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
1961 ADV_PADDR sg_real_addr; /* SG list physical address. */
1962 ADV_PADDR scsiq_rptr;
1963 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
1964 ADV_VADDR scsiq_ptr;
1965 ADV_VADDR carr_va;
1966 /*
1967 * End of microcode structure - 60 bytes. The rest of the structure
1968 * is used by the Adv Library and ignored by the microcode.
1969 */
1970 ADV_VADDR srb_ptr;
1971 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
1972 char *vdata_addr; /* Data buffer virtual address. */
1973 uchar a_flag;
1974 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975} ADV_SCSI_REQ_Q;
1976
1977/*
1978 * Microcode idle loop commands
1979 */
1980#define IDLE_CMD_COMPLETED 0
1981#define IDLE_CMD_STOP_CHIP 0x0001
1982#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
1983#define IDLE_CMD_SEND_INT 0x0004
1984#define IDLE_CMD_ABORT 0x0008
1985#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001986#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
1987#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988#define IDLE_CMD_SCSIREQ 0x0080
1989
1990#define IDLE_CMD_STATUS_SUCCESS 0x0001
1991#define IDLE_CMD_STATUS_FAILURE 0x0002
1992
1993/*
1994 * AdvSendIdleCmd() flag definitions.
1995 */
1996#define ADV_NOWAIT 0x01
1997
1998/*
1999 * Wait loop time out values.
2000 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002001#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2002#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002003#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002005#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2006#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2007#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2008#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002010#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012/* Read byte from a register. */
2013#define AdvReadByteRegister(iop_base, reg_off) \
2014 (ADV_MEM_READB((iop_base) + (reg_off)))
2015
2016/* Write byte to a register. */
2017#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2018 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2019
2020/* Read word (2 bytes) from a register. */
2021#define AdvReadWordRegister(iop_base, reg_off) \
2022 (ADV_MEM_READW((iop_base) + (reg_off)))
2023
2024/* Write word (2 bytes) to a register. */
2025#define AdvWriteWordRegister(iop_base, reg_off, word) \
2026 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2027
2028/* Write dword (4 bytes) to a register. */
2029#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2030 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2031
2032/* Read byte from LRAM. */
2033#define AdvReadByteLram(iop_base, addr, byte) \
2034do { \
2035 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2036 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2037} while (0)
2038
2039/* Write byte to LRAM. */
2040#define AdvWriteByteLram(iop_base, addr, byte) \
2041 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2042 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2043
2044/* Read word (2 bytes) from LRAM. */
2045#define AdvReadWordLram(iop_base, addr, word) \
2046do { \
2047 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2048 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2049} while (0)
2050
2051/* Write word (2 bytes) to LRAM. */
2052#define AdvWriteWordLram(iop_base, addr, word) \
2053 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2054 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2055
2056/* Write little-endian double word (4 bytes) to LRAM */
2057/* Because of unspecified C language ordering don't use auto-increment. */
2058#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2059 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2060 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2061 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2062 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2063 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2064 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2065
2066/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2067#define AdvReadWordAutoIncLram(iop_base) \
2068 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2069
2070/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2071#define AdvWriteWordAutoIncLram(iop_base, word) \
2072 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2073
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074/*
2075 * Define macro to check for Condor signature.
2076 *
2077 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2078 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2079 */
2080#define AdvFindSignature(iop_base) \
2081 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2082 ADV_CHIP_ID_BYTE) && \
2083 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2084 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2085
2086/*
2087 * Define macro to Return the version number of the chip at 'iop_base'.
2088 *
2089 * The second parameter 'bus_type' is currently unused.
2090 */
2091#define AdvGetChipVersion(iop_base, bus_type) \
2092 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2093
2094/*
2095 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2096 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2097 *
2098 * If the request has not yet been sent to the device it will simply be
2099 * aborted from RISC memory. If the request is disconnected it will be
2100 * aborted on reselection by sending an Abort Message to the target ID.
2101 *
2102 * Return value:
2103 * ADV_TRUE(1) - Queue was successfully aborted.
2104 * ADV_FALSE(0) - Queue was not found on the active queue list.
2105 */
2106#define AdvAbortQueue(asc_dvc, scsiq) \
2107 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2108 (ADV_DCNT) (scsiq))
2109
2110/*
2111 * Send a Bus Device Reset Message to the specified target ID.
2112 *
2113 * All outstanding commands will be purged if sending the
2114 * Bus Device Reset Message is successful.
2115 *
2116 * Return Value:
2117 * ADV_TRUE(1) - All requests on the target are purged.
2118 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2119 * are not purged.
2120 */
2121#define AdvResetDevice(asc_dvc, target_id) \
2122 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2123 (ADV_DCNT) (target_id))
2124
2125/*
2126 * SCSI Wide Type definition.
2127 */
2128#define ADV_SCSI_BIT_ID_TYPE ushort
2129
2130/*
2131 * AdvInitScsiTarget() 'cntl_flag' options.
2132 */
2133#define ADV_SCAN_LUN 0x01
2134#define ADV_CAPINFO_NOLUN 0x02
2135
2136/*
2137 * Convert target id to target id bit mask.
2138 */
2139#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2140
2141/*
2142 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2143 */
2144
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002145#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146#define QD_NO_ERROR 0x01
2147#define QD_ABORTED_BY_HOST 0x02
2148#define QD_WITH_ERROR 0x04
2149
2150#define QHSTA_NO_ERROR 0x00
2151#define QHSTA_M_SEL_TIMEOUT 0x11
2152#define QHSTA_M_DATA_OVER_RUN 0x12
2153#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2154#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002155#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2156#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2157#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2158#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2159#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2160#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2161#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002163#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2164#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2165#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2166#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2167#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2168#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2169#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2170#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171#define QHSTA_M_WTM_TIMEOUT 0x41
2172#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2173#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2174#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002175#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2176#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2177#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178
2179/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 * DvcGetPhyAddr() flag arguments
2181 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002182#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2183#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2184#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2185#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2186#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2187#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
2189/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2190#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2191#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2192#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2193
2194/*
2195 * Total contiguous memory needed for driver SG blocks.
2196 *
2197 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2198 * number of scatter-gather elements the driver supports in a
2199 * single request.
2200 */
2201
2202#define ADV_SG_LIST_MAX_BYTE_SIZE \
2203 (sizeof(ADV_SG_BLOCK) * \
2204 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206/* Reference Scsi_Host hostdata */
2207#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
2208
2209/* asc_board_t flags */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002210#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211
2212#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002214#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002216#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
2218#ifdef CONFIG_PROC_FS
2219/* /proc/scsi/advansys/[0...] related definitions */
2220#define ASC_PRTBUF_SIZE 2048
2221#define ASC_PRTLINE_SIZE 160
2222
2223#define ASC_PRT_NEXT() \
2224 if (cp) { \
2225 totlen += len; \
2226 leftlen -= len; \
2227 if (leftlen == 0) { \
2228 return totlen; \
2229 } \
2230 cp += len; \
2231 }
2232#endif /* CONFIG_PROC_FS */
2233
2234/* Asc Library return codes */
2235#define ASC_TRUE 1
2236#define ASC_FALSE 0
2237#define ASC_NOERROR 1
2238#define ASC_BUSY 0
2239#define ASC_ERROR (-1)
2240
2241/* struct scsi_cmnd function return codes */
2242#define STATUS_BYTE(byte) (byte)
2243#define MSG_BYTE(byte) ((byte) << 8)
2244#define HOST_BYTE(byte) ((byte) << 16)
2245#define DRIVER_BYTE(byte) ((byte) << 24)
2246
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002248#define ASC_STATS(shost, counter)
2249#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002251#define ASC_STATS(shost, counter) \
2252 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002254#define ASC_STATS_ADD(shost, counter, count) \
2255 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256#endif /* ADVANSYS_STATS */
2257
2258#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2259
2260/* If the result wraps when calculating tenths, return 0. */
2261#define ASC_TENTHS(num, den) \
2262 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2263 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2264
2265/*
2266 * Display a message to the console.
2267 */
2268#define ASC_PRINT(s) \
2269 { \
2270 printk("advansys: "); \
2271 printk(s); \
2272 }
2273
2274#define ASC_PRINT1(s, a1) \
2275 { \
2276 printk("advansys: "); \
2277 printk((s), (a1)); \
2278 }
2279
2280#define ASC_PRINT2(s, a1, a2) \
2281 { \
2282 printk("advansys: "); \
2283 printk((s), (a1), (a2)); \
2284 }
2285
2286#define ASC_PRINT3(s, a1, a2, a3) \
2287 { \
2288 printk("advansys: "); \
2289 printk((s), (a1), (a2), (a3)); \
2290 }
2291
2292#define ASC_PRINT4(s, a1, a2, a3, a4) \
2293 { \
2294 printk("advansys: "); \
2295 printk((s), (a1), (a2), (a3), (a4)); \
2296 }
2297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298#ifndef ADVANSYS_DEBUG
2299
2300#define ASC_DBG(lvl, s)
2301#define ASC_DBG1(lvl, s, a1)
2302#define ASC_DBG2(lvl, s, a1, a2)
2303#define ASC_DBG3(lvl, s, a1, a2, a3)
2304#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2305#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2306#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
2307#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2308#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2309#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2310#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2311#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2312#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2313#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2314#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2315
2316#else /* ADVANSYS_DEBUG */
2317
2318/*
2319 * Debugging Message Levels:
2320 * 0: Errors Only
2321 * 1: High-Level Tracing
2322 * 2-N: Verbose Tracing
2323 */
2324
2325#define ASC_DBG(lvl, s) \
2326 { \
2327 if (asc_dbglvl >= (lvl)) { \
2328 printk(s); \
2329 } \
2330 }
2331
2332#define ASC_DBG1(lvl, s, a1) \
2333 { \
2334 if (asc_dbglvl >= (lvl)) { \
2335 printk((s), (a1)); \
2336 } \
2337 }
2338
2339#define ASC_DBG2(lvl, s, a1, a2) \
2340 { \
2341 if (asc_dbglvl >= (lvl)) { \
2342 printk((s), (a1), (a2)); \
2343 } \
2344 }
2345
2346#define ASC_DBG3(lvl, s, a1, a2, a3) \
2347 { \
2348 if (asc_dbglvl >= (lvl)) { \
2349 printk((s), (a1), (a2), (a3)); \
2350 } \
2351 }
2352
2353#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2354 { \
2355 if (asc_dbglvl >= (lvl)) { \
2356 printk((s), (a1), (a2), (a3), (a4)); \
2357 } \
2358 }
2359
2360#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2361 { \
2362 if (asc_dbglvl >= (lvl)) { \
2363 asc_prt_scsi_host(s); \
2364 } \
2365 }
2366
2367#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
2368 { \
2369 if (asc_dbglvl >= (lvl)) { \
2370 asc_prt_scsi_cmnd(s); \
2371 } \
2372 }
2373
2374#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2375 { \
2376 if (asc_dbglvl >= (lvl)) { \
2377 asc_prt_asc_scsi_q(scsiqp); \
2378 } \
2379 }
2380
2381#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2382 { \
2383 if (asc_dbglvl >= (lvl)) { \
2384 asc_prt_asc_qdone_info(qdone); \
2385 } \
2386 }
2387
2388#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2389 { \
2390 if (asc_dbglvl >= (lvl)) { \
2391 asc_prt_adv_scsi_req_q(scsiqp); \
2392 } \
2393 }
2394
2395#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2396 { \
2397 if (asc_dbglvl >= (lvl)) { \
2398 asc_prt_hex((name), (start), (length)); \
2399 } \
2400 }
2401
2402#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2403 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2404
2405#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2406 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2407
2408#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2409 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2410#endif /* ADVANSYS_DEBUG */
2411
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412#ifdef ADVANSYS_STATS
2413
2414/* Per board statistics structure */
2415struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002416 /* Driver Entrypoint Statistics */
2417 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2418 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2419 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2420 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2421 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2422 ADV_DCNT done; /* # calls to request's scsi_done function */
2423 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2424 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2425 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2426 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2427 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2428 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2429 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2430 ADV_DCNT exe_unknown; /* # unknown returns. */
2431 /* Data Transfer Statistics */
2432 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2433 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2434 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2435 ADV_DCNT sg_elem; /* # scatter-gather elements */
2436 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437};
2438#endif /* ADVANSYS_STATS */
2439
2440/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 * Adv Library Request Structures
2442 *
2443 * The following two structures are used to process Wide Board requests.
2444 *
2445 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2446 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2447 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2448 * Mid-Level SCSI request structure.
2449 *
2450 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2451 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2452 * up to 255 scatter-gather elements may be used per request or
2453 * ADV_SCSI_REQ_Q.
2454 *
2455 * Both structures must be 32 byte aligned.
2456 */
2457typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002458 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2459 uchar align[32]; /* Sgblock structure padding. */
2460 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461} adv_sgblk_t;
2462
2463typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002464 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2465 uchar align[32]; /* Request structure padding. */
2466 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2467 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2468 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469} adv_req_t;
2470
2471/*
2472 * Structure allocated for each board.
2473 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002474 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 * of the 'Scsi_Host' structure starting at the 'hostdata'
2476 * field. It is guaranteed to be allocated from DMA-able memory.
2477 */
2478typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002479 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002480 int id; /* Board Id */
2481 uint flags; /* Board flags */
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002482 unsigned int irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002483 union {
2484 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2485 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2486 } dvc_var;
2487 union {
2488 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2489 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2490 } dvc_cfg;
2491 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002492 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002493 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2494 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2495 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2496 union {
2497 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2498 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2499 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2500 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2501 } eep_config;
2502 ulong last_reset; /* Saved last reset time */
2503 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002504 /* /proc/scsi/advansys/[0...] */
2505 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002507 struct asc_stats asc_stats; /* Board statistics */
2508#endif /* ADVANSYS_STATS */
2509 /*
2510 * The following fields are used only for Narrow Boards.
2511 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002512 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2513 /*
2514 * The following fields are used only for Wide Boards.
2515 */
2516 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2517 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002518 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002519 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2520 adv_req_t *adv_reqp; /* Request structures. */
2521 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2522 ushort bios_signature; /* BIOS Signature. */
2523 ushort bios_version; /* BIOS Version. */
2524 ushort bios_codeseg; /* BIOS Code Segment. */
2525 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526} asc_board_t;
2527
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002528#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2529 dvc_var.adv_dvc_var)
2530#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2531
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002533static int asc_board_count;
2534
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002536static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002539static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002542 * asc_prt_scsi_host()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 */
Matthew Wilcox51219352007-10-02 21:55:22 -04002544static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002546 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
Matthew Wilcox51219352007-10-02 21:55:22 -04002548 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549
Matthew Wilcox51219352007-10-02 21:55:22 -04002550 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
2551 printk(" host_busy %u, host_no %d, last_reset %d,\n",
2552 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
Matthew Wilcox51219352007-10-02 21:55:22 -04002554 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002555 (ulong)s->base, (ulong)s->io_port, boardp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
Matthew Wilcox51219352007-10-02 21:55:22 -04002557 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
2558 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Matthew Wilcox51219352007-10-02 21:55:22 -04002560 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
2561 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002563 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04002564 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
2565 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002566 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04002567 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
2568 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570}
Matthew Wilcox51219352007-10-02 21:55:22 -04002571
2572/*
2573 * asc_prt_scsi_cmnd()
2574 */
2575static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
2576{
2577 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
2578
2579 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
2580 (ulong)s->device->host, (ulong)s->device, s->device->id,
2581 s->device->lun, s->device->channel);
2582
2583 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
2584
2585 printk("sc_data_direction %u, resid %d\n",
2586 s->sc_data_direction, s->resid);
2587
2588 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
2589
2590 printk(" serial_number 0x%x, retries %d, allowed %d\n",
2591 (unsigned)s->serial_number, s->retries, s->allowed);
2592
2593 printk(" timeout_per_command %d\n", s->timeout_per_command);
2594
2595 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
2596 s->scsi_done, s->done, s->host_scribble, s->result);
2597
2598 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
2599}
2600
2601/*
2602 * asc_prt_asc_dvc_var()
2603 */
2604static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
2605{
2606 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
2607
2608 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
2609 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
2610
2611 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
2612 (unsigned)h->init_sdtr);
2613
2614 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
2615 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
2616 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
2617 (unsigned)h->chip_no);
2618
2619 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
2620 "%u,\n", (unsigned)h->queue_full_or_busy,
2621 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
2622
2623 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
2624 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
2625 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
2626 (unsigned)h->in_critical_cnt);
2627
2628 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
2629 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
2630 (unsigned)h->init_state, (unsigned)h->no_scam,
2631 (unsigned)h->pci_fix_asyn_xfer);
2632
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002633 printk(" cfg 0x%lx\n", (ulong)h->cfg);
Matthew Wilcox51219352007-10-02 21:55:22 -04002634}
2635
2636/*
2637 * asc_prt_asc_dvc_cfg()
2638 */
2639static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
2640{
2641 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
2642
2643 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
2644 h->can_tagged_qng, h->cmd_qng_enabled);
2645 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
2646 h->disc_enable, h->sdtr_enable);
2647
2648 printk
2649 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
2650 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
2651 h->chip_version);
2652
2653 printk
2654 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
2655 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
2656 h->mcode_date);
2657
2658 printk(" mcode_version %d, overrun_buf 0x%lx\n",
2659 h->mcode_version, (ulong)h->overrun_buf);
2660}
2661
2662/*
2663 * asc_prt_asc_scsi_q()
2664 */
2665static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
2666{
2667 ASC_SG_HEAD *sgp;
2668 int i;
2669
2670 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
2671
2672 printk
2673 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
2674 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
2675 q->q2.tag_code);
2676
2677 printk
2678 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2679 (ulong)le32_to_cpu(q->q1.data_addr),
2680 (ulong)le32_to_cpu(q->q1.data_cnt),
2681 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
2682
2683 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
2684 (ulong)q->cdbptr, q->q2.cdb_len,
2685 (ulong)q->sg_head, q->q1.sg_queue_cnt);
2686
2687 if (q->sg_head) {
2688 sgp = q->sg_head;
2689 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
2690 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
2691 sgp->queue_cnt);
2692 for (i = 0; i < sgp->entry_cnt; i++) {
2693 printk(" [%u]: addr 0x%lx, bytes %lu\n",
2694 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
2695 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
2696 }
2697
2698 }
2699}
2700
2701/*
2702 * asc_prt_asc_qdone_info()
2703 */
2704static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
2705{
2706 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
2707 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
2708 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
2709 q->d2.tag_code);
2710 printk
2711 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
2712 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
2713}
2714
2715/*
2716 * asc_prt_adv_dvc_var()
2717 *
2718 * Display an ADV_DVC_VAR structure.
2719 */
2720static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
2721{
2722 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
2723
2724 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
2725 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
2726
2727 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
2728 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
2729 (unsigned)h->wdtr_able);
2730
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002731 printk(" start_motor 0x%x, scsi_reset_wait 0x%x\n",
2732 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Matthew Wilcox51219352007-10-02 21:55:22 -04002733
2734 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
2735 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
2736 (ulong)h->carr_freelist);
2737
2738 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
2739 (ulong)h->icq_sp, (ulong)h->irq_sp);
2740
2741 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
2742 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
2743
2744 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
2745 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
2746}
2747
2748/*
2749 * asc_prt_adv_dvc_cfg()
2750 *
2751 * Display an ADV_DVC_CFG structure.
2752 */
2753static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
2754{
2755 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
2756
2757 printk(" disc_enable 0x%x, termination 0x%x\n",
2758 h->disc_enable, h->termination);
2759
2760 printk(" chip_version 0x%x, mcode_date 0x%x\n",
2761 h->chip_version, h->mcode_date);
2762
2763 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
2764 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
2765
2766 printk(" control_flag 0x%x\n", h->control_flag);
2767}
2768
2769/*
2770 * asc_prt_adv_scsi_req_q()
2771 *
2772 * Display an ADV_SCSI_REQ_Q structure.
2773 */
2774static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
2775{
2776 int sg_blk_cnt;
2777 struct asc_sg_block *sg_ptr;
2778
2779 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
2780
2781 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
2782 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
2783
2784 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
2785 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
2786
2787 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
2788 (ulong)le32_to_cpu(q->data_cnt),
2789 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
2790
2791 printk
2792 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
2793 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
2794
2795 printk(" sg_working_ix 0x%x, target_cmd %u\n",
2796 q->sg_working_ix, q->target_cmd);
2797
2798 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
2799 (ulong)le32_to_cpu(q->scsiq_rptr),
2800 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
2801
2802 /* Display the request's ADV_SG_BLOCK structures. */
2803 if (q->sg_list_ptr != NULL) {
2804 sg_blk_cnt = 0;
2805 while (1) {
2806 /*
2807 * 'sg_ptr' is a physical address. Convert it to a virtual
2808 * address by indexing 'sg_blk_cnt' into the virtual address
2809 * array 'sg_list_ptr'.
2810 *
2811 * XXX - Assumes all SG physical blocks are virtually contiguous.
2812 */
2813 sg_ptr =
2814 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
2815 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
2816 if (sg_ptr->sg_ptr == 0) {
2817 break;
2818 }
2819 sg_blk_cnt++;
2820 }
2821 }
2822}
2823
2824/*
2825 * asc_prt_adv_sgblock()
2826 *
2827 * Display an ADV_SG_BLOCK structure.
2828 */
2829static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
2830{
2831 int i;
2832
2833 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
2834 (ulong)b, sgblockno);
2835 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
2836 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
2837 BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
2838 if (b->sg_ptr != 0)
2839 BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
2840 for (i = 0; i < b->sg_cnt; i++) {
2841 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
2842 i, (ulong)b->sg_list[i].sg_addr,
2843 (ulong)b->sg_list[i].sg_count);
2844 }
2845}
2846
2847/*
2848 * asc_prt_hex()
2849 *
2850 * Print hexadecimal output in 4 byte groupings 32 bytes
2851 * or 8 double-words per line.
2852 */
2853static void asc_prt_hex(char *f, uchar *s, int l)
2854{
2855 int i;
2856 int j;
2857 int k;
2858 int m;
2859
2860 printk("%s: (%d bytes)\n", f, l);
2861
2862 for (i = 0; i < l; i += 32) {
2863
2864 /* Display a maximum of 8 double-words per line. */
2865 if ((k = (l - i) / 4) >= 8) {
2866 k = 8;
2867 m = 0;
2868 } else {
2869 m = (l - i) % 4;
2870 }
2871
2872 for (j = 0; j < k; j++) {
2873 printk(" %2.2X%2.2X%2.2X%2.2X",
2874 (unsigned)s[i + (j * 4)],
2875 (unsigned)s[i + (j * 4) + 1],
2876 (unsigned)s[i + (j * 4) + 2],
2877 (unsigned)s[i + (j * 4) + 3]);
2878 }
2879
2880 switch (m) {
2881 case 0:
2882 default:
2883 break;
2884 case 1:
2885 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
2886 break;
2887 case 2:
2888 printk(" %2.2X%2.2X",
2889 (unsigned)s[i + (j * 4)],
2890 (unsigned)s[i + (j * 4) + 1]);
2891 break;
2892 case 3:
2893 printk(" %2.2X%2.2X%2.2X",
2894 (unsigned)s[i + (j * 4) + 1],
2895 (unsigned)s[i + (j * 4) + 2],
2896 (unsigned)s[i + (j * 4) + 3]);
2897 break;
2898 }
2899
2900 printk("\n");
2901 }
2902}
2903#endif /* ADVANSYS_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
2905/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 * advansys_info()
2907 *
2908 * Return suitable for printing on the console with the argument
2909 * adapter's configuration information.
2910 *
2911 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
2912 * otherwise the static 'info' array will be overrun.
2913 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002914static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002916 static char info[ASC_INFO_SIZE];
2917 asc_board_t *boardp;
2918 ASC_DVC_VAR *asc_dvc_varp;
2919 ADV_DVC_VAR *adv_dvc_varp;
2920 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002921 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002923 boardp = ASC_BOARDP(shost);
2924 if (ASC_NARROW_BOARD(boardp)) {
2925 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
2926 ASC_DBG(1, "advansys_info: begin\n");
2927 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
2928 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
2929 ASC_IS_ISAPNP) {
2930 busname = "ISA PnP";
2931 } else {
2932 busname = "ISA";
2933 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002934 sprintf(info,
2935 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
2936 ASC_VERSION, busname,
2937 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002938 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002939 boardp->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002940 } else {
2941 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
2942 busname = "VL";
2943 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
2944 busname = "EISA";
2945 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
2946 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
2947 == ASC_IS_PCI_ULTRA) {
2948 busname = "PCI Ultra";
2949 } else {
2950 busname = "PCI";
2951 }
2952 } else {
2953 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002954 ASC_PRINT2("advansys_info: board %d: unknown "
2955 "bus type %d\n", boardp->id,
2956 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002957 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002958 sprintf(info,
2959 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002960 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04002961 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002962 boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002963 }
2964 } else {
2965 /*
2966 * Wide Adapter Information
2967 *
2968 * Memory-mapped I/O is used instead of I/O space to access
2969 * the adapter, but display the I/O Port range. The Memory
2970 * I/O address is displayed through the driver /proc file.
2971 */
2972 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
2973 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002974 widename = "Ultra-Wide";
2975 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002976 widename = "Ultra2-Wide";
2977 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002978 widename = "Ultra3-Wide";
2979 }
2980 sprintf(info,
2981 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
2982 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcoxd361db42007-10-02 21:55:29 -04002983 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002984 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002985 BUG_ON(strlen(info) >= ASC_INFO_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002986 ASC_DBG(1, "advansys_info: end\n");
2987 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988}
2989
Matthew Wilcox51219352007-10-02 21:55:22 -04002990#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991/*
Matthew Wilcox51219352007-10-02 21:55:22 -04002992 * asc_prt_line()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 *
Matthew Wilcox51219352007-10-02 21:55:22 -04002994 * If 'cp' is NULL print to the console, otherwise print to a buffer.
2995 *
2996 * Return 0 if printing to the console, otherwise return the number of
2997 * bytes written to the buffer.
2998 *
2999 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
3000 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 */
Matthew Wilcox51219352007-10-02 21:55:22 -04003002static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003{
Matthew Wilcox51219352007-10-02 21:55:22 -04003004 va_list args;
3005 int ret;
3006 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Matthew Wilcox51219352007-10-02 21:55:22 -04003008 va_start(args, fmt);
3009 ret = vsprintf(s, fmt, args);
3010 BUG_ON(ret >= ASC_PRTLINE_SIZE);
3011 if (buf == NULL) {
3012 (void)printk(s);
3013 ret = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003014 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04003015 ret = min(buflen, ret);
3016 memcpy(buf, s, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003017 }
Matthew Wilcox51219352007-10-02 21:55:22 -04003018 va_end(args);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003019 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020}
3021
3022/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 * asc_prt_board_devices()
3024 *
3025 * Print driver information for devices attached to the board.
3026 *
3027 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3028 * cf. asc_prt_line().
3029 *
3030 * Return the number of characters copied into 'cp'. No more than
3031 * 'cplen' characters will be copied to 'cp'.
3032 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003033static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003035 asc_board_t *boardp;
3036 int leftlen;
3037 int totlen;
3038 int len;
3039 int chip_scsi_id;
3040 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003042 boardp = ASC_BOARDP(shost);
3043 leftlen = cplen;
3044 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003046 len = asc_prt_line(cp, leftlen,
3047 "\nDevice Information for AdvanSys SCSI Host %d:\n",
3048 shost->host_no);
3049 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003051 if (ASC_NARROW_BOARD(boardp)) {
3052 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3053 } else {
3054 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003057 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
3058 ASC_PRT_NEXT();
3059 for (i = 0; i <= ADV_MAX_TID; i++) {
3060 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
3061 len = asc_prt_line(cp, leftlen, " %X,", i);
3062 ASC_PRT_NEXT();
3063 }
3064 }
3065 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
3066 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003068 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069}
3070
3071/*
3072 * Display Wide Board BIOS Information.
3073 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003074static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003076 asc_board_t *boardp;
3077 int leftlen;
3078 int totlen;
3079 int len;
3080 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003082 boardp = ASC_BOARDP(shost);
3083 leftlen = cplen;
3084 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003086 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
3087 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003089 /*
3090 * If the BIOS saved a valid signature, then fill in
3091 * the BIOS code segment base address.
3092 */
3093 if (boardp->bios_signature != 0x55AA) {
3094 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
3095 ASC_PRT_NEXT();
3096 len = asc_prt_line(cp, leftlen,
3097 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
3098 ASC_PRT_NEXT();
3099 len = asc_prt_line(cp, leftlen,
3100 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
3101 ASC_PRT_NEXT();
3102 } else {
3103 major = (boardp->bios_version >> 12) & 0xF;
3104 minor = (boardp->bios_version >> 8) & 0xF;
3105 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003107 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
3108 major, minor,
3109 letter >= 26 ? '?' : letter + 'A');
3110 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003112 /*
3113 * Current available ROM BIOS release is 3.1I for UW
3114 * and 3.2I for U2W. This code doesn't differentiate
3115 * UW and U2W boards.
3116 */
3117 if (major < 3 || (major <= 3 && minor < 1) ||
3118 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
3119 len = asc_prt_line(cp, leftlen,
3120 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
3121 ASC_PRT_NEXT();
3122 len = asc_prt_line(cp, leftlen,
3123 "ftp://ftp.connectcom.net/pub\n");
3124 ASC_PRT_NEXT();
3125 }
3126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003128 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129}
3130
3131/*
3132 * Add serial number to information bar if signature AAh
3133 * is found in at bit 15-9 (7 bits) of word 1.
3134 *
3135 * Serial Number consists fo 12 alpha-numeric digits.
3136 *
3137 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
3138 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
3139 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
3140 * 5 - Product revision (A-J) Word0: " "
3141 *
3142 * Signature Word1: 15-9 (7 bits)
3143 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
3144 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
3145 *
3146 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
3147 *
3148 * Note 1: Only production cards will have a serial number.
3149 *
3150 * Note 2: Signature is most significant 7 bits (0xFE).
3151 *
3152 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
3153 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003154static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003156 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003158 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
3159 return ASC_FALSE;
3160 } else {
3161 /*
3162 * First word - 6 digits.
3163 */
3164 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003166 /* Product type - 1st digit. */
3167 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
3168 /* Product type is P=Prototype */
3169 *cp += 0x8;
3170 }
3171 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003173 /* Manufacturing location - 2nd digit. */
3174 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003176 /* Product ID - 3rd, 4th digits. */
3177 num = w & 0x3FF;
3178 *cp++ = '0' + (num / 100);
3179 num %= 100;
3180 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003182 /* Product revision - 5th digit. */
3183 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003185 /*
3186 * Second word
3187 */
3188 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003190 /*
3191 * Year - 6th digit.
3192 *
3193 * If bit 15 of third word is set, then the
3194 * last digit of the year is greater than 7.
3195 */
3196 if (serialnum[2] & 0x8000) {
3197 *cp++ = '8' + ((w & 0x1C0) >> 6);
3198 } else {
3199 *cp++ = '0' + ((w & 0x1C0) >> 6);
3200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003202 /* Week of year - 7th, 8th digits. */
3203 num = w & 0x003F;
3204 *cp++ = '0' + num / 10;
3205 num %= 10;
3206 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003208 /*
3209 * Third word
3210 */
3211 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003213 /* Serial number - 9th digit. */
3214 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003216 /* 10th, 11th, 12th digits. */
3217 num = w % 1000;
3218 *cp++ = '0' + num / 100;
3219 num %= 100;
3220 *cp++ = '0' + num / 10;
3221 num %= 10;
3222 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003224 *cp = '\0'; /* Null Terminate the string. */
3225 return ASC_TRUE;
3226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
3229/*
3230 * asc_prt_asc_board_eeprom()
3231 *
3232 * Print board EEPROM configuration.
3233 *
3234 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3235 * cf. asc_prt_line().
3236 *
3237 * Return the number of characters copied into 'cp'. No more than
3238 * 'cplen' characters will be copied to 'cp'.
3239 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003240static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003242 asc_board_t *boardp;
3243 ASC_DVC_VAR *asc_dvc_varp;
3244 int leftlen;
3245 int totlen;
3246 int len;
3247 ASCEEP_CONFIG *ep;
3248 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003250 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003252 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003254 boardp = ASC_BOARDP(shost);
3255 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3256 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003258 leftlen = cplen;
3259 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003261 len = asc_prt_line(cp, leftlen,
3262 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3263 shost->host_no);
3264 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003266 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
3267 == ASC_TRUE) {
3268 len =
3269 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3270 serialstr);
3271 ASC_PRT_NEXT();
3272 } else {
3273 if (ep->adapter_info[5] == 0xBB) {
3274 len = asc_prt_line(cp, leftlen,
3275 " Default Settings Used for EEPROM-less Adapter.\n");
3276 ASC_PRT_NEXT();
3277 } else {
3278 len = asc_prt_line(cp, leftlen,
3279 " Serial Number Signature Not Present.\n");
3280 ASC_PRT_NEXT();
3281 }
3282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003284 len = asc_prt_line(cp, leftlen,
3285 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3286 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
3287 ep->max_tag_qng);
3288 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003290 len = asc_prt_line(cp, leftlen,
3291 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
3292 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003294 len = asc_prt_line(cp, leftlen, " Target ID: ");
3295 ASC_PRT_NEXT();
3296 for (i = 0; i <= ASC_MAX_TID; i++) {
3297 len = asc_prt_line(cp, leftlen, " %d", i);
3298 ASC_PRT_NEXT();
3299 }
3300 len = asc_prt_line(cp, leftlen, "\n");
3301 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003303 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3304 ASC_PRT_NEXT();
3305 for (i = 0; i <= ASC_MAX_TID; i++) {
3306 len = asc_prt_line(cp, leftlen, " %c",
3307 (ep->
3308 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3309 'N');
3310 ASC_PRT_NEXT();
3311 }
3312 len = asc_prt_line(cp, leftlen, "\n");
3313 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003315 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3316 ASC_PRT_NEXT();
3317 for (i = 0; i <= ASC_MAX_TID; i++) {
3318 len = asc_prt_line(cp, leftlen, " %c",
3319 (ep->
3320 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3321 'N');
3322 ASC_PRT_NEXT();
3323 }
3324 len = asc_prt_line(cp, leftlen, "\n");
3325 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003327 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3328 ASC_PRT_NEXT();
3329 for (i = 0; i <= ASC_MAX_TID; i++) {
3330 len = asc_prt_line(cp, leftlen, " %c",
3331 (ep->
3332 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3333 'N');
3334 ASC_PRT_NEXT();
3335 }
3336 len = asc_prt_line(cp, leftlen, "\n");
3337 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003339 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3340 ASC_PRT_NEXT();
3341 for (i = 0; i <= ASC_MAX_TID; i++) {
3342 len = asc_prt_line(cp, leftlen, " %c",
3343 (ep->
3344 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3345 'N');
3346 ASC_PRT_NEXT();
3347 }
3348 len = asc_prt_line(cp, leftlen, "\n");
3349 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350
3351#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003352 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3353 len = asc_prt_line(cp, leftlen,
3354 " Host ISA DMA speed: %d MB/S\n",
3355 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
3356 ASC_PRT_NEXT();
3357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358#endif /* CONFIG_ISA */
3359
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003360 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361}
3362
3363/*
3364 * asc_prt_adv_board_eeprom()
3365 *
3366 * Print board EEPROM configuration.
3367 *
3368 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3369 * cf. asc_prt_line().
3370 *
3371 * Return the number of characters copied into 'cp'. No more than
3372 * 'cplen' characters will be copied to 'cp'.
3373 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003374static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003376 asc_board_t *boardp;
3377 ADV_DVC_VAR *adv_dvc_varp;
3378 int leftlen;
3379 int totlen;
3380 int len;
3381 int i;
3382 char *termstr;
3383 uchar serialstr[13];
3384 ADVEEP_3550_CONFIG *ep_3550 = NULL;
3385 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
3386 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
3387 ushort word;
3388 ushort *wordp;
3389 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003391 boardp = ASC_BOARDP(shost);
3392 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3393 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3394 ep_3550 = &boardp->eep_config.adv_3550_eep;
3395 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3396 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
3397 } else {
3398 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
3399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003401 leftlen = cplen;
3402 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003404 len = asc_prt_line(cp, leftlen,
3405 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
3406 shost->host_no);
3407 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003409 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3410 wordp = &ep_3550->serial_number_word1;
3411 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3412 wordp = &ep_38C0800->serial_number_word1;
3413 } else {
3414 wordp = &ep_38C1600->serial_number_word1;
3415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003417 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
3418 len =
3419 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
3420 serialstr);
3421 ASC_PRT_NEXT();
3422 } else {
3423 len = asc_prt_line(cp, leftlen,
3424 " Serial Number Signature Not Present.\n");
3425 ASC_PRT_NEXT();
3426 }
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 len = asc_prt_line(cp, leftlen,
3430 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3431 ep_3550->adapter_scsi_id,
3432 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
3433 ASC_PRT_NEXT();
3434 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3435 len = asc_prt_line(cp, leftlen,
3436 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3437 ep_38C0800->adapter_scsi_id,
3438 ep_38C0800->max_host_qng,
3439 ep_38C0800->max_dvc_qng);
3440 ASC_PRT_NEXT();
3441 } else {
3442 len = asc_prt_line(cp, leftlen,
3443 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
3444 ep_38C1600->adapter_scsi_id,
3445 ep_38C1600->max_host_qng,
3446 ep_38C1600->max_dvc_qng);
3447 ASC_PRT_NEXT();
3448 }
3449 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3450 word = ep_3550->termination;
3451 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3452 word = ep_38C0800->termination_lvd;
3453 } else {
3454 word = ep_38C1600->termination_lvd;
3455 }
3456 switch (word) {
3457 case 1:
3458 termstr = "Low Off/High Off";
3459 break;
3460 case 2:
3461 termstr = "Low Off/High On";
3462 break;
3463 case 3:
3464 termstr = "Low On/High On";
3465 break;
3466 default:
3467 case 0:
3468 termstr = "Automatic";
3469 break;
3470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003472 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3473 len = asc_prt_line(cp, leftlen,
3474 " termination: %u (%s), bios_ctrl: 0x%x\n",
3475 ep_3550->termination, termstr,
3476 ep_3550->bios_ctrl);
3477 ASC_PRT_NEXT();
3478 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3479 len = asc_prt_line(cp, leftlen,
3480 " termination: %u (%s), bios_ctrl: 0x%x\n",
3481 ep_38C0800->termination_lvd, termstr,
3482 ep_38C0800->bios_ctrl);
3483 ASC_PRT_NEXT();
3484 } else {
3485 len = asc_prt_line(cp, leftlen,
3486 " termination: %u (%s), bios_ctrl: 0x%x\n",
3487 ep_38C1600->termination_lvd, termstr,
3488 ep_38C1600->bios_ctrl);
3489 ASC_PRT_NEXT();
3490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003492 len = asc_prt_line(cp, leftlen, " Target ID: ");
3493 ASC_PRT_NEXT();
3494 for (i = 0; i <= ADV_MAX_TID; i++) {
3495 len = asc_prt_line(cp, leftlen, " %X", i);
3496 ASC_PRT_NEXT();
3497 }
3498 len = asc_prt_line(cp, leftlen, "\n");
3499 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003501 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3502 word = ep_3550->disc_enable;
3503 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3504 word = ep_38C0800->disc_enable;
3505 } else {
3506 word = ep_38C1600->disc_enable;
3507 }
3508 len = asc_prt_line(cp, leftlen, " Disconnects: ");
3509 ASC_PRT_NEXT();
3510 for (i = 0; i <= ADV_MAX_TID; i++) {
3511 len = asc_prt_line(cp, leftlen, " %c",
3512 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3513 ASC_PRT_NEXT();
3514 }
3515 len = asc_prt_line(cp, leftlen, "\n");
3516 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003518 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3519 word = ep_3550->tagqng_able;
3520 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3521 word = ep_38C0800->tagqng_able;
3522 } else {
3523 word = ep_38C1600->tagqng_able;
3524 }
3525 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
3526 ASC_PRT_NEXT();
3527 for (i = 0; i <= ADV_MAX_TID; i++) {
3528 len = asc_prt_line(cp, leftlen, " %c",
3529 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3530 ASC_PRT_NEXT();
3531 }
3532 len = asc_prt_line(cp, leftlen, "\n");
3533 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003535 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3536 word = ep_3550->start_motor;
3537 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3538 word = ep_38C0800->start_motor;
3539 } else {
3540 word = ep_38C1600->start_motor;
3541 }
3542 len = asc_prt_line(cp, leftlen, " Start Motor: ");
3543 ASC_PRT_NEXT();
3544 for (i = 0; i <= ADV_MAX_TID; i++) {
3545 len = asc_prt_line(cp, leftlen, " %c",
3546 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3547 ASC_PRT_NEXT();
3548 }
3549 len = asc_prt_line(cp, leftlen, "\n");
3550 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003552 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3553 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
3554 ASC_PRT_NEXT();
3555 for (i = 0; i <= ADV_MAX_TID; i++) {
3556 len = asc_prt_line(cp, leftlen, " %c",
3557 (ep_3550->
3558 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
3559 'Y' : 'N');
3560 ASC_PRT_NEXT();
3561 }
3562 len = asc_prt_line(cp, leftlen, "\n");
3563 ASC_PRT_NEXT();
3564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003566 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3567 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
3568 ASC_PRT_NEXT();
3569 for (i = 0; i <= ADV_MAX_TID; i++) {
3570 len = asc_prt_line(cp, leftlen, " %c",
3571 (ep_3550->
3572 ultra_able & ADV_TID_TO_TIDMASK(i))
3573 ? 'Y' : 'N');
3574 ASC_PRT_NEXT();
3575 }
3576 len = asc_prt_line(cp, leftlen, "\n");
3577 ASC_PRT_NEXT();
3578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003580 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
3581 word = ep_3550->wdtr_able;
3582 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
3583 word = ep_38C0800->wdtr_able;
3584 } else {
3585 word = ep_38C1600->wdtr_able;
3586 }
3587 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
3588 ASC_PRT_NEXT();
3589 for (i = 0; i <= ADV_MAX_TID; i++) {
3590 len = asc_prt_line(cp, leftlen, " %c",
3591 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
3592 ASC_PRT_NEXT();
3593 }
3594 len = asc_prt_line(cp, leftlen, "\n");
3595 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003597 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
3598 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
3599 len = asc_prt_line(cp, leftlen,
3600 " Synchronous Transfer Speed (Mhz):\n ");
3601 ASC_PRT_NEXT();
3602 for (i = 0; i <= ADV_MAX_TID; i++) {
3603 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003605 if (i == 0) {
3606 sdtr_speed = adv_dvc_varp->sdtr_speed1;
3607 } else if (i == 4) {
3608 sdtr_speed = adv_dvc_varp->sdtr_speed2;
3609 } else if (i == 8) {
3610 sdtr_speed = adv_dvc_varp->sdtr_speed3;
3611 } else if (i == 12) {
3612 sdtr_speed = adv_dvc_varp->sdtr_speed4;
3613 }
3614 switch (sdtr_speed & ADV_MAX_TID) {
3615 case 0:
3616 speed_str = "Off";
3617 break;
3618 case 1:
3619 speed_str = " 5";
3620 break;
3621 case 2:
3622 speed_str = " 10";
3623 break;
3624 case 3:
3625 speed_str = " 20";
3626 break;
3627 case 4:
3628 speed_str = " 40";
3629 break;
3630 case 5:
3631 speed_str = " 80";
3632 break;
3633 default:
3634 speed_str = "Unk";
3635 break;
3636 }
3637 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
3638 ASC_PRT_NEXT();
3639 if (i == 7) {
3640 len = asc_prt_line(cp, leftlen, "\n ");
3641 ASC_PRT_NEXT();
3642 }
3643 sdtr_speed >>= 4;
3644 }
3645 len = asc_prt_line(cp, leftlen, "\n");
3646 ASC_PRT_NEXT();
3647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003649 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650}
3651
3652/*
3653 * asc_prt_driver_conf()
3654 *
3655 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3656 * cf. asc_prt_line().
3657 *
3658 * Return the number of characters copied into 'cp'. No more than
3659 * 'cplen' characters will be copied to 'cp'.
3660 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003661static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003663 asc_board_t *boardp;
3664 int leftlen;
3665 int totlen;
3666 int len;
3667 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003669 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003671 leftlen = cplen;
3672 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003674 len = asc_prt_line(cp, leftlen,
3675 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
3676 shost->host_no);
3677 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003679 len = asc_prt_line(cp, leftlen,
3680 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
3681 shost->host_busy, shost->last_reset, shost->max_id,
3682 shost->max_lun, shost->max_channel);
3683 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003685 len = asc_prt_line(cp, leftlen,
3686 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
3687 shost->unique_id, shost->can_queue, shost->this_id,
3688 shost->sg_tablesize, shost->cmd_per_lun);
3689 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003691 len = asc_prt_line(cp, leftlen,
3692 " unchecked_isa_dma %d, use_clustering %d\n",
3693 shost->unchecked_isa_dma, shost->use_clustering);
3694 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003696 len = asc_prt_line(cp, leftlen,
3697 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
3698 boardp->flags, boardp->last_reset, jiffies,
3699 boardp->asc_n_io_port);
3700 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003702 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003703 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003705 if (ASC_NARROW_BOARD(boardp)) {
3706 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
3707 } else {
3708 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
3709 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003711 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712}
3713
3714/*
3715 * asc_prt_asc_board_info()
3716 *
3717 * Print dynamic board configuration information.
3718 *
3719 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3720 * cf. asc_prt_line().
3721 *
3722 * Return the number of characters copied into 'cp'. No more than
3723 * 'cplen' characters will be copied to 'cp'.
3724 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003725static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003727 asc_board_t *boardp;
3728 int chip_scsi_id;
3729 int leftlen;
3730 int totlen;
3731 int len;
3732 ASC_DVC_VAR *v;
3733 ASC_DVC_CFG *c;
3734 int i;
3735 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003737 boardp = ASC_BOARDP(shost);
3738 v = &boardp->dvc_var.asc_dvc_var;
3739 c = &boardp->dvc_cfg.asc_dvc_cfg;
3740 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003742 leftlen = cplen;
3743 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003745 len = asc_prt_line(cp, leftlen,
3746 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3747 shost->host_no);
3748 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003750 len = asc_prt_line(cp, leftlen,
3751 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
3752 c->chip_version, c->lib_version, c->lib_serial_no,
3753 c->mcode_date);
3754 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003756 len = asc_prt_line(cp, leftlen,
3757 " mcode_version 0x%x, err_code %u\n",
3758 c->mcode_version, v->err_code);
3759 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003761 /* Current number of commands waiting for the host. */
3762 len = asc_prt_line(cp, leftlen,
3763 " Total Command Pending: %d\n", v->cur_total_qng);
3764 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003766 len = asc_prt_line(cp, leftlen, " Command Queuing:");
3767 ASC_PRT_NEXT();
3768 for (i = 0; i <= ASC_MAX_TID; i++) {
3769 if ((chip_scsi_id == i) ||
3770 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3771 continue;
3772 }
3773 len = asc_prt_line(cp, leftlen, " %X:%c",
3774 i,
3775 (v->
3776 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
3777 'Y' : 'N');
3778 ASC_PRT_NEXT();
3779 }
3780 len = asc_prt_line(cp, leftlen, "\n");
3781 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003783 /* Current number of commands waiting for a device. */
3784 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
3785 ASC_PRT_NEXT();
3786 for (i = 0; i <= ASC_MAX_TID; i++) {
3787 if ((chip_scsi_id == i) ||
3788 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3789 continue;
3790 }
3791 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
3792 ASC_PRT_NEXT();
3793 }
3794 len = asc_prt_line(cp, leftlen, "\n");
3795 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003797 /* Current limit on number of commands that can be sent to a device. */
3798 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
3799 ASC_PRT_NEXT();
3800 for (i = 0; i <= ASC_MAX_TID; i++) {
3801 if ((chip_scsi_id == i) ||
3802 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3803 continue;
3804 }
3805 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
3806 ASC_PRT_NEXT();
3807 }
3808 len = asc_prt_line(cp, leftlen, "\n");
3809 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003811 /* Indicate whether the device has returned queue full status. */
3812 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
3813 ASC_PRT_NEXT();
3814 for (i = 0; i <= ASC_MAX_TID; i++) {
3815 if ((chip_scsi_id == i) ||
3816 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3817 continue;
3818 }
3819 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
3820 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
3821 i, boardp->queue_full_cnt[i]);
3822 } else {
3823 len = asc_prt_line(cp, leftlen, " %X:N", i);
3824 }
3825 ASC_PRT_NEXT();
3826 }
3827 len = asc_prt_line(cp, leftlen, "\n");
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, " Synchronous Transfer:");
3831 ASC_PRT_NEXT();
3832 for (i = 0; i <= ASC_MAX_TID; i++) {
3833 if ((chip_scsi_id == i) ||
3834 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3835 continue;
3836 }
3837 len = asc_prt_line(cp, leftlen, " %X:%c",
3838 i,
3839 (v->
3840 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3841 'N');
3842 ASC_PRT_NEXT();
3843 }
3844 len = asc_prt_line(cp, leftlen, "\n");
3845 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003847 for (i = 0; i <= ASC_MAX_TID; i++) {
3848 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003850 if ((chip_scsi_id == i) ||
3851 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
3852 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
3853 continue;
3854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003856 len = asc_prt_line(cp, leftlen, " %X:", i);
3857 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003859 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
3860 len = asc_prt_line(cp, leftlen, " Asynchronous");
3861 ASC_PRT_NEXT();
3862 } else {
3863 syn_period_ix =
3864 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
3865 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003867 len = asc_prt_line(cp, leftlen,
3868 " Transfer Period Factor: %d (%d.%d Mhz),",
3869 v->sdtr_period_tbl[syn_period_ix],
3870 250 /
3871 v->sdtr_period_tbl[syn_period_ix],
3872 ASC_TENTHS(250,
3873 v->
3874 sdtr_period_tbl
3875 [syn_period_ix]));
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, " REQ/ACK Offset: %d",
3879 boardp->
3880 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
3881 ASC_PRT_NEXT();
3882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003884 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
3885 len = asc_prt_line(cp, leftlen, "*\n");
3886 renegotiate = 1;
3887 } else {
3888 len = asc_prt_line(cp, leftlen, "\n");
3889 }
3890 ASC_PRT_NEXT();
3891 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003893 if (renegotiate) {
3894 len = asc_prt_line(cp, leftlen,
3895 " * = Re-negotiation pending before next command.\n");
3896 ASC_PRT_NEXT();
3897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003899 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900}
3901
3902/*
3903 * asc_prt_adv_board_info()
3904 *
3905 * Print dynamic board configuration information.
3906 *
3907 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
3908 * cf. asc_prt_line().
3909 *
3910 * Return the number of characters copied into 'cp'. No more than
3911 * 'cplen' characters will be copied to 'cp'.
3912 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003913static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003915 asc_board_t *boardp;
3916 int leftlen;
3917 int totlen;
3918 int len;
3919 int i;
3920 ADV_DVC_VAR *v;
3921 ADV_DVC_CFG *c;
3922 AdvPortAddr iop_base;
3923 ushort chip_scsi_id;
3924 ushort lramword;
3925 uchar lrambyte;
3926 ushort tagqng_able;
3927 ushort sdtr_able, wdtr_able;
3928 ushort wdtr_done, sdtr_done;
3929 ushort period = 0;
3930 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003932 boardp = ASC_BOARDP(shost);
3933 v = &boardp->dvc_var.adv_dvc_var;
3934 c = &boardp->dvc_cfg.adv_dvc_cfg;
3935 iop_base = v->iop_base;
3936 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003938 leftlen = cplen;
3939 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003941 len = asc_prt_line(cp, leftlen,
3942 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
3943 shost->host_no);
3944 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003946 len = asc_prt_line(cp, leftlen,
3947 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
3948 v->iop_base,
3949 AdvReadWordRegister(iop_base,
3950 IOPW_SCSI_CFG1) & CABLE_DETECT,
3951 v->err_code);
3952 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003954 len = asc_prt_line(cp, leftlen,
3955 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
3956 c->chip_version, c->lib_version, c->mcode_date,
3957 c->mcode_version);
3958 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003960 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
3961 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
3962 ASC_PRT_NEXT();
3963 for (i = 0; i <= ADV_MAX_TID; i++) {
3964 if ((chip_scsi_id == i) ||
3965 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3966 continue;
3967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003969 len = asc_prt_line(cp, leftlen, " %X:%c",
3970 i,
3971 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
3972 'N');
3973 ASC_PRT_NEXT();
3974 }
3975 len = asc_prt_line(cp, leftlen, "\n");
3976 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003978 len = asc_prt_line(cp, leftlen, " Queue Limit:");
3979 ASC_PRT_NEXT();
3980 for (i = 0; i <= ADV_MAX_TID; i++) {
3981 if ((chip_scsi_id == i) ||
3982 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
3983 continue;
3984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003986 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
3987 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003989 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
3990 ASC_PRT_NEXT();
3991 }
3992 len = asc_prt_line(cp, leftlen, "\n");
3993 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003995 len = asc_prt_line(cp, leftlen, " Command Pending:");
3996 ASC_PRT_NEXT();
3997 for (i = 0; i <= ADV_MAX_TID; i++) {
3998 if ((chip_scsi_id == i) ||
3999 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4000 continue;
4001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004003 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
4004 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004006 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
4007 ASC_PRT_NEXT();
4008 }
4009 len = asc_prt_line(cp, leftlen, "\n");
4010 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004012 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
4013 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
4014 ASC_PRT_NEXT();
4015 for (i = 0; i <= ADV_MAX_TID; i++) {
4016 if ((chip_scsi_id == i) ||
4017 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4018 continue;
4019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004021 len = asc_prt_line(cp, leftlen, " %X:%c",
4022 i,
4023 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4024 'N');
4025 ASC_PRT_NEXT();
4026 }
4027 len = asc_prt_line(cp, leftlen, "\n");
4028 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004030 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
4031 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
4032 ASC_PRT_NEXT();
4033 for (i = 0; i <= ADV_MAX_TID; i++) {
4034 if ((chip_scsi_id == i) ||
4035 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4036 continue;
4037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004039 AdvReadWordLram(iop_base,
4040 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
4041 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004043 len = asc_prt_line(cp, leftlen, " %X:%d",
4044 i, (lramword & 0x8000) ? 16 : 8);
4045 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004047 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
4048 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
4049 len = asc_prt_line(cp, leftlen, "*");
4050 ASC_PRT_NEXT();
4051 renegotiate = 1;
4052 }
4053 }
4054 len = asc_prt_line(cp, leftlen, "\n");
4055 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004057 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
4058 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
4059 ASC_PRT_NEXT();
4060 for (i = 0; i <= ADV_MAX_TID; i++) {
4061 if ((chip_scsi_id == i) ||
4062 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
4063 continue;
4064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004066 len = asc_prt_line(cp, leftlen, " %X:%c",
4067 i,
4068 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4069 'N');
4070 ASC_PRT_NEXT();
4071 }
4072 len = asc_prt_line(cp, leftlen, "\n");
4073 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004075 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
4076 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004078 AdvReadWordLram(iop_base,
4079 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
4080 lramword);
4081 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004083 if ((chip_scsi_id == i) ||
4084 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
4085 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
4086 continue;
4087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004089 len = asc_prt_line(cp, leftlen, " %X:", i);
4090 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004092 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
4093 len = asc_prt_line(cp, leftlen, " Asynchronous");
4094 ASC_PRT_NEXT();
4095 } else {
4096 len =
4097 asc_prt_line(cp, leftlen,
4098 " Transfer Period Factor: ");
4099 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004101 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
4102 len =
4103 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
4104 ASC_PRT_NEXT();
4105 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
4106 len =
4107 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
4108 ASC_PRT_NEXT();
4109 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004111 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004113 if (period == 0) { /* Should never happen. */
4114 len =
4115 asc_prt_line(cp, leftlen,
4116 "%d (? Mhz), ");
4117 ASC_PRT_NEXT();
4118 } else {
4119 len = asc_prt_line(cp, leftlen,
4120 "%d (%d.%d Mhz),",
4121 period, 250 / period,
4122 ASC_TENTHS(250,
4123 period));
4124 ASC_PRT_NEXT();
4125 }
4126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004128 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
4129 lramword & 0x1F);
4130 ASC_PRT_NEXT();
4131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004133 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
4134 len = asc_prt_line(cp, leftlen, "*\n");
4135 renegotiate = 1;
4136 } else {
4137 len = asc_prt_line(cp, leftlen, "\n");
4138 }
4139 ASC_PRT_NEXT();
4140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004142 if (renegotiate) {
4143 len = asc_prt_line(cp, leftlen,
4144 " * = Re-negotiation pending before next command.\n");
4145 ASC_PRT_NEXT();
4146 }
4147
4148 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149}
4150
4151/*
4152 * asc_proc_copy()
4153 *
4154 * Copy proc information to a read buffer taking into account the current
4155 * read offset in the file and the remaining space in the read buffer.
4156 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004157static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004159 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004161 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004163 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
4164 (unsigned)offset, (unsigned)advoffset, cplen);
4165 if (offset <= advoffset) {
4166 /* Read offset below current offset, copy everything. */
4167 cnt = min(cplen, leftlen);
4168 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
4169 (ulong)curbuf, (ulong)cp, cnt);
4170 memcpy(curbuf, cp, cnt);
4171 } else if (offset < advoffset + cplen) {
4172 /* Read offset within current range, partial copy. */
4173 cnt = (advoffset + cplen) - offset;
4174 cp = (cp + cplen) - cnt;
4175 cnt = min(cnt, leftlen);
4176 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
4177 (ulong)curbuf, (ulong)cp, cnt);
4178 memcpy(curbuf, cp, cnt);
4179 }
4180 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181}
4182
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183#ifdef ADVANSYS_STATS
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184/*
4185 * asc_prt_board_stats()
4186 *
4187 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4188 * cf. asc_prt_line().
4189 *
4190 * Return the number of characters copied into 'cp'. No more than
4191 * 'cplen' characters will be copied to 'cp'.
4192 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004193static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004195 int leftlen;
4196 int totlen;
4197 int len;
4198 struct asc_stats *s;
4199 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004201 leftlen = cplen;
4202 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004204 boardp = ASC_BOARDP(shost);
4205 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004207 len = asc_prt_line(cp, leftlen,
4208 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
4209 shost->host_no);
4210 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004212 len = asc_prt_line(cp, leftlen,
4213 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
4214 s->queuecommand, s->reset, s->biosparam,
4215 s->interrupt);
4216 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004218 len = asc_prt_line(cp, leftlen,
4219 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
4220 s->callback, s->done, s->build_error,
4221 s->adv_build_noreq, s->adv_build_nosg);
4222 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004224 len = asc_prt_line(cp, leftlen,
4225 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
4226 s->exe_noerror, s->exe_busy, s->exe_error,
4227 s->exe_unknown);
4228 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004230 /*
4231 * Display data transfer statistics.
4232 */
4233 if (s->cont_cnt > 0) {
4234 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
4235 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004237 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
4238 s->cont_xfer / 2,
4239 ASC_TENTHS(s->cont_xfer, 2));
4240 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004242 /* Contiguous transfer average size */
4243 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
4244 (s->cont_xfer / 2) / s->cont_cnt,
4245 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
4246 ASC_PRT_NEXT();
4247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004249 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004251 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
4252 s->sg_cnt, s->sg_elem);
4253 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004255 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
4256 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
4257 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004259 /* Scatter gather transfer statistics */
4260 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
4261 s->sg_elem / s->sg_cnt,
4262 ASC_TENTHS(s->sg_elem, s->sg_cnt));
4263 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004265 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
4266 (s->sg_xfer / 2) / s->sg_elem,
4267 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
4268 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004270 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
4271 (s->sg_xfer / 2) / s->sg_cnt,
4272 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
4273 ASC_PRT_NEXT();
4274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004276 /*
4277 * Display request queuing statistics.
4278 */
4279 len = asc_prt_line(cp, leftlen,
4280 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
4281 HZ);
4282 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004284 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286#endif /* ADVANSYS_STATS */
4287
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288/*
Matthew Wilcox51219352007-10-02 21:55:22 -04004289 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
4290 *
4291 * *buffer: I/O buffer
4292 * **start: if inout == FALSE pointer into buffer where user read should start
4293 * offset: current offset into a /proc/scsi/advansys/[0...] file
4294 * length: length of buffer
4295 * hostno: Scsi_Host host_no
4296 * inout: TRUE - user is writing; FALSE - user is reading
4297 *
4298 * Return the number of bytes read from or written to a
4299 * /proc/scsi/advansys/[0...] file.
4300 *
4301 * Note: This function uses the per board buffer 'prtbuf' which is
4302 * allocated when the board is initialized in advansys_detect(). The
4303 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4304 * used to write to the buffer. The way asc_proc_copy() is written
4305 * if 'prtbuf' is too small it will not be overwritten. Instead the
4306 * user just won't get all the available statistics.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 */
Matthew Wilcox51219352007-10-02 21:55:22 -04004308static int
4309advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
4310 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004312 asc_board_t *boardp;
Matthew Wilcox51219352007-10-02 21:55:22 -04004313 char *cp;
4314 int cplen;
4315 int cnt;
4316 int totcnt;
4317 int leftlen;
4318 char *curbuf;
4319 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Matthew Wilcox51219352007-10-02 21:55:22 -04004321 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Matthew Wilcox51219352007-10-02 21:55:22 -04004323 /*
4324 * User write not supported.
4325 */
4326 if (inout == TRUE) {
4327 return (-ENOSYS);
4328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329
Matthew Wilcox51219352007-10-02 21:55:22 -04004330 /*
4331 * User read of /proc/scsi/advansys/[0...] file.
4332 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
Matthew Wilcox51219352007-10-02 21:55:22 -04004334 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Matthew Wilcox51219352007-10-02 21:55:22 -04004336 /* Copy read data starting at the beginning of the buffer. */
4337 *start = buffer;
4338 curbuf = buffer;
4339 advoffset = 0;
4340 totcnt = 0;
4341 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Matthew Wilcox51219352007-10-02 21:55:22 -04004343 /*
4344 * Get board configuration information.
4345 *
4346 * advansys_info() returns the board string from its own static buffer.
4347 */
4348 cp = (char *)advansys_info(shost);
4349 strcat(cp, "\n");
4350 cplen = strlen(cp);
4351 /* Copy board information. */
4352 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4353 totcnt += cnt;
4354 leftlen -= cnt;
4355 if (leftlen == 0) {
4356 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4357 return totcnt;
4358 }
4359 advoffset += cplen;
4360 curbuf += cnt;
4361
4362 /*
4363 * Display Wide Board BIOS Information.
4364 */
Matthew Wilcox9a256fa2007-10-02 21:55:28 -04004365 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004366 cp = boardp->prtbuf;
4367 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
4368 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4369 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
4370 cplen);
4371 totcnt += cnt;
4372 leftlen -= cnt;
4373 if (leftlen == 0) {
4374 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4375 return totcnt;
4376 }
4377 advoffset += cplen;
4378 curbuf += cnt;
4379 }
4380
4381 /*
4382 * Display driver information for each device attached to the board.
4383 */
4384 cp = boardp->prtbuf;
4385 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
4386 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4387 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4388 totcnt += cnt;
4389 leftlen -= cnt;
4390 if (leftlen == 0) {
4391 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4392 return totcnt;
4393 }
4394 advoffset += cplen;
4395 curbuf += cnt;
4396
4397 /*
4398 * Display EEPROM configuration for the board.
4399 */
4400 cp = boardp->prtbuf;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004401 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04004402 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004403 } else {
Matthew Wilcox51219352007-10-02 21:55:22 -04004404 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004405 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004406 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4407 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4408 totcnt += cnt;
4409 leftlen -= cnt;
4410 if (leftlen == 0) {
4411 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4412 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004413 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004414 advoffset += cplen;
4415 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
Matthew Wilcox51219352007-10-02 21:55:22 -04004417 /*
4418 * Display driver configuration and information for the board.
4419 */
4420 cp = boardp->prtbuf;
4421 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
4422 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4423 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4424 totcnt += cnt;
4425 leftlen -= cnt;
4426 if (leftlen == 0) {
4427 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4428 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004429 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004430 advoffset += cplen;
4431 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Matthew Wilcox51219352007-10-02 21:55:22 -04004433#ifdef ADVANSYS_STATS
4434 /*
4435 * Display driver statistics for the board.
4436 */
4437 cp = boardp->prtbuf;
4438 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
4439 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4440 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4441 totcnt += cnt;
4442 leftlen -= cnt;
4443 if (leftlen == 0) {
4444 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4445 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004446 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004447 advoffset += cplen;
4448 curbuf += cnt;
4449#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Matthew Wilcox51219352007-10-02 21:55:22 -04004451 /*
4452 * Display Asc Library dynamic configuration information
4453 * for the board.
4454 */
4455 cp = boardp->prtbuf;
4456 if (ASC_NARROW_BOARD(boardp)) {
4457 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
4458 } else {
4459 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004460 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004461 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
4462 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4463 totcnt += cnt;
4464 leftlen -= cnt;
4465 if (leftlen == 0) {
4466 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4467 return totcnt;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004468 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004469 advoffset += cplen;
4470 curbuf += cnt;
4471
4472 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4473
4474 return totcnt;
4475}
4476#endif /* CONFIG_PROC_FS */
4477
4478static void asc_scsi_done(struct scsi_cmnd *scp)
4479{
4480 struct asc_board *boardp = ASC_BOARDP(scp->device->host);
4481
4482 if (scp->use_sg)
4483 dma_unmap_sg(boardp->dev,
4484 (struct scatterlist *)scp->request_buffer,
4485 scp->use_sg, scp->sc_data_direction);
4486 else if (scp->request_bufflen)
4487 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
4488 scp->request_bufflen, scp->sc_data_direction);
4489
4490 ASC_STATS(scp->device->host, done);
4491
4492 scp->scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493}
4494
Matthew Wilcox51219352007-10-02 21:55:22 -04004495static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496{
Matthew Wilcox51219352007-10-02 21:55:22 -04004497 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498
Matthew Wilcox51219352007-10-02 21:55:22 -04004499 val = AscGetChipControl(iop_base) &
4500 (~
4501 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
4502 CC_CHIP_RESET));
4503 if (bank == 1) {
4504 val |= CC_BANK_ONE;
4505 } else if (bank == 2) {
4506 val |= CC_DIAG | CC_BANK_ONE;
4507 } else {
4508 val &= ~CC_BANK_ONE;
4509 }
4510 AscSetChipControl(iop_base, val);
4511 return;
4512}
4513
4514static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
4515{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004516 AscSetBank(iop_base, 1);
Matthew Wilcox51219352007-10-02 21:55:22 -04004517 AscWriteChipIH(iop_base, ins_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004518 AscSetBank(iop_base, 0);
Matthew Wilcox51219352007-10-02 21:55:22 -04004519 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520}
4521
Matthew Wilcox51219352007-10-02 21:55:22 -04004522static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523{
Matthew Wilcox51219352007-10-02 21:55:22 -04004524 AscSetChipControl(iop_base, 0);
4525 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4526 return (0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004527 }
Matthew Wilcox51219352007-10-02 21:55:22 -04004528 return (1);
4529}
4530
4531static int AscStopChip(PortAddr iop_base)
4532{
4533 uchar cc_val;
4534
4535 cc_val =
4536 AscGetChipControl(iop_base) &
4537 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
4538 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
4539 AscSetChipIH(iop_base, INS_HALT);
4540 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4541 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
4542 return (0);
4543 }
4544 return (1);
4545}
4546
4547static int AscIsChipHalted(PortAddr iop_base)
4548{
4549 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
4550 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
4551 return (1);
4552 }
4553 }
4554 return (0);
4555}
4556
4557static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
4558{
4559 PortAddr iop_base;
4560 int i = 10;
4561
4562 iop_base = asc_dvc->iop_base;
4563 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
4564 && (i-- > 0)) {
4565 mdelay(100);
4566 }
4567 AscStopChip(iop_base);
4568 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
4569 udelay(60);
4570 AscSetChipIH(iop_base, INS_RFLAG_WTM);
4571 AscSetChipIH(iop_base, INS_HALT);
4572 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
4573 AscSetChipControl(iop_base, CC_HALT);
4574 mdelay(200);
4575 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
4576 AscSetChipStatus(iop_base, 0);
4577 return (AscIsChipHalted(iop_base));
4578}
4579
4580static int AscFindSignature(PortAddr iop_base)
4581{
4582 ushort sig_word;
4583
4584 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
4585 iop_base, AscGetChipSignatureByte(iop_base));
4586 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
4587 ASC_DBG2(1,
4588 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
4589 iop_base, AscGetChipSignatureWord(iop_base));
4590 sig_word = AscGetChipSignatureWord(iop_base);
4591 if ((sig_word == (ushort)ASC_1000_ID0W) ||
4592 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
4593 return (1);
4594 }
4595 }
4596 return (0);
4597}
4598
4599static void AscEnableInterrupt(PortAddr iop_base)
4600{
4601 ushort cfg;
4602
4603 cfg = AscGetChipCfgLsw(iop_base);
4604 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
4605 return;
4606}
4607
4608static void AscDisableInterrupt(PortAddr iop_base)
4609{
4610 ushort cfg;
4611
4612 cfg = AscGetChipCfgLsw(iop_base);
4613 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
4614 return;
4615}
4616
4617static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
4618{
4619 unsigned char byte_data;
4620 unsigned short word_data;
4621
4622 if (isodd_word(addr)) {
4623 AscSetChipLramAddr(iop_base, addr - 1);
4624 word_data = AscGetChipLramData(iop_base);
4625 byte_data = (word_data >> 8) & 0xFF;
4626 } else {
4627 AscSetChipLramAddr(iop_base, addr);
4628 word_data = AscGetChipLramData(iop_base);
4629 byte_data = word_data & 0xFF;
4630 }
4631 return byte_data;
4632}
4633
4634static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
4635{
4636 ushort word_data;
4637
4638 AscSetChipLramAddr(iop_base, addr);
4639 word_data = AscGetChipLramData(iop_base);
4640 return (word_data);
4641}
4642
4643#if CC_VERY_LONG_SG_LIST
4644static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
4645{
4646 ushort val_low, val_high;
4647 ASC_DCNT dword_data;
4648
4649 AscSetChipLramAddr(iop_base, addr);
4650 val_low = AscGetChipLramData(iop_base);
4651 val_high = AscGetChipLramData(iop_base);
4652 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
4653 return (dword_data);
4654}
4655#endif /* CC_VERY_LONG_SG_LIST */
4656
4657static void
4658AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
4659{
4660 int i;
4661
4662 AscSetChipLramAddr(iop_base, s_addr);
4663 for (i = 0; i < words; i++) {
4664 AscSetChipLramData(iop_base, set_wval);
4665 }
4666}
4667
4668static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
4669{
4670 AscSetChipLramAddr(iop_base, addr);
4671 AscSetChipLramData(iop_base, word_val);
4672 return;
4673}
4674
4675static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
4676{
4677 ushort word_data;
4678
4679 if (isodd_word(addr)) {
4680 addr--;
4681 word_data = AscReadLramWord(iop_base, addr);
4682 word_data &= 0x00FF;
4683 word_data |= (((ushort)byte_val << 8) & 0xFF00);
4684 } else {
4685 word_data = AscReadLramWord(iop_base, addr);
4686 word_data &= 0xFF00;
4687 word_data |= ((ushort)byte_val & 0x00FF);
4688 }
4689 AscWriteLramWord(iop_base, addr, word_data);
4690 return;
4691}
4692
4693/*
4694 * Copy 2 bytes to LRAM.
4695 *
4696 * The source data is assumed to be in little-endian order in memory
4697 * and is maintained in little-endian order when written to LRAM.
4698 */
4699static void
4700AscMemWordCopyPtrToLram(PortAddr iop_base,
4701 ushort s_addr, uchar *s_buffer, int words)
4702{
4703 int i;
4704
4705 AscSetChipLramAddr(iop_base, s_addr);
4706 for (i = 0; i < 2 * words; i += 2) {
4707 /*
4708 * On a little-endian system the second argument below
4709 * produces a little-endian ushort which is written to
4710 * LRAM in little-endian order. On a big-endian system
4711 * the second argument produces a big-endian ushort which
4712 * is "transparently" byte-swapped by outpw() and written
4713 * in little-endian order to LRAM.
4714 */
4715 outpw(iop_base + IOP_RAM_DATA,
4716 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
4717 }
4718 return;
4719}
4720
4721/*
4722 * Copy 4 bytes to LRAM.
4723 *
4724 * The source data is assumed to be in little-endian order in memory
4725 * and is maintained in little-endian order when writen to LRAM.
4726 */
4727static void
4728AscMemDWordCopyPtrToLram(PortAddr iop_base,
4729 ushort s_addr, uchar *s_buffer, int dwords)
4730{
4731 int i;
4732
4733 AscSetChipLramAddr(iop_base, s_addr);
4734 for (i = 0; i < 4 * dwords; i += 4) {
4735 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
4736 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
4737 }
4738 return;
4739}
4740
4741/*
4742 * Copy 2 bytes from LRAM.
4743 *
4744 * The source data is assumed to be in little-endian order in LRAM
4745 * and is maintained in little-endian order when written to memory.
4746 */
4747static void
4748AscMemWordCopyPtrFromLram(PortAddr iop_base,
4749 ushort s_addr, uchar *d_buffer, int words)
4750{
4751 int i;
4752 ushort word;
4753
4754 AscSetChipLramAddr(iop_base, s_addr);
4755 for (i = 0; i < 2 * words; i += 2) {
4756 word = inpw(iop_base + IOP_RAM_DATA);
4757 d_buffer[i] = word & 0xff;
4758 d_buffer[i + 1] = (word >> 8) & 0xff;
4759 }
4760 return;
4761}
4762
4763static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
4764{
4765 ASC_DCNT sum;
4766 int i;
4767
4768 sum = 0L;
4769 for (i = 0; i < words; i++, s_addr += 2) {
4770 sum += AscReadLramWord(iop_base, s_addr);
4771 }
4772 return (sum);
4773}
4774
4775static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
4776{
4777 uchar i;
4778 ushort s_addr;
4779 PortAddr iop_base;
4780 ushort warn_code;
4781
4782 iop_base = asc_dvc->iop_base;
4783 warn_code = 0;
4784 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
4785 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
4786 64) >> 1));
4787 i = ASC_MIN_ACTIVE_QNO;
4788 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
4789 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4790 (uchar)(i + 1));
4791 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4792 (uchar)(asc_dvc->max_total_qng));
4793 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4794 (uchar)i);
4795 i++;
4796 s_addr += ASC_QBLK_SIZE;
4797 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
4798 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4799 (uchar)(i + 1));
4800 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4801 (uchar)(i - 1));
4802 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4803 (uchar)i);
4804 }
4805 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
4806 (uchar)ASC_QLINK_END);
4807 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
4808 (uchar)(asc_dvc->max_total_qng - 1));
4809 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
4810 (uchar)asc_dvc->max_total_qng);
4811 i++;
4812 s_addr += ASC_QBLK_SIZE;
4813 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
4814 i++, s_addr += ASC_QBLK_SIZE) {
4815 AscWriteLramByte(iop_base,
4816 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
4817 AscWriteLramByte(iop_base,
4818 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
4819 AscWriteLramByte(iop_base,
4820 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
4821 }
4822 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004823}
4824
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004825static ASC_DCNT
4826AscLoadMicroCode(PortAddr iop_base,
4827 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004829 ASC_DCNT chksum;
4830 ushort mcode_word_size;
4831 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004832
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004833 /* Write the microcode buffer starting at LRAM address 0. */
4834 mcode_word_size = (ushort)(mcode_size >> 1);
4835 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
4836 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004838 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
4839 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
4840 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
4841 (ushort)ASC_CODE_SEC_BEG,
4842 (ushort)((mcode_size -
4843 s_addr - (ushort)
4844 ASC_CODE_SEC_BEG) /
4845 2));
4846 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
4847 (ulong)mcode_chksum);
4848 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
4849 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
4850 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851}
4852
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004854static uchar _asc_mcode_buf[] = {
4855 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004856 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
4861 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4862 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004863 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004864 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
4865 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
4866 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004867 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004868 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
4869 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
4870 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004871 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004872 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
4873 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
4874 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004875 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004876 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
4877 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
4878 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004879 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004880 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
4881 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
4882 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004883 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004884 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
4885 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
4886 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004887 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004888 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
4889 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
4890 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004891 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004892 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
4893 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
4894 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004895 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004896 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
4897 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
4898 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004899 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004900 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
4901 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
4902 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004903 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004904 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
4905 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
4906 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004907 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004908 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
4909 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
4910 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004911 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004912 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
4913 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
4914 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004915 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004916 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
4917 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
4918 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004919 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004920 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
4921 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
4922 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004923 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004924 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
4925 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
4926 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004927 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004928 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
4929 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
4930 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004931 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004932 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
4933 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
4934 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004935 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004936 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
4937 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
4938 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004939 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004940 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
4941 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
4942 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004943 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004944 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
4945 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
4946 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004947 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004948 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
4949 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
4950 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004951 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004952 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
4953 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
4954 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004955 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004956 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
4957 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
4958 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004959 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004960 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
4961 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
4962 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004963 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004964 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
4965 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
4966 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004967 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004968 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
4969 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
4970 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004971 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004972 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
4973 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
4974 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004975 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004976 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
4977 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
4978 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004979 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004980 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
4981 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
4982 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004983 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004984 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
4985 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
4986 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004987 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004988 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
4989 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
4990 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004991 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004992 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
4993 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
4994 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004995 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06004996 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
4997 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
4998 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004999 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005000 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
5001 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
5002 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005003 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005004 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
5005 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
5006 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005007 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005008 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
5009 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
5010 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005011 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005012 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
5013 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
5014 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005015 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005016 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
5017 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
5018 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005019 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005020 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
5021 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
5022 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005023 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005024 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
5025 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
5026 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005027 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005028 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
5029 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
5030 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005031 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005032 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
5033 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
5034 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005035 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005036 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
5037 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
5038 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005039 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005040 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
5041 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
5042 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005043 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005044 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
5045 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
5046 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047};
5048
Matthew Wilcox51219352007-10-02 21:55:22 -04005049static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005050static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005053static unsigned char _adv_asc3550_buf[] = {
5054 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005055 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
5056 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
5057 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005058 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005059 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
5060 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
5061 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005062 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005063 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
5064 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
5065 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005066 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005067 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
5068 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
5069 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005070 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005071 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
5072 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
5073 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005074 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005075 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
5076 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
5077 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005078 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005079 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
5080 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
5081 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005082 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005083 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
5084 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
5085 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005086 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005087 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
5088 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
5089 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005090 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005091 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
5092 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
5093 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005094 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005095 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
5096 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
5097 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005098 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005099 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
5100 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5101 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005102 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005103 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
5104 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
5105 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005106 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005107 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
5108 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5109 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005110 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005111 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
5112 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
5113 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005114 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005115 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
5116 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
5117 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005118 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005119 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
5120 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
5121 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005122 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005123 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
5124 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
5125 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005126 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005127 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
5128 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
5129 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005130 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005131 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
5132 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
5133 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005134 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005135 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
5136 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
5137 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005138 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005139 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
5140 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
5141 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005142 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005143 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
5144 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
5145 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005146 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005147 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
5148 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
5149 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005150 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005151 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
5152 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
5153 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005154 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005155 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
5156 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
5157 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005158 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005159 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
5160 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
5161 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005162 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005163 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
5164 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
5165 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005166 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005167 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
5168 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
5169 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005170 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005171 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
5172 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
5173 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005174 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005175 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
5176 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
5177 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005178 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005179 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
5180 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
5181 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005182 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005183 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
5184 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
5185 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005186 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005187 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
5188 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
5189 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005190 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005191 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
5192 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
5193 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005194 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005195 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
5196 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
5197 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005198 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005199 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
5200 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
5201 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005202 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005203 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
5204 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
5205 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005206 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005207 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
5208 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
5209 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005210 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005211 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
5212 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
5213 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005214 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005215 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
5216 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
5217 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005218 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005219 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
5220 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
5221 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005222 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005223 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
5224 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
5225 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005226 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005227 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
5228 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
5229 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005230 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005231 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
5232 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
5233 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005234 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005235 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
5236 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
5237 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005238 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005239 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
5240 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
5241 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005242 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005243 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
5244 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
5245 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005246 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005247 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
5248 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
5249 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005250 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005251 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
5252 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
5253 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005254 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005255 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
5256 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
5257 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005258 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005259 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
5260 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
5261 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005262 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005263 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
5264 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
5265 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005266 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005267 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
5268 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
5269 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005270 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005271 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
5272 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
5273 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005274 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005275 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
5276 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
5277 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005278 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005279 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
5280 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
5281 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005282 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005283 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
5284 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
5285 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005286 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005287 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
5288 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
5289 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005290 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005291 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
5292 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
5293 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005294 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005295 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
5296 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
5297 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005298 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005299 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
5300 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
5301 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005302 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005303 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
5304 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
5305 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005306 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005307 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
5308 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
5309 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005310 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005311 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
5312 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
5313 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005314 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005315 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
5316 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
5317 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005318 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005319 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
5320 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
5321 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005322 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005323 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
5324 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
5325 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005326 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005327 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
5328 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
5329 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005330 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005331 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
5332 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
5333 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005334 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005335 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
5336 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
5337 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005338 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005339 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
5340 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
5341 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005342 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005343 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
5344 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
5345 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005346 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005347 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
5348 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
5349 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005350 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005351 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
5352 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
5353 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005354 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005355 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
5356 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
5357 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005358 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005359 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
5360 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
5361 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005362 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005363 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
5364 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
5365 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005366 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005367 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
5368 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
5369 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005370 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005371 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
5372 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
5373 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005374 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005375 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
5376 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
5377 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005378 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005379 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
5380 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
5381 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005382 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005383 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
5384 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
5385 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005386 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005387 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
5388 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
5389 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005390 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005391 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
5392 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
5393 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005394 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005395 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
5396 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
5397 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005398 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005399 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
5400 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
5401 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005402 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005403 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
5404 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
5405 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005406 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005407 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
5408 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
5409 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005410 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005411 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
5412 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
5413 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005414 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005415 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
5416 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
5417 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005418 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005419 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
5420 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
5421 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005422 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005423 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
5424 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
5425 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005426 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005427 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
5428 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
5429 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005430 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005431 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
5432 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
5433 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005434 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005435 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
5436 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
5437 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005438 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005439 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
5440 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
5441 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005442 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005443 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
5444 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
5445 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005446 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005447 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
5448 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
5449 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005450 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005451 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
5452 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
5453 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005454 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005455 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
5456 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
5457 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005458 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005459 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
5460 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
5461 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005462 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005463 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
5464 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
5465 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005466 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005467 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
5468 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
5469 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005470 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005471 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
5472 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473};
5474
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005475static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
5476static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477
5478/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005479static unsigned char _adv_asc38C0800_buf[] = {
5480 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005481 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
5482 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
5483 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005485 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
5486 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
5487 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005488 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005489 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
5490 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
5491 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005492 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005493 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
5494 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
5495 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005496 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005497 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
5498 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
5499 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005500 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005501 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
5502 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
5503 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005504 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005505 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
5506 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
5507 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005508 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005509 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
5510 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
5511 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005512 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005513 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
5514 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
5515 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005516 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005517 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
5518 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
5519 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005520 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005521 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
5522 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
5523 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005524 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005525 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
5526 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5527 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005528 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005529 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
5530 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
5531 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005532 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005533 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
5534 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
5535 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005536 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005537 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
5538 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
5539 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005540 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005541 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
5542 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
5543 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005544 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005545 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
5546 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
5547 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005548 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005549 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
5550 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
5551 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005552 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005553 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
5554 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
5555 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005556 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005557 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
5558 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
5559 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005560 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005561 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
5562 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
5563 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005564 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005565 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
5566 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
5567 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005568 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005569 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
5570 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
5571 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005572 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005573 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
5574 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
5575 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005576 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005577 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
5578 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
5579 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005580 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005581 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
5582 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
5583 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005584 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005585 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
5586 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
5587 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005588 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005589 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
5590 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
5591 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005592 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005593 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
5594 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
5595 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005596 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005597 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
5598 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
5599 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005600 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005601 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
5602 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
5603 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005604 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005605 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
5606 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
5607 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005608 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005609 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
5610 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
5611 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005612 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005613 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
5614 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
5615 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005616 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005617 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
5618 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
5619 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005620 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005621 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
5622 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
5623 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005624 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005625 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
5626 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
5627 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005628 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005629 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
5630 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
5631 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005632 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005633 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
5634 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
5635 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005636 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005637 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
5638 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
5639 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005640 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005641 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
5642 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
5643 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005644 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005645 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
5646 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
5647 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005648 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005649 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
5650 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
5651 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005652 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005653 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
5654 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
5655 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005656 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005657 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
5658 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
5659 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005660 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005661 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
5662 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
5663 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005664 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005665 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
5666 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
5667 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005668 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005669 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
5670 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
5671 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005672 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005673 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
5674 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
5675 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005676 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005677 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
5678 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
5679 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005680 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005681 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
5682 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
5683 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005684 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005685 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
5686 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
5687 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005688 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005689 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
5690 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
5691 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005692 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005693 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
5694 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
5695 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005696 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005697 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
5698 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
5699 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005700 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005701 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
5702 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
5703 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005704 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005705 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
5706 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
5707 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005708 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005709 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
5710 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
5711 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005712 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005713 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
5714 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
5715 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005716 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005717 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
5718 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
5719 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005720 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005721 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
5722 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
5723 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005724 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005725 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
5726 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
5727 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005728 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005729 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
5730 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
5731 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005732 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005733 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
5734 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
5735 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005736 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005737 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
5738 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
5739 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005740 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005741 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
5742 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
5743 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005744 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005745 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
5746 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
5747 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005748 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005749 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
5750 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
5751 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005752 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005753 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
5754 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
5755 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005756 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005757 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
5758 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
5759 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005760 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005761 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
5762 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
5763 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005764 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005765 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
5766 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
5767 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005768 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005769 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
5770 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
5771 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005772 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005773 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
5774 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
5775 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005776 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005777 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
5778 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
5779 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005780 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005781 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
5782 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
5783 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005784 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005785 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
5786 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
5787 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005788 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005789 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
5790 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
5791 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005792 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005793 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
5794 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
5795 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005796 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005797 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
5798 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
5799 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005800 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005801 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
5802 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
5803 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005804 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005805 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
5806 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
5807 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005808 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005809 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
5810 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
5811 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005812 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005813 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
5814 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
5815 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005816 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005817 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
5818 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
5819 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005820 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005821 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
5822 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
5823 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005824 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005825 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
5826 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5827 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005828 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005829 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
5830 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
5831 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005832 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005833 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
5834 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
5835 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005836 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005837 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
5838 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
5839 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005840 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005841 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
5842 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
5843 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005844 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005845 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
5846 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
5847 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005848 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005849 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
5850 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
5851 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005852 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005853 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
5854 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
5855 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005856 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005857 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
5858 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
5859 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005860 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005861 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
5862 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
5863 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005864 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005865 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
5866 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
5867 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005868 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005869 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
5870 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
5871 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005872 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005873 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
5874 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
5875 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005876 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005877 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
5878 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
5879 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005880 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005881 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
5882 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
5883 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005884 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005885 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
5886 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
5887 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005888 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005889 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
5890 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
5891 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005892 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005893 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
5894 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
5895 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005896 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005897 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
5898 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
5899 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005900 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005901 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
5902 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
5903 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005904 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005905 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
5906 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
5907 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005908 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005909 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
5910 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
5911 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005912 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005913 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
5914 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
5915 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005916 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005917 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
5918 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
5919 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005920 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005921 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
5922 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
5923 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005924 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925};
5926
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005927static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
5928static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929
5930/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005931static unsigned char _adv_asc38C1600_buf[] = {
5932 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005933 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
5934 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
5935 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005936 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005937 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
5938 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
5939 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005940 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005941 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
5942 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
5943 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005944 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005945 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
5946 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
5947 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005948 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005949 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
5950 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
5951 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005952 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005953 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
5954 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
5955 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005956 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005957 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
5958 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
5959 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005960 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005961 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
5962 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
5963 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005964 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005965 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
5966 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
5967 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005968 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005969 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
5970 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
5971 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005972 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005973 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
5974 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
5975 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005976 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005977 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
5978 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
5979 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005980 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005981 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
5982 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
5983 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005984 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005985 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
5986 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
5987 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005988 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005989 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
5990 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
5991 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005992 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005993 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
5994 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
5995 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005996 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06005997 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
5998 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
5999 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006000 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006001 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
6002 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
6003 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006004 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006005 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
6006 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
6007 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006008 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006009 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
6010 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
6011 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006012 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006013 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
6014 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
6015 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006016 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006017 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
6018 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
6019 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006020 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006021 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
6022 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
6023 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006024 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006025 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
6026 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
6027 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006028 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006029 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
6030 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
6031 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006032 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006033 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
6034 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
6035 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006036 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006037 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
6038 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
6039 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006040 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006041 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
6042 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
6043 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006044 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006045 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
6046 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
6047 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006048 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006049 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
6050 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
6051 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006052 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006053 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
6054 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
6055 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006056 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006057 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
6058 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
6059 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006060 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006061 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
6062 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
6063 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006064 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006065 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
6066 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
6067 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006068 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006069 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
6070 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
6071 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006072 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006073 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
6074 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
6075 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006076 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006077 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
6078 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
6079 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006080 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006081 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
6082 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
6083 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006084 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006085 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
6086 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
6087 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006088 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006089 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
6090 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
6091 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006092 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006093 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
6094 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
6095 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006096 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006097 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
6098 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
6099 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006100 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006101 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
6102 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
6103 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006104 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006105 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
6106 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
6107 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006108 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006109 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
6110 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
6111 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006112 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006113 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
6114 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
6115 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006116 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006117 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
6118 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
6119 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006120 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006121 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
6122 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
6123 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006124 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006125 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
6126 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
6127 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006128 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006129 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
6130 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
6131 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006132 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006133 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
6134 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
6135 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006136 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006137 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
6138 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
6139 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006140 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006141 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
6142 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
6143 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006144 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006145 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
6146 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
6147 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006148 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006149 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
6150 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
6151 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006152 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006153 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
6154 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
6155 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006156 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006157 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
6158 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
6159 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006160 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006161 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
6162 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
6163 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006164 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006165 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
6166 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
6167 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006168 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006169 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
6170 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
6171 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006172 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006173 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
6174 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
6175 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006176 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006177 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
6178 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
6179 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006180 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006181 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
6182 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
6183 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006184 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006185 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
6186 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
6187 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006188 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006189 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
6190 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
6191 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006192 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006193 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
6194 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
6195 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006196 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006197 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
6198 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
6199 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006200 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006201 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
6202 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
6203 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006204 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006205 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
6206 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
6207 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006208 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006209 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
6210 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
6211 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006212 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006213 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
6214 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
6215 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006216 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006217 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
6218 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
6219 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006220 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006221 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
6222 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
6223 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006224 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006225 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
6226 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
6227 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006228 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006229 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
6230 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
6231 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006232 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006233 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
6234 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
6235 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006236 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006237 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
6238 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
6239 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006240 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006241 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
6242 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
6243 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006244 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006245 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
6246 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
6247 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006248 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006249 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
6250 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
6251 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006252 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006253 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
6254 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
6255 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006256 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006257 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
6258 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
6259 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006260 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006261 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
6262 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
6263 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006264 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006265 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
6266 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
6267 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006268 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006269 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
6270 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
6271 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006272 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006273 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
6274 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
6275 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006276 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006277 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
6278 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
6279 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006280 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006281 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
6282 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
6283 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006284 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006285 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
6286 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
6287 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006288 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006289 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
6290 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
6291 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006292 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006293 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
6294 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
6295 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006296 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006297 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
6298 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
6299 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006300 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006301 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
6302 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
6303 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006304 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006305 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
6306 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
6307 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006308 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006309 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
6310 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
6311 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006312 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006313 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
6314 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
6315 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006316 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006317 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
6318 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
6319 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006321 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
6322 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
6323 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006324 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006325 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
6326 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
6327 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006328 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006329 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
6330 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
6331 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006332 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006333 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
6334 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
6335 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006336 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006337 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
6338 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
6339 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006340 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006341 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
6342 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
6343 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006344 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006345 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
6346 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
6347 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006348 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006349 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
6350 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
6351 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006352 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006353 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
6354 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
6355 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006356 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006357 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
6358 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
6359 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006360 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006361 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
6362 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
6363 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006364 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006365 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
6366 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
6367 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006368 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006369 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
6370 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
6371 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006372 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006373 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
6374 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
6375 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006376 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006377 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
6378 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
6379 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006380 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006381 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
6382 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
6383 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006384 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006385 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
6386 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
6387 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006388 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006389 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
6390 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
6391 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006392 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006393 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
6394 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
6395 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006396 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006397 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
6398 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
6399 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006400 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006401 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
6402 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
6403 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006404 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006405 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
6406 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
6407 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006408 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006409 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
6410 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
6411 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006412 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006413 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
6414 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
6415 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006416 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006417 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
6418 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
6419 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006420 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006421 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
6422 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
6423 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006424 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006425 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
6426 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
6427 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006428 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006429 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
6430 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
6431 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006432 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006433 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
6434 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
6435 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006436 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006437 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
6438 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
6439 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006440 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006441 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
6442 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
6443 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006444 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006445 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
6446 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
6447 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006448 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006449 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
6450 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
6451 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006452 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006453 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
6454 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
6455 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006456 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06006457 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
6458 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
6459 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460};
6461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006462static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
6463static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006464
Matthew Wilcox51219352007-10-02 21:55:22 -04006465static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006466{
Matthew Wilcox51219352007-10-02 21:55:22 -04006467 PortAddr iop_base;
6468 int i;
6469 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006470
Matthew Wilcox51219352007-10-02 21:55:22 -04006471 iop_base = asc_dvc->iop_base;
6472 AscPutRiscVarFreeQHead(iop_base, 1);
6473 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6474 AscPutVarFreeQHead(iop_base, 1);
6475 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6476 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6477 (uchar)((int)asc_dvc->max_total_qng + 1));
6478 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6479 (uchar)((int)asc_dvc->max_total_qng + 2));
6480 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
6481 asc_dvc->max_total_qng);
6482 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6483 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6484 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6485 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6486 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6487 AscPutQDoneInProgress(iop_base, 0);
6488 lram_addr = ASC_QADR_BEG;
6489 for (i = 0; i < 32; i++, lram_addr += 2) {
6490 AscWriteLramWord(iop_base, lram_addr, 0);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492}
6493
Matthew Wilcox51219352007-10-02 21:55:22 -04006494static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006495{
Matthew Wilcox51219352007-10-02 21:55:22 -04006496 int i;
6497 ushort warn_code;
6498 PortAddr iop_base;
6499 ASC_PADDR phy_addr;
6500 ASC_DCNT phy_size;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006501
Matthew Wilcox51219352007-10-02 21:55:22 -04006502 iop_base = asc_dvc->iop_base;
6503 warn_code = 0;
6504 for (i = 0; i <= ASC_MAX_TID; i++) {
6505 AscPutMCodeInitSDTRAtID(iop_base, i,
6506 asc_dvc->cfg->sdtr_period_offset[i]);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006507 }
6508
Matthew Wilcox51219352007-10-02 21:55:22 -04006509 AscInitQLinkVar(asc_dvc);
6510 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
6511 asc_dvc->cfg->disc_enable);
6512 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
6513 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006514
Matthew Wilcox51219352007-10-02 21:55:22 -04006515 /* Align overrun buffer on an 8 byte boundary. */
6516 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
6517 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
6518 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
6519 (uchar *)&phy_addr, 1);
6520 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
6521 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
6522 (uchar *)&phy_size, 1);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006523
Matthew Wilcox51219352007-10-02 21:55:22 -04006524 asc_dvc->cfg->mcode_date =
6525 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
6526 asc_dvc->cfg->mcode_version =
6527 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006528
Matthew Wilcox51219352007-10-02 21:55:22 -04006529 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6530 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6531 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
6532 return warn_code;
6533 }
6534 if (AscStartChip(iop_base) != 1) {
6535 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
6536 return warn_code;
6537 }
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006538
Matthew Wilcox51219352007-10-02 21:55:22 -04006539 return warn_code;
6540}
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006541
Matthew Wilcox51219352007-10-02 21:55:22 -04006542static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
6543{
6544 ushort warn_code;
6545 PortAddr iop_base;
6546
6547 iop_base = asc_dvc->iop_base;
6548 warn_code = 0;
6549 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
6550 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
6551 AscResetChipAndScsiBus(asc_dvc);
6552 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6553 }
6554 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
6555 if (asc_dvc->err_code != 0)
6556 return UW_ERR;
6557 if (!AscFindSignature(asc_dvc->iop_base)) {
6558 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
6559 return warn_code;
6560 }
6561 AscDisableInterrupt(iop_base);
6562 warn_code |= AscInitLram(asc_dvc);
6563 if (asc_dvc->err_code != 0)
6564 return UW_ERR;
6565 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
6566 (ulong)_asc_mcode_chksum);
6567 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
6568 _asc_mcode_size) != _asc_mcode_chksum) {
6569 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
6570 return warn_code;
6571 }
6572 warn_code |= AscInitMicroCodeVar(asc_dvc);
6573 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
6574 AscEnableInterrupt(iop_base);
6575 return warn_code;
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06006576}
6577
Linus Torvalds1da177e2005-04-16 15:20:36 -07006578/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006579 * Load the Microcode
6580 *
6581 * Write the microcode image to RISC memory starting at address 0.
6582 *
6583 * The microcode is stored compressed in the following format:
6584 *
6585 * 254 word (508 byte) table indexed by byte code followed
6586 * by the following byte codes:
6587 *
6588 * 1-Byte Code:
6589 * 00: Emit word 0 in table.
6590 * 01: Emit word 1 in table.
6591 * .
6592 * FD: Emit word 253 in table.
6593 *
6594 * Multi-Byte Code:
6595 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
6596 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
6597 *
6598 * Returns 0 or an error if the checksum doesn't match
6599 */
6600static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
6601 int memsize, int chksum)
6602{
6603 int i, j, end, len = 0;
6604 ADV_DCNT sum;
6605
6606 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6607
6608 for (i = 253 * 2; i < size; i++) {
6609 if (buf[i] == 0xff) {
6610 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
6611 for (j = 0; j < buf[i + 1]; j++) {
6612 AdvWriteWordAutoIncLram(iop_base, word);
6613 len += 2;
6614 }
6615 i += 3;
6616 } else if (buf[i] == 0xfe) {
6617 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
6618 AdvWriteWordAutoIncLram(iop_base, word);
6619 i += 2;
6620 len += 2;
6621 } else {
6622 unsigned char off = buf[i] * 2;
6623 unsigned short word = (buf[off + 1] << 8) | buf[off];
6624 AdvWriteWordAutoIncLram(iop_base, word);
6625 len += 2;
6626 }
6627 }
6628
6629 end = len;
6630
6631 while (len < memsize) {
6632 AdvWriteWordAutoIncLram(iop_base, 0);
6633 len += 2;
6634 }
6635
6636 /* Verify the microcode checksum. */
6637 sum = 0;
6638 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
6639
6640 for (len = 0; len < end; len += 2) {
6641 sum += AdvReadWordAutoIncLram(iop_base);
6642 }
6643
6644 if (sum != chksum)
6645 return ASC_IERR_MCODE_CHKSUM;
6646
6647 return 0;
6648}
6649
6650/*
Matthew Wilcox51219352007-10-02 21:55:22 -04006651 * DvcGetPhyAddr()
6652 *
6653 * Return the physical address of 'vaddr' and set '*lenp' to the
6654 * number of physically contiguous bytes that follow 'vaddr'.
6655 * 'flag' indicates the type of structure whose physical address
6656 * is being translated.
6657 *
6658 * Note: Because Linux currently doesn't page the kernel and all
6659 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
6660 */
6661ADV_PADDR
6662DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
6663 uchar *vaddr, ADV_SDCNT *lenp, int flag)
6664{
6665 ADV_PADDR paddr = virt_to_bus(vaddr);
6666
6667 ASC_DBG4(4, "DvcGetPhyAddr: vaddr 0x%p, lenp 0x%p *lenp %lu, paddr 0x%lx\n",
6668 vaddr, lenp, (ulong)*((ulong *)lenp), (ulong)paddr);
6669
6670 return paddr;
6671}
6672
6673static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
6674{
6675 ADV_CARR_T *carrp;
6676 ADV_SDCNT buf_size;
6677 ADV_PADDR carr_paddr;
6678
6679 BUG_ON(!asc_dvc->carrier_buf);
6680
6681 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
6682 asc_dvc->carr_freelist = NULL;
6683 if (carrp == asc_dvc->carrier_buf) {
6684 buf_size = ADV_CARRIER_BUFSIZE;
6685 } else {
6686 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
6687 }
6688
6689 do {
6690 /* Get physical address of the carrier 'carrp'. */
6691 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
6692 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
6693 (uchar *)carrp,
6694 (ADV_SDCNT *)&contig_len,
6695 ADV_IS_CARRIER_FLAG));
6696
6697 buf_size -= sizeof(ADV_CARR_T);
6698
6699 /*
6700 * If the current carrier is not physically contiguous, then
6701 * maybe there was a page crossing. Try the next carrier
6702 * aligned start address.
6703 */
6704 if (contig_len < sizeof(ADV_CARR_T)) {
6705 carrp++;
6706 continue;
6707 }
6708
6709 carrp->carr_pa = carr_paddr;
6710 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
6711
6712 /*
6713 * Insert the carrier at the beginning of the freelist.
6714 */
6715 carrp->next_vpa =
6716 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
6717 asc_dvc->carr_freelist = carrp;
6718
6719 carrp++;
6720 } while (buf_size > 0);
6721}
6722
6723/*
6724 * Send an idle command to the chip and wait for completion.
6725 *
6726 * Command completion is polled for once per microsecond.
6727 *
6728 * The function can be called from anywhere including an interrupt handler.
6729 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
6730 * functions to prevent reentrancy.
6731 *
6732 * Return Values:
6733 * ADV_TRUE - command completed successfully
6734 * ADV_FALSE - command failed
6735 * ADV_ERROR - command timed out
6736 */
6737static int
6738AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
6739 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
6740{
6741 int result;
6742 ADV_DCNT i, j;
6743 AdvPortAddr iop_base;
6744
6745 iop_base = asc_dvc->iop_base;
6746
6747 /*
6748 * Clear the idle command status which is set by the microcode
6749 * to a non-zero value to indicate when the command is completed.
6750 * The non-zero result is one of the IDLE_CMD_STATUS_* values
6751 */
6752 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
6753
6754 /*
6755 * Write the idle command value after the idle command parameter
6756 * has been written to avoid a race condition. If the order is not
6757 * followed, the microcode may process the idle command before the
6758 * parameters have been written to LRAM.
6759 */
6760 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
6761 cpu_to_le32(idle_cmd_parameter));
6762 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
6763
6764 /*
6765 * Tickle the RISC to tell it to process the idle command.
6766 */
6767 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
6768 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
6769 /*
6770 * Clear the tickle value. In the ASC-3550 the RISC flag
6771 * command 'clr_tickle_b' does not work unless the host
6772 * value is cleared.
6773 */
6774 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
6775 }
6776
6777 /* Wait for up to 100 millisecond for the idle command to timeout. */
6778 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
6779 /* Poll once each microsecond for command completion. */
6780 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
6781 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
6782 result);
6783 if (result != 0)
6784 return result;
6785 udelay(1);
6786 }
6787 }
6788
6789 BUG(); /* The idle command should never timeout. */
6790 return ADV_ERROR;
6791}
6792
6793/*
6794 * Reset SCSI Bus and purge all outstanding requests.
6795 *
6796 * Return Value:
6797 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
6798 * ADV_FALSE(0) - Microcode command failed.
6799 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
6800 * may be hung which requires driver recovery.
6801 */
6802static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
6803{
6804 int status;
6805
6806 /*
6807 * Send the SCSI Bus Reset idle start idle command which asserts
6808 * the SCSI Bus Reset signal.
6809 */
6810 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
6811 if (status != ADV_TRUE) {
6812 return status;
6813 }
6814
6815 /*
6816 * Delay for the specified SCSI Bus Reset hold time.
6817 *
6818 * The hold time delay is done on the host because the RISC has no
6819 * microsecond accurate timer.
6820 */
6821 udelay(ASC_SCSI_RESET_HOLD_TIME_US);
6822
6823 /*
6824 * Send the SCSI Bus Reset end idle command which de-asserts
6825 * the SCSI Bus Reset signal and purges any pending requests.
6826 */
6827 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
6828 if (status != ADV_TRUE) {
6829 return status;
6830 }
6831
6832 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
6833
6834 return status;
6835}
6836
6837/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838 * Initialize the ASC-3550.
6839 *
6840 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
6841 *
6842 * For a non-fatal error return a warning code. If there are no warnings
6843 * then 0 is returned.
6844 *
6845 * Needed after initialization for error recovery.
6846 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006847static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006848{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006849 AdvPortAddr iop_base;
6850 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006851 int begin_addr;
6852 int end_addr;
6853 ushort code_sum;
6854 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006855 int i;
6856 ushort scsi_cfg1;
6857 uchar tid;
6858 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
6859 ushort wdtr_able = 0, sdtr_able, tagqng_able;
6860 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006861
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006862 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006863 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006864 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006866 /*
6867 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
6868 */
6869 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006870 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006871 return ADV_ERROR;
6872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006873
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006874 warn_code = 0;
6875 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006877 /*
6878 * Save the RISC memory BIOS region before writing the microcode.
6879 * The BIOS may already be loaded and using its RISC LRAM region
6880 * so its region must be saved and restored.
6881 *
6882 * Note: This code makes the assumption, which is currently true,
6883 * that a chip reset does not clear RISC LRAM.
6884 */
6885 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6886 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6887 bios_mem[i]);
6888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006889
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006890 /*
6891 * Save current per TID negotiated values.
6892 */
6893 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
6894 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006896 bios_version =
6897 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
6898 major = (bios_version >> 12) & 0xF;
6899 minor = (bios_version >> 8) & 0xF;
6900 if (major < 3 || (major == 3 && minor == 1)) {
6901 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
6902 AdvReadWordLram(iop_base, 0x120, wdtr_able);
6903 } else {
6904 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6905 }
6906 }
6907 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
6908 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
6909 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
6910 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
6911 max_cmd[tid]);
6912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006913
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06006914 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
6915 _adv_asc3550_size, ADV_3550_MEMSIZE,
6916 _adv_asc3550_chksum);
6917 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006918 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006920 /*
6921 * Restore the RISC memory BIOS region.
6922 */
6923 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
6924 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
6925 bios_mem[i]);
6926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006927
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006928 /*
6929 * Calculate and write the microcode code checksum to the microcode
6930 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
6931 */
6932 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
6933 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
6934 code_sum = 0;
6935 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
6936 for (word = begin_addr; word < end_addr; word += 2) {
6937 code_sum += AdvReadWordAutoIncLram(iop_base);
6938 }
6939 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006941 /*
6942 * Read and save microcode version and date.
6943 */
6944 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
6945 asc_dvc->cfg->mcode_date);
6946 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
6947 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006949 /*
6950 * Set the chip type to indicate the ASC3550.
6951 */
6952 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006954 /*
6955 * If the PCI Configuration Command Register "Parity Error Response
6956 * Control" Bit was clear (0), then set the microcode variable
6957 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
6958 * to ignore DMA parity errors.
6959 */
6960 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
6961 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6962 word |= CONTROL_FLAG_IGNORE_PERR;
6963 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
6964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006966 /*
6967 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
6968 * threshold of 128 bytes. This register is only accessible to the host.
6969 */
6970 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
6971 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006973 /*
6974 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006975 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006976 * device reports it is capable of in Inquiry byte 7.
6977 *
6978 * If SCSI Bus Resets have been disabled, then directly set
6979 * SDTR and WDTR from the EEPROM configuration. This will allow
6980 * the BIOS and warm boot to work without a SCSI bus hang on
6981 * the Inquiry caused by host and target mismatched DTR values.
6982 * Without the SCSI Bus Reset, before an Inquiry a device can't
6983 * be assumed to be in Asynchronous, Narrow mode.
6984 */
6985 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
6986 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
6987 asc_dvc->wdtr_able);
6988 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
6989 asc_dvc->sdtr_able);
6990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006992 /*
6993 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
6994 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
6995 * bitmask. These values determine the maximum SDTR speed negotiated
6996 * with a device.
6997 *
6998 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
6999 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7000 * without determining here whether the device supports SDTR.
7001 *
7002 * 4-bit speed SDTR speed name
7003 * =========== ===============
7004 * 0000b (0x0) SDTR disabled
7005 * 0001b (0x1) 5 Mhz
7006 * 0010b (0x2) 10 Mhz
7007 * 0011b (0x3) 20 Mhz (Ultra)
7008 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
7009 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
7010 * 0110b (0x6) Undefined
7011 * .
7012 * 1111b (0xF) Undefined
7013 */
7014 word = 0;
7015 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7016 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
7017 /* Set Ultra speed for TID 'tid'. */
7018 word |= (0x3 << (4 * (tid % 4)));
7019 } else {
7020 /* Set Fast speed for TID 'tid'. */
7021 word |= (0x2 << (4 * (tid % 4)));
7022 }
7023 if (tid == 3) { /* Check if done with sdtr_speed1. */
7024 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
7025 word = 0;
7026 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
7027 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
7028 word = 0;
7029 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
7030 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
7031 word = 0;
7032 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
7033 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
7034 /* End of loop. */
7035 }
7036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007038 /*
7039 * Set microcode operating variable for the disconnect per TID bitmask.
7040 */
7041 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7042 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007043
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007044 /*
7045 * Set SCSI_CFG0 Microcode Default Value.
7046 *
7047 * The microcode will set the SCSI_CFG0 register using this value
7048 * after it is started below.
7049 */
7050 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7051 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7052 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007053
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007054 /*
7055 * Determine SCSI_CFG1 Microcode Default Value.
7056 *
7057 * The microcode will set the SCSI_CFG1 register using this value
7058 * after it is started below.
7059 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007061 /* Read current SCSI_CFG1 Register value. */
7062 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007063
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007064 /*
7065 * If all three connectors are in use, return an error.
7066 */
7067 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
7068 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
7069 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
7070 return ADV_ERROR;
7071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007072
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007073 /*
7074 * If the internal narrow cable is reversed all of the SCSI_CTRL
7075 * register signals will be set. Check for and return an error if
7076 * this condition is found.
7077 */
7078 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7079 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7080 return ADV_ERROR;
7081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007083 /*
7084 * If this is a differential board and a single-ended device
7085 * is attached to one of the connectors, return an error.
7086 */
7087 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
7088 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
7089 return ADV_ERROR;
7090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007092 /*
7093 * If automatic termination control is enabled, then set the
7094 * termination value based on a table listed in a_condor.h.
7095 *
7096 * If manual termination was specified with an EEPROM setting
7097 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
7098 * is ready to be 'ored' into SCSI_CFG1.
7099 */
7100 if (asc_dvc->cfg->termination == 0) {
7101 /*
7102 * The software always controls termination by setting TERM_CTL_SEL.
7103 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
7104 */
7105 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007107 switch (scsi_cfg1 & CABLE_DETECT) {
7108 /* TERM_CTL_H: on, TERM_CTL_L: on */
7109 case 0x3:
7110 case 0x7:
7111 case 0xB:
7112 case 0xD:
7113 case 0xE:
7114 case 0xF:
7115 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
7116 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007118 /* TERM_CTL_H: on, TERM_CTL_L: off */
7119 case 0x1:
7120 case 0x5:
7121 case 0x9:
7122 case 0xA:
7123 case 0xC:
7124 asc_dvc->cfg->termination |= TERM_CTL_H;
7125 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007127 /* TERM_CTL_H: off, TERM_CTL_L: off */
7128 case 0x2:
7129 case 0x6:
7130 break;
7131 }
7132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007133
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007134 /*
7135 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
7136 */
7137 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007138
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007139 /*
7140 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
7141 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
7142 * referenced, because the hardware internally inverts
7143 * the Termination High and Low bits if TERM_POL is set.
7144 */
7145 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007146
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007147 /*
7148 * Set SCSI_CFG1 Microcode Default Value
7149 *
7150 * Set filter value and possibly modified termination control
7151 * bits in the Microcode SCSI_CFG1 Register Value.
7152 *
7153 * The microcode will set the SCSI_CFG1 register using this value
7154 * after it is started below.
7155 */
7156 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
7157 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007158
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007159 /*
7160 * Set MEM_CFG Microcode Default Value
7161 *
7162 * The microcode will set the MEM_CFG register using this value
7163 * after it is started below.
7164 *
7165 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7166 * are defined.
7167 *
7168 * ASC-3550 has 8KB internal memory.
7169 */
7170 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7171 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007173 /*
7174 * Set SEL_MASK Microcode Default Value
7175 *
7176 * The microcode will set the SEL_MASK register using this value
7177 * after it is started below.
7178 */
7179 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7180 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007181
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007182 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007184 /*
7185 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7186 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007188 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7189 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7190 return ADV_ERROR;
7191 }
7192 asc_dvc->carr_freelist = (ADV_CARR_T *)
7193 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007194
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007195 /*
7196 * The first command issued will be placed in the stopper carrier.
7197 */
7198 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007200 /*
7201 * Set RISC ICQ physical address start value.
7202 */
7203 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007204
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007205 /*
7206 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7207 */
7208 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7209 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7210 return ADV_ERROR;
7211 }
7212 asc_dvc->carr_freelist = (ADV_CARR_T *)
7213 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007215 /*
7216 * The first command completed by the RISC will be placed in
7217 * the stopper.
7218 *
7219 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7220 * completed the RISC will set the ASC_RQ_STOPPER bit.
7221 */
7222 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007223
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007224 /*
7225 * Set RISC IRQ physical address start value.
7226 */
7227 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7228 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007230 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7231 (ADV_INTR_ENABLE_HOST_INTR |
7232 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007234 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7235 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007237 /* finally, finally, gentlemen, start your engine */
7238 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007240 /*
7241 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7242 * Resets should be performed. The RISC has to be running
7243 * to issue a SCSI Bus Reset.
7244 */
7245 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7246 /*
7247 * If the BIOS Signature is present in memory, restore the
7248 * BIOS Handshake Configuration Table and do not perform
7249 * a SCSI Bus Reset.
7250 */
7251 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7252 0x55AA) {
7253 /*
7254 * Restore per TID negotiated values.
7255 */
7256 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7257 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7258 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7259 tagqng_able);
7260 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7261 AdvWriteByteLram(iop_base,
7262 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7263 max_cmd[tid]);
7264 }
7265 } else {
7266 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7267 warn_code = ASC_WARN_BUSRESET_ERROR;
7268 }
7269 }
7270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007272 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007273}
7274
7275/*
7276 * Initialize the ASC-38C0800.
7277 *
7278 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
7279 *
7280 * For a non-fatal error return a warning code. If there are no warnings
7281 * then 0 is returned.
7282 *
7283 * Needed after initialization for error recovery.
7284 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007285static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007286{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007287 AdvPortAddr iop_base;
7288 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007289 int begin_addr;
7290 int end_addr;
7291 ushort code_sum;
7292 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007293 int i;
7294 ushort scsi_cfg1;
7295 uchar byte;
7296 uchar tid;
7297 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7298 ushort wdtr_able, sdtr_able, tagqng_able;
7299 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007300
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007301 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007302 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007303 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007304
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007305 /*
7306 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
7307 */
7308 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
7309 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7310 return ADV_ERROR;
7311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007312
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007313 warn_code = 0;
7314 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007316 /*
7317 * Save the RISC memory BIOS region before writing the microcode.
7318 * The BIOS may already be loaded and using its RISC LRAM region
7319 * so its region must be saved and restored.
7320 *
7321 * Note: This code makes the assumption, which is currently true,
7322 * that a chip reset does not clear RISC LRAM.
7323 */
7324 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7325 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7326 bios_mem[i]);
7327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007328
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007329 /*
7330 * Save current per TID negotiated values.
7331 */
7332 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7333 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7334 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7335 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7336 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7337 max_cmd[tid]);
7338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007339
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007340 /*
7341 * RAM BIST (RAM Built-In Self Test)
7342 *
7343 * Address : I/O base + offset 0x38h register (byte).
7344 * Function: Bit 7-6(RW) : RAM mode
7345 * Normal Mode : 0x00
7346 * Pre-test Mode : 0x40
7347 * RAM Test Mode : 0x80
7348 * Bit 5 : unused
7349 * Bit 4(RO) : Done bit
7350 * Bit 3-0(RO) : Status
7351 * Host Error : 0x08
7352 * Int_RAM Error : 0x04
7353 * RISC Error : 0x02
7354 * SCSI Error : 0x01
7355 * No Error : 0x00
7356 *
7357 * Note: RAM BIST code should be put right here, before loading the
7358 * microcode and after saving the RISC memory BIOS region.
7359 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007361 /*
7362 * LRAM Pre-test
7363 *
7364 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7365 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7366 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7367 * to NORMAL_MODE, return an error too.
7368 */
7369 for (i = 0; i < 2; i++) {
7370 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007371 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7373 if ((byte & RAM_TEST_DONE) == 0
7374 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007375 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007376 return ADV_ERROR;
7377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007379 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007380 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007381 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7382 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007383 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007384 return ADV_ERROR;
7385 }
7386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007387
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007388 /*
7389 * LRAM Test - It takes about 1.5 ms to run through the test.
7390 *
7391 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7392 * If Done bit not set or Status not 0, save register byte, set the
7393 * err_code, and return an error.
7394 */
7395 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007396 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007397
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007398 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7399 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7400 /* Get here if Done bit not set or Status not 0. */
7401 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007402 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007403 return ADV_ERROR;
7404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007406 /* We need to reset back to normal mode after LRAM test passes. */
7407 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007409 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
7410 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
7411 _adv_asc38C0800_chksum);
7412 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007413 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007414
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007415 /*
7416 * Restore the RISC memory BIOS region.
7417 */
7418 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7419 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7420 bios_mem[i]);
7421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007422
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007423 /*
7424 * Calculate and write the microcode code checksum to the microcode
7425 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7426 */
7427 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7428 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7429 code_sum = 0;
7430 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7431 for (word = begin_addr; word < end_addr; word += 2) {
7432 code_sum += AdvReadWordAutoIncLram(iop_base);
7433 }
7434 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007435
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007436 /*
7437 * Read microcode version and date.
7438 */
7439 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7440 asc_dvc->cfg->mcode_date);
7441 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7442 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007444 /*
7445 * Set the chip type to indicate the ASC38C0800.
7446 */
7447 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007449 /*
7450 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7451 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7452 * cable detection and then we are able to read C_DET[3:0].
7453 *
7454 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7455 * Microcode Default Value' section below.
7456 */
7457 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7458 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7459 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007461 /*
7462 * If the PCI Configuration Command Register "Parity Error Response
7463 * Control" Bit was clear (0), then set the microcode variable
7464 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7465 * to ignore DMA parity errors.
7466 */
7467 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7468 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7469 word |= CONTROL_FLAG_IGNORE_PERR;
7470 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007472
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007473 /*
7474 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
7475 * bits for the default FIFO threshold.
7476 *
7477 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
7478 *
7479 * For DMA Errata #4 set the BC_THRESH_ENB bit.
7480 */
7481 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7482 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
7483 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007485 /*
7486 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007487 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007488 * device reports it is capable of in Inquiry byte 7.
7489 *
7490 * If SCSI Bus Resets have been disabled, then directly set
7491 * SDTR and WDTR from the EEPROM configuration. This will allow
7492 * the BIOS and warm boot to work without a SCSI bus hang on
7493 * the Inquiry caused by host and target mismatched DTR values.
7494 * Without the SCSI Bus Reset, before an Inquiry a device can't
7495 * be assumed to be in Asynchronous, Narrow mode.
7496 */
7497 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7498 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7499 asc_dvc->wdtr_able);
7500 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7501 asc_dvc->sdtr_able);
7502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007503
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007504 /*
7505 * Set microcode operating variables for DISC and SDTR_SPEED1,
7506 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7507 * configuration values.
7508 *
7509 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7510 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7511 * without determining here whether the device supports SDTR.
7512 */
7513 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
7514 asc_dvc->cfg->disc_enable);
7515 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
7516 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
7517 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
7518 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007520 /*
7521 * Set SCSI_CFG0 Microcode Default Value.
7522 *
7523 * The microcode will set the SCSI_CFG0 register using this value
7524 * after it is started below.
7525 */
7526 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
7527 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
7528 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007529
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007530 /*
7531 * Determine SCSI_CFG1 Microcode Default Value.
7532 *
7533 * The microcode will set the SCSI_CFG1 register using this value
7534 * after it is started below.
7535 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007537 /* Read current SCSI_CFG1 Register value. */
7538 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007540 /*
7541 * If the internal narrow cable is reversed all of the SCSI_CTRL
7542 * register signals will be set. Check for and return an error if
7543 * this condition is found.
7544 */
7545 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
7546 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
7547 return ADV_ERROR;
7548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007549
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007550 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007551 * All kind of combinations of devices attached to one of four
7552 * connectors are acceptable except HVD device attached. For example,
7553 * LVD device can be attached to SE connector while SE device attached
7554 * to LVD connector. If LVD device attached to SE connector, it only
7555 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007556 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007557 * If an HVD device is attached to one of LVD connectors, return an
7558 * error. However, there is no way to detect HVD device attached to
7559 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007560 */
7561 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007562 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007563 return ADV_ERROR;
7564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007566 /*
7567 * If either SE or LVD automatic termination control is enabled, then
7568 * set the termination value based on a table listed in a_condor.h.
7569 *
7570 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007571 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
7572 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007573 */
7574 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
7575 /* SE automatic termination control is enabled. */
7576 switch (scsi_cfg1 & C_DET_SE) {
7577 /* TERM_SE_HI: on, TERM_SE_LO: on */
7578 case 0x1:
7579 case 0x2:
7580 case 0x3:
7581 asc_dvc->cfg->termination |= TERM_SE;
7582 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007584 /* TERM_SE_HI: on, TERM_SE_LO: off */
7585 case 0x0:
7586 asc_dvc->cfg->termination |= TERM_SE_HI;
7587 break;
7588 }
7589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007590
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007591 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
7592 /* LVD automatic termination control is enabled. */
7593 switch (scsi_cfg1 & C_DET_LVD) {
7594 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
7595 case 0x4:
7596 case 0x8:
7597 case 0xC:
7598 asc_dvc->cfg->termination |= TERM_LVD;
7599 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007600
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007601 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
7602 case 0x0:
7603 break;
7604 }
7605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007607 /*
7608 * Clear any set TERM_SE and TERM_LVD bits.
7609 */
7610 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007612 /*
7613 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
7614 */
7615 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007616
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007617 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007618 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
7619 * bits and set possibly modified termination control bits in the
7620 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007621 */
7622 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007623
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007624 /*
7625 * Set SCSI_CFG1 Microcode Default Value
7626 *
7627 * Set possibly modified termination control and reset DIS_TERM_DRV
7628 * bits in the Microcode SCSI_CFG1 Register Value.
7629 *
7630 * The microcode will set the SCSI_CFG1 register using this value
7631 * after it is started below.
7632 */
7633 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007634
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007635 /*
7636 * Set MEM_CFG Microcode Default Value
7637 *
7638 * The microcode will set the MEM_CFG register using this value
7639 * after it is started below.
7640 *
7641 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
7642 * are defined.
7643 *
7644 * ASC-38C0800 has 16KB internal memory.
7645 */
7646 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
7647 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007648
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007649 /*
7650 * Set SEL_MASK Microcode Default Value
7651 *
7652 * The microcode will set the SEL_MASK register using this value
7653 * after it is started below.
7654 */
7655 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
7656 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007657
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06007658 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007659
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007660 /*
7661 * Set-up the Host->RISC Initiator Command Queue (ICQ).
7662 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007663
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007664 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
7665 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7666 return ADV_ERROR;
7667 }
7668 asc_dvc->carr_freelist = (ADV_CARR_T *)
7669 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007670
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007671 /*
7672 * The first command issued will be placed in the stopper carrier.
7673 */
7674 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007675
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007676 /*
7677 * Set RISC ICQ physical address start value.
7678 * carr_pa is LE, must be native before write
7679 */
7680 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007682 /*
7683 * Set-up the RISC->Host Initiator Response Queue (IRQ).
7684 */
7685 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
7686 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
7687 return ADV_ERROR;
7688 }
7689 asc_dvc->carr_freelist = (ADV_CARR_T *)
7690 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007692 /*
7693 * The first command completed by the RISC will be placed in
7694 * the stopper.
7695 *
7696 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
7697 * completed the RISC will set the ASC_RQ_STOPPER bit.
7698 */
7699 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007700
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007701 /*
7702 * Set RISC IRQ physical address start value.
7703 *
7704 * carr_pa is LE, must be native before write *
7705 */
7706 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
7707 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007708
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007709 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
7710 (ADV_INTR_ENABLE_HOST_INTR |
7711 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007713 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
7714 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007716 /* finally, finally, gentlemen, start your engine */
7717 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007719 /*
7720 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
7721 * Resets should be performed. The RISC has to be running
7722 * to issue a SCSI Bus Reset.
7723 */
7724 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
7725 /*
7726 * If the BIOS Signature is present in memory, restore the
7727 * BIOS Handshake Configuration Table and do not perform
7728 * a SCSI Bus Reset.
7729 */
7730 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
7731 0x55AA) {
7732 /*
7733 * Restore per TID negotiated values.
7734 */
7735 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7736 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7737 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
7738 tagqng_able);
7739 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
7740 AdvWriteByteLram(iop_base,
7741 ASC_MC_NUMBER_OF_MAX_CMD + tid,
7742 max_cmd[tid]);
7743 }
7744 } else {
7745 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
7746 warn_code = ASC_WARN_BUSRESET_ERROR;
7747 }
7748 }
7749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007750
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007751 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007752}
7753
7754/*
7755 * Initialize the ASC-38C1600.
7756 *
7757 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
7758 *
7759 * For a non-fatal error return a warning code. If there are no warnings
7760 * then 0 is returned.
7761 *
7762 * Needed after initialization for error recovery.
7763 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007764static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007765{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007766 AdvPortAddr iop_base;
7767 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007768 int begin_addr;
7769 int end_addr;
7770 ushort code_sum;
7771 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007772 int i;
7773 ushort scsi_cfg1;
7774 uchar byte;
7775 uchar tid;
7776 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
7777 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
7778 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007779
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007780 /* If there is already an error, don't continue. */
7781 if (asc_dvc->err_code != 0) {
7782 return ADV_ERROR;
7783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007785 /*
7786 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
7787 */
7788 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
7789 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
7790 return ADV_ERROR;
7791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007792
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007793 warn_code = 0;
7794 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007796 /*
7797 * Save the RISC memory BIOS region before writing the microcode.
7798 * The BIOS may already be loaded and using its RISC LRAM region
7799 * so its region must be saved and restored.
7800 *
7801 * Note: This code makes the assumption, which is currently true,
7802 * that a chip reset does not clear RISC LRAM.
7803 */
7804 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7805 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7806 bios_mem[i]);
7807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007808
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007809 /*
7810 * Save current per TID negotiated values.
7811 */
7812 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
7813 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
7814 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
7815 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
7816 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7817 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
7818 max_cmd[tid]);
7819 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007820
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007821 /*
7822 * RAM BIST (Built-In Self Test)
7823 *
7824 * Address : I/O base + offset 0x38h register (byte).
7825 * Function: Bit 7-6(RW) : RAM mode
7826 * Normal Mode : 0x00
7827 * Pre-test Mode : 0x40
7828 * RAM Test Mode : 0x80
7829 * Bit 5 : unused
7830 * Bit 4(RO) : Done bit
7831 * Bit 3-0(RO) : Status
7832 * Host Error : 0x08
7833 * Int_RAM Error : 0x04
7834 * RISC Error : 0x02
7835 * SCSI Error : 0x01
7836 * No Error : 0x00
7837 *
7838 * Note: RAM BIST code should be put right here, before loading the
7839 * microcode and after saving the RISC memory BIOS region.
7840 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007841
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007842 /*
7843 * LRAM Pre-test
7844 *
7845 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
7846 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
7847 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
7848 * to NORMAL_MODE, return an error too.
7849 */
7850 for (i = 0; i < 2; i++) {
7851 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007852 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007853 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7854 if ((byte & RAM_TEST_DONE) == 0
7855 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007856 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007857 return ADV_ERROR;
7858 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007859
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007860 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007861 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007862 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
7863 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007864 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007865 return ADV_ERROR;
7866 }
7867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007869 /*
7870 * LRAM Test - It takes about 1.5 ms to run through the test.
7871 *
7872 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
7873 * If Done bit not set or Status not 0, save register byte, set the
7874 * err_code, and return an error.
7875 */
7876 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007877 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007879 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
7880 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
7881 /* Get here if Done bit not set or Status not 0. */
7882 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007883 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007884 return ADV_ERROR;
7885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007887 /* We need to reset back to normal mode after LRAM test passes. */
7888 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007889
Matthew Wilcoxb9d96612007-09-09 08:56:28 -06007890 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
7891 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
7892 _adv_asc38C1600_chksum);
7893 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007894 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007896 /*
7897 * Restore the RISC memory BIOS region.
7898 */
7899 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
7900 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
7901 bios_mem[i]);
7902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007903
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007904 /*
7905 * Calculate and write the microcode code checksum to the microcode
7906 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
7907 */
7908 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
7909 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
7910 code_sum = 0;
7911 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
7912 for (word = begin_addr; word < end_addr; word += 2) {
7913 code_sum += AdvReadWordAutoIncLram(iop_base);
7914 }
7915 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007916
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007917 /*
7918 * Read microcode version and date.
7919 */
7920 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
7921 asc_dvc->cfg->mcode_date);
7922 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
7923 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007925 /*
7926 * Set the chip type to indicate the ASC38C1600.
7927 */
7928 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007930 /*
7931 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
7932 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
7933 * cable detection and then we are able to read C_DET[3:0].
7934 *
7935 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
7936 * Microcode Default Value' section below.
7937 */
7938 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
7939 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
7940 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007942 /*
7943 * If the PCI Configuration Command Register "Parity Error Response
7944 * Control" Bit was clear (0), then set the microcode variable
7945 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
7946 * to ignore DMA parity errors.
7947 */
7948 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
7949 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7950 word |= CONTROL_FLAG_IGNORE_PERR;
7951 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007954 /*
7955 * If the BIOS control flag AIPP (Asynchronous Information
7956 * Phase Protection) disable bit is not set, then set the firmware
7957 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
7958 * AIPP checking and encoding.
7959 */
7960 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
7961 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7962 word |= CONTROL_FLAG_ENABLE_AIPP;
7963 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
7964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007966 /*
7967 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
7968 * and START_CTL_TH [3:2].
7969 */
7970 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
7971 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007973 /*
7974 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007975 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007976 * device reports it is capable of in Inquiry byte 7.
7977 *
7978 * If SCSI Bus Resets have been disabled, then directly set
7979 * SDTR and WDTR from the EEPROM configuration. This will allow
7980 * the BIOS and warm boot to work without a SCSI bus hang on
7981 * the Inquiry caused by host and target mismatched DTR values.
7982 * Without the SCSI Bus Reset, before an Inquiry a device can't
7983 * be assumed to be in Asynchronous, Narrow mode.
7984 */
7985 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
7986 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
7987 asc_dvc->wdtr_able);
7988 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
7989 asc_dvc->sdtr_able);
7990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007991
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007992 /*
7993 * Set microcode operating variables for DISC and SDTR_SPEED1,
7994 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
7995 * configuration values.
7996 *
7997 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
7998 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
7999 * without determining here whether the device supports SDTR.
8000 */
8001 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
8002 asc_dvc->cfg->disc_enable);
8003 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
8004 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
8005 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
8006 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008007
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008008 /*
8009 * Set SCSI_CFG0 Microcode Default Value.
8010 *
8011 * The microcode will set the SCSI_CFG0 register using this value
8012 * after it is started below.
8013 */
8014 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
8015 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
8016 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008018 /*
8019 * Calculate SCSI_CFG1 Microcode Default Value.
8020 *
8021 * The microcode will set the SCSI_CFG1 register using this value
8022 * after it is started below.
8023 *
8024 * Each ASC-38C1600 function has only two cable detect bits.
8025 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
8026 */
8027 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008028
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008029 /*
8030 * If the cable is reversed all of the SCSI_CTRL register signals
8031 * will be set. Check for and return an error if this condition is
8032 * found.
8033 */
8034 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
8035 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
8036 return ADV_ERROR;
8037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008039 /*
8040 * Each ASC-38C1600 function has two connectors. Only an HVD device
8041 * can not be connected to either connector. An LVD device or SE device
8042 * may be connected to either connecor. If an SE device is connected,
8043 * then at most Ultra speed (20 Mhz) can be used on both connectors.
8044 *
8045 * If an HVD device is attached, return an error.
8046 */
8047 if (scsi_cfg1 & HVD) {
8048 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
8049 return ADV_ERROR;
8050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008051
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008052 /*
8053 * Each function in the ASC-38C1600 uses only the SE cable detect and
8054 * termination because there are two connectors for each function. Each
8055 * function may use either LVD or SE mode. Corresponding the SE automatic
8056 * termination control EEPROM bits are used for each function. Each
8057 * function has its own EEPROM. If SE automatic control is enabled for
8058 * the function, then set the termination value based on a table listed
8059 * in a_condor.h.
8060 *
8061 * If manual termination is specified in the EEPROM for the function,
8062 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
8063 * ready to be 'ored' into SCSI_CFG1.
8064 */
8065 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06008066 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008067 /* SE automatic termination control is enabled. */
8068 switch (scsi_cfg1 & C_DET_SE) {
8069 /* TERM_SE_HI: on, TERM_SE_LO: on */
8070 case 0x1:
8071 case 0x2:
8072 case 0x3:
8073 asc_dvc->cfg->termination |= TERM_SE;
8074 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008075
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008076 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06008077 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008078 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
8079 } else {
8080 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
8081 asc_dvc->cfg->termination |= TERM_SE_HI;
8082 }
8083 break;
8084 }
8085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008086
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008087 /*
8088 * Clear any set TERM_SE bits.
8089 */
8090 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008091
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008092 /*
8093 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
8094 */
8095 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008096
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008097 /*
8098 * Clear Big Endian and Terminator Polarity bits and set possibly
8099 * modified termination control bits in the Microcode SCSI_CFG1
8100 * Register Value.
8101 *
8102 * Big Endian bit is not used even on big endian machines.
8103 */
8104 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008106 /*
8107 * Set SCSI_CFG1 Microcode Default Value
8108 *
8109 * Set possibly modified termination control bits in the Microcode
8110 * SCSI_CFG1 Register Value.
8111 *
8112 * The microcode will set the SCSI_CFG1 register using this value
8113 * after it is started below.
8114 */
8115 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008116
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008117 /*
8118 * Set MEM_CFG Microcode Default Value
8119 *
8120 * The microcode will set the MEM_CFG register using this value
8121 * after it is started below.
8122 *
8123 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
8124 * are defined.
8125 *
8126 * ASC-38C1600 has 32KB internal memory.
8127 *
8128 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
8129 * out a special 16K Adv Library and Microcode version. After the issue
8130 * resolved, we should turn back to the 32K support. Both a_condor.h and
8131 * mcode.sas files also need to be updated.
8132 *
8133 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8134 * BIOS_EN | RAM_SZ_32KB);
8135 */
8136 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
8137 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008138
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008139 /*
8140 * Set SEL_MASK Microcode Default Value
8141 *
8142 * The microcode will set the SEL_MASK register using this value
8143 * after it is started below.
8144 */
8145 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
8146 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008147
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -06008148 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008149
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008150 /*
8151 * Set-up the Host->RISC Initiator Command Queue (ICQ).
8152 */
8153 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
8154 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8155 return ADV_ERROR;
8156 }
8157 asc_dvc->carr_freelist = (ADV_CARR_T *)
8158 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008159
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008160 /*
8161 * The first command issued will be placed in the stopper carrier.
8162 */
8163 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008164
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008165 /*
8166 * Set RISC ICQ physical address start value. Initialize the
8167 * COMMA register to the same value otherwise the RISC will
8168 * prematurely detect a command is available.
8169 */
8170 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
8171 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
8172 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008173
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008174 /*
8175 * Set-up the RISC->Host Initiator Response Queue (IRQ).
8176 */
8177 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
8178 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
8179 return ADV_ERROR;
8180 }
8181 asc_dvc->carr_freelist = (ADV_CARR_T *)
8182 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008184 /*
8185 * The first command completed by the RISC will be placed in
8186 * the stopper.
8187 *
8188 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
8189 * completed the RISC will set the ASC_RQ_STOPPER bit.
8190 */
8191 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008192
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008193 /*
8194 * Set RISC IRQ physical address start value.
8195 */
8196 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
8197 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008199 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
8200 (ADV_INTR_ENABLE_HOST_INTR |
8201 ADV_INTR_ENABLE_GLOBAL_INTR));
8202 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
8203 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008204
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008205 /* finally, finally, gentlemen, start your engine */
8206 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008207
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008208 /*
8209 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
8210 * Resets should be performed. The RISC has to be running
8211 * to issue a SCSI Bus Reset.
8212 */
8213 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
8214 /*
8215 * If the BIOS Signature is present in memory, restore the
8216 * per TID microcode operating variables.
8217 */
8218 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
8219 0x55AA) {
8220 /*
8221 * Restore per TID negotiated values.
8222 */
8223 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8224 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8225 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8226 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
8227 tagqng_able);
8228 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
8229 AdvWriteByteLram(iop_base,
8230 ASC_MC_NUMBER_OF_MAX_CMD + tid,
8231 max_cmd[tid]);
8232 }
8233 } else {
8234 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
8235 warn_code = ASC_WARN_BUSRESET_ERROR;
8236 }
8237 }
8238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008239
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008240 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008241}
8242
8243/*
Matthew Wilcox51219352007-10-02 21:55:22 -04008244 * Reset chip and SCSI Bus.
8245 *
8246 * Return Value:
8247 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
8248 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
8249 */
8250static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
8251{
8252 int status;
8253 ushort wdtr_able, sdtr_able, tagqng_able;
8254 ushort ppr_able = 0;
8255 uchar tid, max_cmd[ADV_MAX_TID + 1];
8256 AdvPortAddr iop_base;
8257 ushort bios_sig;
8258
8259 iop_base = asc_dvc->iop_base;
8260
8261 /*
8262 * Save current per TID negotiated values.
8263 */
8264 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8265 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8266 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8267 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8268 }
8269 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8270 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8271 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8272 max_cmd[tid]);
8273 }
8274
8275 /*
8276 * Force the AdvInitAsc3550/38C0800Driver() function to
8277 * perform a SCSI Bus Reset by clearing the BIOS signature word.
8278 * The initialization functions assumes a SCSI Bus Reset is not
8279 * needed if the BIOS signature word is present.
8280 */
8281 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8282 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
8283
8284 /*
8285 * Stop chip and reset it.
8286 */
8287 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
8288 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
8289 mdelay(100);
8290 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
8291 ADV_CTRL_REG_CMD_WR_IO_REG);
8292
8293 /*
8294 * Reset Adv Library error code, if any, and try
8295 * re-initializing the chip.
8296 */
8297 asc_dvc->err_code = 0;
8298 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8299 status = AdvInitAsc38C1600Driver(asc_dvc);
8300 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8301 status = AdvInitAsc38C0800Driver(asc_dvc);
8302 } else {
8303 status = AdvInitAsc3550Driver(asc_dvc);
8304 }
8305
8306 /* Translate initialization return value to status value. */
8307 if (status == 0) {
8308 status = ADV_TRUE;
8309 } else {
8310 status = ADV_FALSE;
8311 }
8312
8313 /*
8314 * Restore the BIOS signature word.
8315 */
8316 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
8317
8318 /*
8319 * Restore per TID negotiated values.
8320 */
8321 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
8322 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
8323 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
8324 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
8325 }
8326 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
8327 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
8328 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
8329 max_cmd[tid]);
8330 }
8331
8332 return status;
8333}
8334
8335/*
8336 * adv_async_callback() - Adv Library asynchronous event callback function.
8337 */
8338static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
8339{
8340 switch (code) {
8341 case ADV_ASYNC_SCSI_BUS_RESET_DET:
8342 /*
8343 * The firmware detected a SCSI Bus reset.
8344 */
8345 ASC_DBG(0,
8346 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
8347 break;
8348
8349 case ADV_ASYNC_RDMA_FAILURE:
8350 /*
8351 * Handle RDMA failure by resetting the SCSI Bus and
8352 * possibly the chip if it is unresponsive. Log the error
8353 * with a unique code.
8354 */
8355 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
8356 AdvResetChipAndSB(adv_dvc_varp);
8357 break;
8358
8359 case ADV_HOST_SCSI_BUS_RESET:
8360 /*
8361 * Host generated SCSI bus reset occurred.
8362 */
8363 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
8364 break;
8365
8366 default:
8367 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
8368 break;
8369 }
8370}
8371
8372/*
8373 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
8374 *
8375 * Callback function for the Wide SCSI Adv Library.
8376 */
8377static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
8378{
8379 asc_board_t *boardp;
8380 adv_req_t *reqp;
8381 adv_sgblk_t *sgblkp;
8382 struct scsi_cmnd *scp;
8383 struct Scsi_Host *shost;
8384 ADV_DCNT resid_cnt;
8385
8386 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
8387 (ulong)adv_dvc_varp, (ulong)scsiqp);
8388 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
8389
8390 /*
8391 * Get the adv_req_t structure for the command that has been
8392 * completed. The adv_req_t structure actually contains the
8393 * completed ADV_SCSI_REQ_Q structure.
8394 */
8395 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
8396 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
8397 if (reqp == NULL) {
8398 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
8399 return;
8400 }
8401
8402 /*
8403 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
8404 * command that has been completed.
8405 *
8406 * Note: The adv_req_t request structure and adv_sgblk_t structure,
8407 * if any, are dropped, because a board structure pointer can not be
8408 * determined.
8409 */
8410 scp = reqp->cmndp;
8411 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
8412 if (scp == NULL) {
8413 ASC_PRINT
8414 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
8415 return;
8416 }
8417 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
8418
8419 shost = scp->device->host;
8420 ASC_STATS(shost, callback);
8421 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
8422
8423 boardp = ASC_BOARDP(shost);
8424 BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
8425
8426 /*
8427 * 'done_status' contains the command's ending status.
8428 */
8429 switch (scsiqp->done_status) {
8430 case QD_NO_ERROR:
8431 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
8432 scp->result = 0;
8433
8434 /*
8435 * Check for an underrun condition.
8436 *
8437 * If there was no error and an underrun condition, then
8438 * then return the number of underrun bytes.
8439 */
8440 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
8441 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
8442 resid_cnt <= scp->request_bufflen) {
8443 ASC_DBG1(1,
8444 "adv_isr_callback: underrun condition %lu bytes\n",
8445 (ulong)resid_cnt);
8446 scp->resid = resid_cnt;
8447 }
8448 break;
8449
8450 case QD_WITH_ERROR:
8451 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
8452 switch (scsiqp->host_status) {
8453 case QHSTA_NO_ERROR:
8454 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
8455 ASC_DBG(2,
8456 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
8457 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
8458 sizeof(scp->sense_buffer));
8459 /*
8460 * Note: The 'status_byte()' macro used by
8461 * target drivers defined in scsi.h shifts the
8462 * status byte returned by host drivers right
8463 * by 1 bit. This is why target drivers also
8464 * use right shifted status byte definitions.
8465 * For instance target drivers use
8466 * CHECK_CONDITION, defined to 0x1, instead of
8467 * the SCSI defined check condition value of
8468 * 0x2. Host drivers are supposed to return
8469 * the status byte as it is defined by SCSI.
8470 */
8471 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
8472 STATUS_BYTE(scsiqp->scsi_status);
8473 } else {
8474 scp->result = STATUS_BYTE(scsiqp->scsi_status);
8475 }
8476 break;
8477
8478 default:
8479 /* Some other QHSTA error occurred. */
8480 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
8481 scsiqp->host_status);
8482 scp->result = HOST_BYTE(DID_BAD_TARGET);
8483 break;
8484 }
8485 break;
8486
8487 case QD_ABORTED_BY_HOST:
8488 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
8489 scp->result =
8490 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
8491 break;
8492
8493 default:
8494 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
8495 scsiqp->done_status);
8496 scp->result =
8497 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
8498 break;
8499 }
8500
8501 /*
8502 * If the 'init_tidmask' bit isn't already set for the target and the
8503 * current request finished normally, then set the bit for the target
8504 * to indicate that a device is present.
8505 */
8506 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
8507 scsiqp->done_status == QD_NO_ERROR &&
8508 scsiqp->host_status == QHSTA_NO_ERROR) {
8509 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
8510 }
8511
8512 asc_scsi_done(scp);
8513
8514 /*
8515 * Free all 'adv_sgblk_t' structures allocated for the request.
8516 */
8517 while ((sgblkp = reqp->sgblkp) != NULL) {
8518 /* Remove 'sgblkp' from the request list. */
8519 reqp->sgblkp = sgblkp->next_sgblkp;
8520
8521 /* Add 'sgblkp' to the board free list. */
8522 sgblkp->next_sgblkp = boardp->adv_sgblkp;
8523 boardp->adv_sgblkp = sgblkp;
8524 }
8525
8526 /*
8527 * Free the adv_req_t structure used with the command by adding
8528 * it back to the board free list.
8529 */
8530 reqp->next_reqp = boardp->adv_reqp;
8531 boardp->adv_reqp = reqp;
8532
8533 ASC_DBG(1, "adv_isr_callback: done\n");
8534
8535 return;
8536}
8537
8538/*
8539 * Adv Library Interrupt Service Routine
8540 *
8541 * This function is called by a driver's interrupt service routine.
8542 * The function disables and re-enables interrupts.
8543 *
8544 * When a microcode idle command is completed, the ADV_DVC_VAR
8545 * 'idle_cmd_done' field is set to ADV_TRUE.
8546 *
8547 * Note: AdvISR() can be called when interrupts are disabled or even
8548 * when there is no hardware interrupt condition present. It will
8549 * always check for completed idle commands and microcode requests.
8550 * This is an important feature that shouldn't be changed because it
8551 * allows commands to be completed from polling mode loops.
8552 *
8553 * Return:
8554 * ADV_TRUE(1) - interrupt was pending
8555 * ADV_FALSE(0) - no interrupt was pending
8556 */
8557static int AdvISR(ADV_DVC_VAR *asc_dvc)
8558{
8559 AdvPortAddr iop_base;
8560 uchar int_stat;
8561 ushort target_bit;
8562 ADV_CARR_T *free_carrp;
8563 ADV_VADDR irq_next_vpa;
8564 ADV_SCSI_REQ_Q *scsiq;
8565
8566 iop_base = asc_dvc->iop_base;
8567
8568 /* Reading the register clears the interrupt. */
8569 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
8570
8571 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
8572 ADV_INTR_STATUS_INTRC)) == 0) {
8573 return ADV_FALSE;
8574 }
8575
8576 /*
8577 * Notify the driver of an asynchronous microcode condition by
8578 * calling the adv_async_callback function. The function
8579 * is passed the microcode ASC_MC_INTRB_CODE byte value.
8580 */
8581 if (int_stat & ADV_INTR_STATUS_INTRB) {
8582 uchar intrb_code;
8583
8584 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
8585
8586 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
8587 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
8588 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
8589 asc_dvc->carr_pending_cnt != 0) {
8590 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
8591 ADV_TICKLE_A);
8592 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
8593 AdvWriteByteRegister(iop_base,
8594 IOPB_TICKLE,
8595 ADV_TICKLE_NOP);
8596 }
8597 }
8598 }
8599
8600 adv_async_callback(asc_dvc, intrb_code);
8601 }
8602
8603 /*
8604 * Check if the IRQ stopper carrier contains a completed request.
8605 */
8606 while (((irq_next_vpa =
8607 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
8608 /*
8609 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
8610 * The RISC will have set 'areq_vpa' to a virtual address.
8611 *
8612 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
8613 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
8614 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
8615 * in AdvExeScsiQueue().
8616 */
8617 scsiq = (ADV_SCSI_REQ_Q *)
8618 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
8619
8620 /*
8621 * Request finished with good status and the queue was not
8622 * DMAed to host memory by the firmware. Set all status fields
8623 * to indicate good status.
8624 */
8625 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
8626 scsiq->done_status = QD_NO_ERROR;
8627 scsiq->host_status = scsiq->scsi_status = 0;
8628 scsiq->data_cnt = 0L;
8629 }
8630
8631 /*
8632 * Advance the stopper pointer to the next carrier
8633 * ignoring the lower four bits. Free the previous
8634 * stopper carrier.
8635 */
8636 free_carrp = asc_dvc->irq_sp;
8637 asc_dvc->irq_sp = (ADV_CARR_T *)
8638 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
8639
8640 free_carrp->next_vpa =
8641 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
8642 asc_dvc->carr_freelist = free_carrp;
8643 asc_dvc->carr_pending_cnt--;
8644
8645 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
8646
8647 /*
8648 * Clear request microcode control flag.
8649 */
8650 scsiq->cntl = 0;
8651
8652 /*
8653 * Notify the driver of the completed request by passing
8654 * the ADV_SCSI_REQ_Q pointer to its callback function.
8655 */
8656 scsiq->a_flag |= ADV_SCSIQ_DONE;
8657 adv_isr_callback(asc_dvc, scsiq);
8658 /*
8659 * Note: After the driver callback function is called, 'scsiq'
8660 * can no longer be referenced.
8661 *
8662 * Fall through and continue processing other completed
8663 * requests...
8664 */
8665 }
8666 return ADV_TRUE;
8667}
8668
8669static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
8670{
8671 if (asc_dvc->err_code == 0) {
8672 asc_dvc->err_code = err_code;
8673 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8674 err_code);
8675 }
8676 return err_code;
8677}
8678
8679static void AscAckInterrupt(PortAddr iop_base)
8680{
8681 uchar host_flag;
8682 uchar risc_flag;
8683 ushort loop;
8684
8685 loop = 0;
8686 do {
8687 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8688 if (loop++ > 0x7FFF) {
8689 break;
8690 }
8691 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8692 host_flag =
8693 AscReadLramByte(iop_base,
8694 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8695 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8696 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8697 AscSetChipStatus(iop_base, CIW_INT_ACK);
8698 loop = 0;
8699 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8700 AscSetChipStatus(iop_base, CIW_INT_ACK);
8701 if (loop++ > 3) {
8702 break;
8703 }
8704 }
8705 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8706 return;
8707}
8708
8709static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
8710{
8711 uchar *period_table;
8712 int max_index;
8713 int min_index;
8714 int i;
8715
8716 period_table = asc_dvc->sdtr_period_tbl;
8717 max_index = (int)asc_dvc->max_sdtr_index;
8718 min_index = (int)asc_dvc->host_init_sdtr_index;
8719 if ((syn_time <= period_table[max_index])) {
8720 for (i = min_index; i < (max_index - 1); i++) {
8721 if (syn_time <= period_table[i]) {
8722 return (uchar)i;
8723 }
8724 }
8725 return (uchar)max_index;
8726 } else {
8727 return (uchar)(max_index + 1);
8728 }
8729}
8730
8731static uchar
8732AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
8733{
8734 EXT_MSG sdtr_buf;
8735 uchar sdtr_period_index;
8736 PortAddr iop_base;
8737
8738 iop_base = asc_dvc->iop_base;
8739 sdtr_buf.msg_type = EXTENDED_MESSAGE;
8740 sdtr_buf.msg_len = MS_SDTR_LEN;
8741 sdtr_buf.msg_req = EXTENDED_SDTR;
8742 sdtr_buf.xfer_period = sdtr_period;
8743 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8744 sdtr_buf.req_ack_offset = sdtr_offset;
8745 sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8746 if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
8747 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8748 (uchar *)&sdtr_buf,
8749 sizeof(EXT_MSG) >> 1);
8750 return ((sdtr_period_index << 4) | sdtr_offset);
8751 } else {
8752 sdtr_buf.req_ack_offset = 0;
8753 AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
8754 (uchar *)&sdtr_buf,
8755 sizeof(EXT_MSG) >> 1);
8756 return 0;
8757 }
8758}
8759
8760static uchar
8761AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
8762{
8763 uchar byte;
8764 uchar sdtr_period_ix;
8765
8766 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8767 if (sdtr_period_ix > asc_dvc->max_sdtr_index) {
8768 return 0xFF;
8769 }
8770 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8771 return byte;
8772}
8773
8774static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
8775{
8776 ASC_SCSI_BIT_ID_TYPE org_id;
8777 int i;
8778 int sta = TRUE;
8779
8780 AscSetBank(iop_base, 1);
8781 org_id = AscReadChipDvcID(iop_base);
8782 for (i = 0; i <= ASC_MAX_TID; i++) {
8783 if (org_id == (0x01 << i))
8784 break;
8785 }
8786 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8787 AscWriteChipDvcID(iop_base, id);
8788 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8789 AscSetBank(iop_base, 0);
8790 AscSetChipSyn(iop_base, sdtr_data);
8791 if (AscGetChipSyn(iop_base) != sdtr_data) {
8792 sta = FALSE;
8793 }
8794 } else {
8795 sta = FALSE;
8796 }
8797 AscSetBank(iop_base, 1);
8798 AscWriteChipDvcID(iop_base, org_id);
8799 AscSetBank(iop_base, 0);
8800 return (sta);
8801}
8802
8803static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
8804{
8805 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8806 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8807}
8808
8809static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
8810{
8811 EXT_MSG ext_msg;
8812 EXT_MSG out_msg;
8813 ushort halt_q_addr;
8814 int sdtr_accept;
8815 ushort int_halt_code;
8816 ASC_SCSI_BIT_ID_TYPE scsi_busy;
8817 ASC_SCSI_BIT_ID_TYPE target_id;
8818 PortAddr iop_base;
8819 uchar tag_code;
8820 uchar q_status;
8821 uchar halt_qp;
8822 uchar sdtr_data;
8823 uchar target_ix;
8824 uchar q_cntl, tid_no;
8825 uchar cur_dvc_qng;
8826 uchar asyn_sdtr;
8827 uchar scsi_status;
8828 asc_board_t *boardp;
8829
8830 BUG_ON(!asc_dvc->drv_ptr);
8831 boardp = asc_dvc->drv_ptr;
8832
8833 iop_base = asc_dvc->iop_base;
8834 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
8835
8836 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
8837 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
8838 target_ix = AscReadLramByte(iop_base,
8839 (ushort)(halt_q_addr +
8840 (ushort)ASC_SCSIQ_B_TARGET_IX));
8841 q_cntl = AscReadLramByte(iop_base,
8842 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
8843 tid_no = ASC_TIX_TO_TID(target_ix);
8844 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
8845 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8846 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
8847 } else {
8848 asyn_sdtr = 0;
8849 }
8850 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
8851 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8852 AscSetChipSDTR(iop_base, 0, tid_no);
8853 boardp->sdtr_data[tid_no] = 0;
8854 }
8855 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8856 return (0);
8857 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
8858 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
8859 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8860 boardp->sdtr_data[tid_no] = asyn_sdtr;
8861 }
8862 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8863 return (0);
8864 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
8865 AscMemWordCopyPtrFromLram(iop_base,
8866 ASCV_MSGIN_BEG,
8867 (uchar *)&ext_msg,
8868 sizeof(EXT_MSG) >> 1);
8869
8870 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8871 ext_msg.msg_req == EXTENDED_SDTR &&
8872 ext_msg.msg_len == MS_SDTR_LEN) {
8873 sdtr_accept = TRUE;
8874 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
8875
8876 sdtr_accept = FALSE;
8877 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
8878 }
8879 if ((ext_msg.xfer_period <
8880 asc_dvc->sdtr_period_tbl[asc_dvc->
8881 host_init_sdtr_index])
8882 || (ext_msg.xfer_period >
8883 asc_dvc->sdtr_period_tbl[asc_dvc->
8884 max_sdtr_index])) {
8885 sdtr_accept = FALSE;
8886 ext_msg.xfer_period =
8887 asc_dvc->sdtr_period_tbl[asc_dvc->
8888 host_init_sdtr_index];
8889 }
8890 if (sdtr_accept) {
8891 sdtr_data =
8892 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
8893 ext_msg.req_ack_offset);
8894 if ((sdtr_data == 0xFF)) {
8895
8896 q_cntl |= QC_MSG_OUT;
8897 asc_dvc->init_sdtr &= ~target_id;
8898 asc_dvc->sdtr_done &= ~target_id;
8899 AscSetChipSDTR(iop_base, asyn_sdtr,
8900 tid_no);
8901 boardp->sdtr_data[tid_no] = asyn_sdtr;
8902 }
8903 }
8904 if (ext_msg.req_ack_offset == 0) {
8905
8906 q_cntl &= ~QC_MSG_OUT;
8907 asc_dvc->init_sdtr &= ~target_id;
8908 asc_dvc->sdtr_done &= ~target_id;
8909 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
8910 } else {
8911 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
8912
8913 q_cntl &= ~QC_MSG_OUT;
8914 asc_dvc->sdtr_done |= target_id;
8915 asc_dvc->init_sdtr |= target_id;
8916 asc_dvc->pci_fix_asyn_xfer &=
8917 ~target_id;
8918 sdtr_data =
8919 AscCalSDTRData(asc_dvc,
8920 ext_msg.xfer_period,
8921 ext_msg.
8922 req_ack_offset);
8923 AscSetChipSDTR(iop_base, sdtr_data,
8924 tid_no);
8925 boardp->sdtr_data[tid_no] = sdtr_data;
8926 } else {
8927
8928 q_cntl |= QC_MSG_OUT;
8929 AscMsgOutSDTR(asc_dvc,
8930 ext_msg.xfer_period,
8931 ext_msg.req_ack_offset);
8932 asc_dvc->pci_fix_asyn_xfer &=
8933 ~target_id;
8934 sdtr_data =
8935 AscCalSDTRData(asc_dvc,
8936 ext_msg.xfer_period,
8937 ext_msg.
8938 req_ack_offset);
8939 AscSetChipSDTR(iop_base, sdtr_data,
8940 tid_no);
8941 boardp->sdtr_data[tid_no] = sdtr_data;
8942 asc_dvc->sdtr_done |= target_id;
8943 asc_dvc->init_sdtr |= target_id;
8944 }
8945 }
8946
8947 AscWriteLramByte(iop_base,
8948 (ushort)(halt_q_addr +
8949 (ushort)ASC_SCSIQ_B_CNTL),
8950 q_cntl);
8951 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8952 return (0);
8953 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
8954 ext_msg.msg_req == EXTENDED_WDTR &&
8955 ext_msg.msg_len == MS_WDTR_LEN) {
8956
8957 ext_msg.wdtr_width = 0;
8958 AscMemWordCopyPtrToLram(iop_base,
8959 ASCV_MSGOUT_BEG,
8960 (uchar *)&ext_msg,
8961 sizeof(EXT_MSG) >> 1);
8962 q_cntl |= QC_MSG_OUT;
8963 AscWriteLramByte(iop_base,
8964 (ushort)(halt_q_addr +
8965 (ushort)ASC_SCSIQ_B_CNTL),
8966 q_cntl);
8967 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8968 return (0);
8969 } else {
8970
8971 ext_msg.msg_type = MESSAGE_REJECT;
8972 AscMemWordCopyPtrToLram(iop_base,
8973 ASCV_MSGOUT_BEG,
8974 (uchar *)&ext_msg,
8975 sizeof(EXT_MSG) >> 1);
8976 q_cntl |= QC_MSG_OUT;
8977 AscWriteLramByte(iop_base,
8978 (ushort)(halt_q_addr +
8979 (ushort)ASC_SCSIQ_B_CNTL),
8980 q_cntl);
8981 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8982 return (0);
8983 }
8984 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
8985
8986 q_cntl |= QC_REQ_SENSE;
8987
8988 if ((asc_dvc->init_sdtr & target_id) != 0) {
8989
8990 asc_dvc->sdtr_done &= ~target_id;
8991
8992 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8993 q_cntl |= QC_MSG_OUT;
8994 AscMsgOutSDTR(asc_dvc,
8995 asc_dvc->
8996 sdtr_period_tbl[(sdtr_data >> 4) &
8997 (uchar)(asc_dvc->
8998 max_sdtr_index -
8999 1)],
9000 (uchar)(sdtr_data & (uchar)
9001 ASC_SYN_MAX_OFFSET));
9002 }
9003
9004 AscWriteLramByte(iop_base,
9005 (ushort)(halt_q_addr +
9006 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
9007
9008 tag_code = AscReadLramByte(iop_base,
9009 (ushort)(halt_q_addr + (ushort)
9010 ASC_SCSIQ_B_TAG_CODE));
9011 tag_code &= 0xDC;
9012 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
9013 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
9014 ) {
9015
9016 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
9017 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
9018
9019 }
9020 AscWriteLramByte(iop_base,
9021 (ushort)(halt_q_addr +
9022 (ushort)ASC_SCSIQ_B_TAG_CODE),
9023 tag_code);
9024
9025 q_status = AscReadLramByte(iop_base,
9026 (ushort)(halt_q_addr + (ushort)
9027 ASC_SCSIQ_B_STATUS));
9028 q_status |= (QS_READY | QS_BUSY);
9029 AscWriteLramByte(iop_base,
9030 (ushort)(halt_q_addr +
9031 (ushort)ASC_SCSIQ_B_STATUS),
9032 q_status);
9033
9034 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
9035 scsi_busy &= ~target_id;
9036 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
9037
9038 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9039 return (0);
9040 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
9041
9042 AscMemWordCopyPtrFromLram(iop_base,
9043 ASCV_MSGOUT_BEG,
9044 (uchar *)&out_msg,
9045 sizeof(EXT_MSG) >> 1);
9046
9047 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
9048 (out_msg.msg_len == MS_SDTR_LEN) &&
9049 (out_msg.msg_req == EXTENDED_SDTR)) {
9050
9051 asc_dvc->init_sdtr &= ~target_id;
9052 asc_dvc->sdtr_done &= ~target_id;
9053 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
9054 boardp->sdtr_data[tid_no] = asyn_sdtr;
9055 }
9056 q_cntl &= ~QC_MSG_OUT;
9057 AscWriteLramByte(iop_base,
9058 (ushort)(halt_q_addr +
9059 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
9060 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9061 return (0);
9062 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
9063
9064 scsi_status = AscReadLramByte(iop_base,
9065 (ushort)((ushort)halt_q_addr +
9066 (ushort)
9067 ASC_SCSIQ_SCSI_STATUS));
9068 cur_dvc_qng =
9069 AscReadLramByte(iop_base,
9070 (ushort)((ushort)ASC_QADR_BEG +
9071 (ushort)target_ix));
9072 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
9073
9074 scsi_busy = AscReadLramByte(iop_base,
9075 (ushort)ASCV_SCSIBUSY_B);
9076 scsi_busy |= target_id;
9077 AscWriteLramByte(iop_base,
9078 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
9079 asc_dvc->queue_full_or_busy |= target_id;
9080
9081 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
9082 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
9083 cur_dvc_qng -= 1;
9084 asc_dvc->max_dvc_qng[tid_no] =
9085 cur_dvc_qng;
9086
9087 AscWriteLramByte(iop_base,
9088 (ushort)((ushort)
9089 ASCV_MAX_DVC_QNG_BEG
9090 + (ushort)
9091 tid_no),
9092 cur_dvc_qng);
9093
9094 /*
9095 * Set the device queue depth to the
9096 * number of active requests when the
9097 * QUEUE FULL condition was encountered.
9098 */
9099 boardp->queue_full |= target_id;
9100 boardp->queue_full_cnt[tid_no] =
9101 cur_dvc_qng;
9102 }
9103 }
9104 }
9105 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9106 return (0);
9107 }
9108#if CC_VERY_LONG_SG_LIST
9109 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
9110 uchar q_no;
9111 ushort q_addr;
9112 uchar sg_wk_q_no;
9113 uchar first_sg_wk_q_no;
9114 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
9115 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
9116 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
9117 ushort sg_list_dwords;
9118 ushort sg_entry_cnt;
9119 uchar next_qp;
9120 int i;
9121
9122 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
9123 if (q_no == ASC_QLINK_END)
9124 return 0;
9125
9126 q_addr = ASC_QNO_TO_QADDR(q_no);
9127
9128 /*
9129 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
9130 * structure pointer using a macro provided by the driver.
9131 * The ASC_SCSI_REQ pointer provides a pointer to the
9132 * host ASC_SG_HEAD structure.
9133 */
9134 /* Read request's SRB pointer. */
9135 scsiq = (ASC_SCSI_Q *)
9136 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
9137 (ushort)
9138 (q_addr +
9139 ASC_SCSIQ_D_SRBPTR))));
9140
9141 /*
9142 * Get request's first and working SG queue.
9143 */
9144 sg_wk_q_no = AscReadLramByte(iop_base,
9145 (ushort)(q_addr +
9146 ASC_SCSIQ_B_SG_WK_QP));
9147
9148 first_sg_wk_q_no = AscReadLramByte(iop_base,
9149 (ushort)(q_addr +
9150 ASC_SCSIQ_B_FIRST_SG_WK_QP));
9151
9152 /*
9153 * Reset request's working SG queue back to the
9154 * first SG queue.
9155 */
9156 AscWriteLramByte(iop_base,
9157 (ushort)(q_addr +
9158 (ushort)ASC_SCSIQ_B_SG_WK_QP),
9159 first_sg_wk_q_no);
9160
9161 sg_head = scsiq->sg_head;
9162
9163 /*
9164 * Set sg_entry_cnt to the number of SG elements
9165 * that will be completed on this interrupt.
9166 *
9167 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
9168 * SG elements. The data_cnt and data_addr fields which
9169 * add 1 to the SG element capacity are not used when
9170 * restarting SG handling after a halt.
9171 */
9172 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
9173 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
9174
9175 /*
9176 * Keep track of remaining number of SG elements that
9177 * will need to be handled on the next interrupt.
9178 */
9179 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
9180 } else {
9181 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
9182 scsiq->remain_sg_entry_cnt = 0;
9183 }
9184
9185 /*
9186 * Copy SG elements into the list of allocated SG queues.
9187 *
9188 * Last index completed is saved in scsiq->next_sg_index.
9189 */
9190 next_qp = first_sg_wk_q_no;
9191 q_addr = ASC_QNO_TO_QADDR(next_qp);
9192 scsi_sg_q.sg_head_qp = q_no;
9193 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
9194 for (i = 0; i < sg_head->queue_cnt; i++) {
9195 scsi_sg_q.seq_no = i + 1;
9196 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
9197 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
9198 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
9199 /*
9200 * After very first SG queue RISC FW uses next
9201 * SG queue first element then checks sg_list_cnt
9202 * against zero and then decrements, so set
9203 * sg_list_cnt 1 less than number of SG elements
9204 * in each SG queue.
9205 */
9206 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
9207 scsi_sg_q.sg_cur_list_cnt =
9208 ASC_SG_LIST_PER_Q - 1;
9209 } else {
9210 /*
9211 * This is the last SG queue in the list of
9212 * allocated SG queues. If there are more
9213 * SG elements than will fit in the allocated
9214 * queues, then set the QCSG_SG_XFER_MORE flag.
9215 */
9216 if (scsiq->remain_sg_entry_cnt != 0) {
9217 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
9218 } else {
9219 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
9220 }
9221 /* equals sg_entry_cnt * 2 */
9222 sg_list_dwords = sg_entry_cnt << 1;
9223 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
9224 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
9225 sg_entry_cnt = 0;
9226 }
9227
9228 scsi_sg_q.q_no = next_qp;
9229 AscMemWordCopyPtrToLram(iop_base,
9230 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
9231 (uchar *)&scsi_sg_q,
9232 sizeof(ASC_SG_LIST_Q) >> 1);
9233
9234 AscMemDWordCopyPtrToLram(iop_base,
9235 q_addr + ASC_SGQ_LIST_BEG,
9236 (uchar *)&sg_head->
9237 sg_list[scsiq->next_sg_index],
9238 sg_list_dwords);
9239
9240 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
9241
9242 /*
9243 * If the just completed SG queue contained the
9244 * last SG element, then no more SG queues need
9245 * to be written.
9246 */
9247 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
9248 break;
9249 }
9250
9251 next_qp = AscReadLramByte(iop_base,
9252 (ushort)(q_addr +
9253 ASC_SCSIQ_B_FWD));
9254 q_addr = ASC_QNO_TO_QADDR(next_qp);
9255 }
9256
9257 /*
9258 * Clear the halt condition so the RISC will be restarted
9259 * after the return.
9260 */
9261 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
9262 return (0);
9263 }
9264#endif /* CC_VERY_LONG_SG_LIST */
9265 return (0);
9266}
9267
9268/*
9269 * void
9270 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9271 *
9272 * Calling/Exit State:
9273 * none
9274 *
9275 * Description:
9276 * Input an ASC_QDONE_INFO structure from the chip
9277 */
9278static void
9279DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
9280{
9281 int i;
9282 ushort word;
9283
9284 AscSetChipLramAddr(iop_base, s_addr);
9285 for (i = 0; i < 2 * words; i += 2) {
9286 if (i == 10) {
9287 continue;
9288 }
9289 word = inpw(iop_base + IOP_RAM_DATA);
9290 inbuf[i] = word & 0xff;
9291 inbuf[i + 1] = (word >> 8) & 0xff;
9292 }
9293 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
9294}
9295
9296static uchar
9297_AscCopyLramScsiDoneQ(PortAddr iop_base,
9298 ushort q_addr,
9299 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
9300{
9301 ushort _val;
9302 uchar sg_queue_cnt;
9303
9304 DvcGetQinfo(iop_base,
9305 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
9306 (uchar *)scsiq,
9307 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
9308
9309 _val = AscReadLramWord(iop_base,
9310 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
9311 scsiq->q_status = (uchar)_val;
9312 scsiq->q_no = (uchar)(_val >> 8);
9313 _val = AscReadLramWord(iop_base,
9314 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
9315 scsiq->cntl = (uchar)_val;
9316 sg_queue_cnt = (uchar)(_val >> 8);
9317 _val = AscReadLramWord(iop_base,
9318 (ushort)(q_addr +
9319 (ushort)ASC_SCSIQ_B_SENSE_LEN));
9320 scsiq->sense_len = (uchar)_val;
9321 scsiq->extra_bytes = (uchar)(_val >> 8);
9322
9323 /*
9324 * Read high word of remain bytes from alternate location.
9325 */
9326 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
9327 (ushort)(q_addr +
9328 (ushort)
9329 ASC_SCSIQ_W_ALT_DC1)))
9330 << 16);
9331 /*
9332 * Read low word of remain bytes from original location.
9333 */
9334 scsiq->remain_bytes += AscReadLramWord(iop_base,
9335 (ushort)(q_addr + (ushort)
9336 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
9337
9338 scsiq->remain_bytes &= max_dma_count;
9339 return sg_queue_cnt;
9340}
9341
9342/*
9343 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
9344 *
9345 * Interrupt callback function for the Narrow SCSI Asc Library.
9346 */
9347static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9348{
9349 asc_board_t *boardp;
9350 struct scsi_cmnd *scp;
9351 struct Scsi_Host *shost;
9352
9353 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
9354 (ulong)asc_dvc_varp, (ulong)qdonep);
9355 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
9356
9357 /*
9358 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
9359 * command that has been completed.
9360 */
9361 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
9362 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
9363
9364 if (scp == NULL) {
9365 ASC_PRINT("asc_isr_callback: scp is NULL\n");
9366 return;
9367 }
9368 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
9369
9370 shost = scp->device->host;
9371 ASC_STATS(shost, callback);
9372 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
9373
9374 boardp = ASC_BOARDP(shost);
9375 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
9376
9377 /*
9378 * 'qdonep' contains the command's ending status.
9379 */
9380 switch (qdonep->d3.done_stat) {
9381 case QD_NO_ERROR:
9382 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
9383 scp->result = 0;
9384
9385 /*
9386 * Check for an underrun condition.
9387 *
9388 * If there was no error and an underrun condition, then
9389 * return the number of underrun bytes.
9390 */
9391 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
9392 qdonep->remain_bytes <= scp->request_bufflen) {
9393 ASC_DBG1(1,
9394 "asc_isr_callback: underrun condition %u bytes\n",
9395 (unsigned)qdonep->remain_bytes);
9396 scp->resid = qdonep->remain_bytes;
9397 }
9398 break;
9399
9400 case QD_WITH_ERROR:
9401 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
9402 switch (qdonep->d3.host_stat) {
9403 case QHSTA_NO_ERROR:
9404 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
9405 ASC_DBG(2,
9406 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
9407 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
9408 sizeof(scp->sense_buffer));
9409 /*
9410 * Note: The 'status_byte()' macro used by
9411 * target drivers defined in scsi.h shifts the
9412 * status byte returned by host drivers right
9413 * by 1 bit. This is why target drivers also
9414 * use right shifted status byte definitions.
9415 * For instance target drivers use
9416 * CHECK_CONDITION, defined to 0x1, instead of
9417 * the SCSI defined check condition value of
9418 * 0x2. Host drivers are supposed to return
9419 * the status byte as it is defined by SCSI.
9420 */
9421 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
9422 STATUS_BYTE(qdonep->d3.scsi_stat);
9423 } else {
9424 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
9425 }
9426 break;
9427
9428 default:
9429 /* QHSTA error occurred */
9430 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
9431 qdonep->d3.host_stat);
9432 scp->result = HOST_BYTE(DID_BAD_TARGET);
9433 break;
9434 }
9435 break;
9436
9437 case QD_ABORTED_BY_HOST:
9438 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
9439 scp->result =
9440 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
9441 scsi_msg) |
9442 STATUS_BYTE(qdonep->d3.scsi_stat);
9443 break;
9444
9445 default:
9446 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
9447 qdonep->d3.done_stat);
9448 scp->result =
9449 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
9450 scsi_msg) |
9451 STATUS_BYTE(qdonep->d3.scsi_stat);
9452 break;
9453 }
9454
9455 /*
9456 * If the 'init_tidmask' bit isn't already set for the target and the
9457 * current request finished normally, then set the bit for the target
9458 * to indicate that a device is present.
9459 */
9460 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
9461 qdonep->d3.done_stat == QD_NO_ERROR &&
9462 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
9463 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
9464 }
9465
9466 asc_scsi_done(scp);
9467
9468 return;
9469}
9470
9471static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
9472{
9473 uchar next_qp;
9474 uchar n_q_used;
9475 uchar sg_list_qp;
9476 uchar sg_queue_cnt;
9477 uchar q_cnt;
9478 uchar done_q_tail;
9479 uchar tid_no;
9480 ASC_SCSI_BIT_ID_TYPE scsi_busy;
9481 ASC_SCSI_BIT_ID_TYPE target_id;
9482 PortAddr iop_base;
9483 ushort q_addr;
9484 ushort sg_q_addr;
9485 uchar cur_target_qng;
9486 ASC_QDONE_INFO scsiq_buf;
9487 ASC_QDONE_INFO *scsiq;
9488 int false_overrun;
9489
9490 iop_base = asc_dvc->iop_base;
9491 n_q_used = 1;
9492 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
9493 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
9494 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
9495 next_qp = AscReadLramByte(iop_base,
9496 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
9497 if (next_qp != ASC_QLINK_END) {
9498 AscPutVarDoneQTail(iop_base, next_qp);
9499 q_addr = ASC_QNO_TO_QADDR(next_qp);
9500 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
9501 asc_dvc->max_dma_count);
9502 AscWriteLramByte(iop_base,
9503 (ushort)(q_addr +
9504 (ushort)ASC_SCSIQ_B_STATUS),
9505 (uchar)(scsiq->
9506 q_status & (uchar)~(QS_READY |
9507 QS_ABORTED)));
9508 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
9509 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
9510 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
9511 sg_q_addr = q_addr;
9512 sg_list_qp = next_qp;
9513 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
9514 sg_list_qp = AscReadLramByte(iop_base,
9515 (ushort)(sg_q_addr
9516 + (ushort)
9517 ASC_SCSIQ_B_FWD));
9518 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
9519 if (sg_list_qp == ASC_QLINK_END) {
9520 AscSetLibErrorCode(asc_dvc,
9521 ASCQ_ERR_SG_Q_LINKS);
9522 scsiq->d3.done_stat = QD_WITH_ERROR;
9523 scsiq->d3.host_stat =
9524 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
9525 goto FATAL_ERR_QDONE;
9526 }
9527 AscWriteLramByte(iop_base,
9528 (ushort)(sg_q_addr + (ushort)
9529 ASC_SCSIQ_B_STATUS),
9530 QS_FREE);
9531 }
9532 n_q_used = sg_queue_cnt + 1;
9533 AscPutVarDoneQTail(iop_base, sg_list_qp);
9534 }
9535 if (asc_dvc->queue_full_or_busy & target_id) {
9536 cur_target_qng = AscReadLramByte(iop_base,
9537 (ushort)((ushort)
9538 ASC_QADR_BEG
9539 + (ushort)
9540 scsiq->d2.
9541 target_ix));
9542 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
9543 scsi_busy = AscReadLramByte(iop_base, (ushort)
9544 ASCV_SCSIBUSY_B);
9545 scsi_busy &= ~target_id;
9546 AscWriteLramByte(iop_base,
9547 (ushort)ASCV_SCSIBUSY_B,
9548 scsi_busy);
9549 asc_dvc->queue_full_or_busy &= ~target_id;
9550 }
9551 }
9552 if (asc_dvc->cur_total_qng >= n_q_used) {
9553 asc_dvc->cur_total_qng -= n_q_used;
9554 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
9555 asc_dvc->cur_dvc_qng[tid_no]--;
9556 }
9557 } else {
9558 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
9559 scsiq->d3.done_stat = QD_WITH_ERROR;
9560 goto FATAL_ERR_QDONE;
9561 }
9562 if ((scsiq->d2.srb_ptr == 0UL) ||
9563 ((scsiq->q_status & QS_ABORTED) != 0)) {
9564 return (0x11);
9565 } else if (scsiq->q_status == QS_DONE) {
9566 false_overrun = FALSE;
9567 if (scsiq->extra_bytes != 0) {
9568 scsiq->remain_bytes +=
9569 (ADV_DCNT)scsiq->extra_bytes;
9570 }
9571 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
9572 if (scsiq->d3.host_stat ==
9573 QHSTA_M_DATA_OVER_RUN) {
9574 if ((scsiq->
9575 cntl & (QC_DATA_IN | QC_DATA_OUT))
9576 == 0) {
9577 scsiq->d3.done_stat =
9578 QD_NO_ERROR;
9579 scsiq->d3.host_stat =
9580 QHSTA_NO_ERROR;
9581 } else if (false_overrun) {
9582 scsiq->d3.done_stat =
9583 QD_NO_ERROR;
9584 scsiq->d3.host_stat =
9585 QHSTA_NO_ERROR;
9586 }
9587 } else if (scsiq->d3.host_stat ==
9588 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
9589 AscStopChip(iop_base);
9590 AscSetChipControl(iop_base,
9591 (uchar)(CC_SCSI_RESET
9592 | CC_HALT));
9593 udelay(60);
9594 AscSetChipControl(iop_base, CC_HALT);
9595 AscSetChipStatus(iop_base,
9596 CIW_CLR_SCSI_RESET_INT);
9597 AscSetChipStatus(iop_base, 0);
9598 AscSetChipControl(iop_base, 0);
9599 }
9600 }
9601 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9602 asc_isr_callback(asc_dvc, scsiq);
9603 } else {
9604 if ((AscReadLramByte(iop_base,
9605 (ushort)(q_addr + (ushort)
9606 ASC_SCSIQ_CDB_BEG))
9607 == START_STOP)) {
9608 asc_dvc->unit_not_ready &= ~target_id;
9609 if (scsiq->d3.done_stat != QD_NO_ERROR) {
9610 asc_dvc->start_motor &=
9611 ~target_id;
9612 }
9613 }
9614 }
9615 return (1);
9616 } else {
9617 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
9618 FATAL_ERR_QDONE:
9619 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
9620 asc_isr_callback(asc_dvc, scsiq);
9621 }
9622 return (0x80);
9623 }
9624 }
9625 return (0);
9626}
9627
9628static int AscISR(ASC_DVC_VAR *asc_dvc)
9629{
9630 ASC_CS_TYPE chipstat;
9631 PortAddr iop_base;
9632 ushort saved_ram_addr;
9633 uchar ctrl_reg;
9634 uchar saved_ctrl_reg;
9635 int int_pending;
9636 int status;
9637 uchar host_flag;
9638
9639 iop_base = asc_dvc->iop_base;
9640 int_pending = FALSE;
9641
9642 if (AscIsIntPending(iop_base) == 0)
9643 return int_pending;
9644
9645 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
9646 return ERR;
9647 }
9648 if (asc_dvc->in_critical_cnt != 0) {
9649 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
9650 return ERR;
9651 }
9652 if (asc_dvc->is_in_int) {
9653 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
9654 return ERR;
9655 }
9656 asc_dvc->is_in_int = TRUE;
9657 ctrl_reg = AscGetChipControl(iop_base);
9658 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
9659 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
9660 chipstat = AscGetChipStatus(iop_base);
9661 if (chipstat & CSW_SCSI_RESET_LATCH) {
9662 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
9663 int i = 10;
9664 int_pending = TRUE;
9665 asc_dvc->sdtr_done = 0;
9666 saved_ctrl_reg &= (uchar)(~CC_HALT);
9667 while ((AscGetChipStatus(iop_base) &
9668 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
9669 mdelay(100);
9670 }
9671 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
9672 AscSetChipControl(iop_base, CC_HALT);
9673 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9674 AscSetChipStatus(iop_base, 0);
9675 chipstat = AscGetChipStatus(iop_base);
9676 }
9677 }
9678 saved_ram_addr = AscGetChipLramAddr(iop_base);
9679 host_flag = AscReadLramByte(iop_base,
9680 ASCV_HOST_FLAG_B) &
9681 (uchar)(~ASC_HOST_FLAG_IN_ISR);
9682 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
9683 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
9684 if ((chipstat & CSW_INT_PENDING) || (int_pending)) {
9685 AscAckInterrupt(iop_base);
9686 int_pending = TRUE;
9687 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
9688 if (AscIsrChipHalted(asc_dvc) == ERR) {
9689 goto ISR_REPORT_QDONE_FATAL_ERROR;
9690 } else {
9691 saved_ctrl_reg &= (uchar)(~CC_HALT);
9692 }
9693 } else {
9694 ISR_REPORT_QDONE_FATAL_ERROR:
9695 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
9696 while (((status =
9697 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
9698 }
9699 } else {
9700 do {
9701 if ((status =
9702 AscIsrQDone(asc_dvc)) == 1) {
9703 break;
9704 }
9705 } while (status == 0x11);
9706 }
9707 if ((status & 0x80) != 0)
9708 int_pending = ERR;
9709 }
9710 }
9711 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
9712 AscSetChipLramAddr(iop_base, saved_ram_addr);
9713 AscSetChipControl(iop_base, saved_ctrl_reg);
9714 asc_dvc->is_in_int = FALSE;
9715 return int_pending;
9716}
9717
9718/*
9719 * advansys_reset()
9720 *
9721 * Reset the bus associated with the command 'scp'.
9722 *
9723 * This function runs its own thread. Interrupts must be blocked but
9724 * sleeping is allowed and no locking other than for host structures is
9725 * required. Returns SUCCESS or FAILED.
9726 */
9727static int advansys_reset(struct scsi_cmnd *scp)
9728{
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009729 struct Scsi_Host *shost = scp->device->host;
9730 struct asc_board *boardp = ASC_BOARDP(shost);
9731 unsigned long flags;
Matthew Wilcox51219352007-10-02 21:55:22 -04009732 int status;
9733 int ret = SUCCESS;
9734
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009735 ASC_DBG1(1, "advansys_reset: 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -04009736
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009737 ASC_STATS(shost, reset);
Matthew Wilcox51219352007-10-02 21:55:22 -04009738
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009739 scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009740
9741 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009742 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009743
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009744 /* Reset the chip and SCSI bus. */
Matthew Wilcox51219352007-10-02 21:55:22 -04009745 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009746 status = AscInitAsc1000Driver(asc_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009747
9748 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009749 if (asc_dvc->err_code) {
9750 scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
9751 "0x%x\n", asc_dvc->err_code);
Matthew Wilcox51219352007-10-02 21:55:22 -04009752 ret = FAILED;
9753 } else if (status) {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009754 scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
9755 "0x%x\n", status);
Matthew Wilcox51219352007-10-02 21:55:22 -04009756 } else {
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009757 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9758 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009759 }
9760
9761 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
9762 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcox51219352007-10-02 21:55:22 -04009763 } else {
9764 /*
Matthew Wilcox51219352007-10-02 21:55:22 -04009765 * If the suggest reset bus flags are set, then reset the bus.
9766 * Otherwise only reset the device.
9767 */
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009768 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox51219352007-10-02 21:55:22 -04009769
9770 /*
9771 * Reset the target's SCSI bus.
9772 */
9773 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009774 switch (AdvResetChipAndSB(adv_dvc)) {
Matthew Wilcox51219352007-10-02 21:55:22 -04009775 case ASC_TRUE:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009776 scmd_printk(KERN_INFO, scp, "SCSI bus reset "
9777 "successful\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009778 break;
9779 case ASC_FALSE:
9780 default:
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009781 scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n");
Matthew Wilcox51219352007-10-02 21:55:22 -04009782 ret = FAILED;
9783 break;
9784 }
9785 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcox52fa0772007-10-02 21:55:26 -04009786 AdvISR(adv_dvc);
Matthew Wilcox51219352007-10-02 21:55:22 -04009787 }
Matthew Wilcox51219352007-10-02 21:55:22 -04009788
9789 /* Save the time of the most recently completed reset. */
9790 boardp->last_reset = jiffies;
Matthew Wilcox51219352007-10-02 21:55:22 -04009791 spin_unlock_irqrestore(&boardp->lock, flags);
9792
9793 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
9794
9795 return ret;
9796}
9797
9798/*
9799 * advansys_biosparam()
9800 *
9801 * Translate disk drive geometry if the "BIOS greater than 1 GB"
9802 * support is enabled for a drive.
9803 *
9804 * ip (information pointer) is an int array with the following definition:
9805 * ip[0]: heads
9806 * ip[1]: sectors
9807 * ip[2]: cylinders
9808 */
9809static int
9810advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
9811 sector_t capacity, int ip[])
9812{
9813 asc_board_t *boardp;
9814
9815 ASC_DBG(1, "advansys_biosparam: begin\n");
9816 ASC_STATS(sdev->host, biosparam);
9817 boardp = ASC_BOARDP(sdev->host);
9818 if (ASC_NARROW_BOARD(boardp)) {
9819 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
9820 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
9821 ip[0] = 255;
9822 ip[1] = 63;
9823 } else {
9824 ip[0] = 64;
9825 ip[1] = 32;
9826 }
9827 } else {
9828 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
9829 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
9830 ip[0] = 255;
9831 ip[1] = 63;
9832 } else {
9833 ip[0] = 64;
9834 ip[1] = 32;
9835 }
9836 }
9837 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
9838 ASC_DBG(1, "advansys_biosparam: end\n");
9839 return 0;
9840}
9841
9842/*
9843 * First-level interrupt handler.
9844 *
9845 * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host.
9846 */
9847static irqreturn_t advansys_interrupt(int irq, void *dev_id)
9848{
9849 unsigned long flags;
9850 struct Scsi_Host *shost = dev_id;
9851 asc_board_t *boardp = ASC_BOARDP(shost);
9852 irqreturn_t result = IRQ_NONE;
9853
9854 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
9855 spin_lock_irqsave(&boardp->lock, flags);
9856 if (ASC_NARROW_BOARD(boardp)) {
9857 if (AscIsIntPending(shost->io_port)) {
9858 result = IRQ_HANDLED;
9859 ASC_STATS(shost, interrupt);
9860 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
9861 AscISR(&boardp->dvc_var.asc_dvc_var);
9862 }
9863 } else {
9864 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
9865 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
9866 result = IRQ_HANDLED;
9867 ASC_STATS(shost, interrupt);
9868 }
9869 }
9870 spin_unlock_irqrestore(&boardp->lock, flags);
9871
9872 ASC_DBG(1, "advansys_interrupt: end\n");
9873 return result;
9874}
9875
9876static int AscHostReqRiscHalt(PortAddr iop_base)
9877{
9878 int count = 0;
9879 int sta = 0;
9880 uchar saved_stop_code;
9881
9882 if (AscIsChipHalted(iop_base))
9883 return (1);
9884 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
9885 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
9886 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
9887 do {
9888 if (AscIsChipHalted(iop_base)) {
9889 sta = 1;
9890 break;
9891 }
9892 mdelay(100);
9893 } while (count++ < 20);
9894 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
9895 return (sta);
9896}
9897
9898static int
9899AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
9900{
9901 int sta = FALSE;
9902
9903 if (AscHostReqRiscHalt(iop_base)) {
9904 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
9905 AscStartChip(iop_base);
9906 }
9907 return sta;
9908}
9909
9910static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
9911{
9912 char type = sdev->type;
9913 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
9914
9915 if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN))
9916 return;
9917 if (asc_dvc->init_sdtr & tid_bits)
9918 return;
9919
9920 if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0))
9921 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9922
9923 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
9924 if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) ||
9925 (type == TYPE_ROM) || (type == TYPE_TAPE))
9926 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9927
9928 if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
9929 AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id,
9930 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
9931}
9932
9933static void
9934advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
9935{
9936 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
9937 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
9938
9939 if (sdev->lun == 0) {
9940 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
9941 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
9942 asc_dvc->init_sdtr |= tid_bit;
9943 } else {
9944 asc_dvc->init_sdtr &= ~tid_bit;
9945 }
9946
9947 if (orig_init_sdtr != asc_dvc->init_sdtr)
9948 AscAsyncFix(asc_dvc, sdev);
9949 }
9950
9951 if (sdev->tagged_supported) {
9952 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
9953 if (sdev->lun == 0) {
9954 asc_dvc->cfg->can_tagged_qng |= tid_bit;
9955 asc_dvc->use_tagged_qng |= tid_bit;
9956 }
9957 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
9958 asc_dvc->max_dvc_qng[sdev->id]);
9959 }
9960 } else {
9961 if (sdev->lun == 0) {
9962 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
9963 asc_dvc->use_tagged_qng &= ~tid_bit;
9964 }
9965 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
9966 }
9967
9968 if ((sdev->lun == 0) &&
9969 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
9970 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
9971 asc_dvc->cfg->disc_enable);
9972 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
9973 asc_dvc->use_tagged_qng);
9974 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
9975 asc_dvc->cfg->can_tagged_qng);
9976
9977 asc_dvc->max_dvc_qng[sdev->id] =
9978 asc_dvc->cfg->max_tag_qng[sdev->id];
9979 AscWriteLramByte(asc_dvc->iop_base,
9980 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
9981 asc_dvc->max_dvc_qng[sdev->id]);
9982 }
9983}
9984
9985/*
9986 * Wide Transfers
9987 *
9988 * If the EEPROM enabled WDTR for the device and the device supports wide
9989 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
9990 * write the new value to the microcode.
9991 */
9992static void
9993advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
9994{
9995 unsigned short cfg_word;
9996 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
9997 if ((cfg_word & tidmask) != 0)
9998 return;
9999
10000 cfg_word |= tidmask;
10001 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
10002
10003 /*
10004 * Clear the microcode SDTR and WDTR negotiation done indicators for
10005 * the target to cause it to negotiate with the new setting set above.
10006 * WDTR when accepted causes the target to enter asynchronous mode, so
10007 * SDTR must be negotiated.
10008 */
10009 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10010 cfg_word &= ~tidmask;
10011 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10012 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
10013 cfg_word &= ~tidmask;
10014 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
10015}
10016
10017/*
10018 * Synchronous Transfers
10019 *
10020 * If the EEPROM enabled SDTR for the device and the device
10021 * supports synchronous transfers, then turn on the device's
10022 * 'sdtr_able' bit. Write the new value to the microcode.
10023 */
10024static void
10025advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
10026{
10027 unsigned short cfg_word;
10028 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
10029 if ((cfg_word & tidmask) != 0)
10030 return;
10031
10032 cfg_word |= tidmask;
10033 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
10034
10035 /*
10036 * Clear the microcode "SDTR negotiation" done indicator for the
10037 * target to cause it to negotiate with the new setting set above.
10038 */
10039 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10040 cfg_word &= ~tidmask;
10041 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
10042}
10043
10044/*
10045 * PPR (Parallel Protocol Request) Capable
10046 *
10047 * If the device supports DT mode, then it must be PPR capable.
10048 * The PPR message will be used in place of the SDTR and WDTR
10049 * messages to negotiate synchronous speed and offset, transfer
10050 * width, and protocol options.
10051 */
10052static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
10053 AdvPortAddr iop_base, unsigned short tidmask)
10054{
10055 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
10056 adv_dvc->ppr_able |= tidmask;
10057 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
10058}
10059
10060static void
10061advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
10062{
10063 AdvPortAddr iop_base = adv_dvc->iop_base;
10064 unsigned short tidmask = 1 << sdev->id;
10065
10066 if (sdev->lun == 0) {
10067 /*
10068 * Handle WDTR, SDTR, and Tag Queuing. If the feature
10069 * is enabled in the EEPROM and the device supports the
10070 * feature, then enable it in the microcode.
10071 */
10072
10073 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
10074 advansys_wide_enable_wdtr(iop_base, tidmask);
10075 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
10076 advansys_wide_enable_sdtr(iop_base, tidmask);
10077 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
10078 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
10079
10080 /*
10081 * Tag Queuing is disabled for the BIOS which runs in polled
10082 * mode and would see no benefit from Tag Queuing. Also by
10083 * disabling Tag Queuing in the BIOS devices with Tag Queuing
10084 * bugs will at least work with the BIOS.
10085 */
10086 if ((adv_dvc->tagqng_able & tidmask) &&
10087 sdev->tagged_supported) {
10088 unsigned short cfg_word;
10089 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
10090 cfg_word |= tidmask;
10091 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
10092 cfg_word);
10093 AdvWriteByteLram(iop_base,
10094 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
10095 adv_dvc->max_dvc_qng);
10096 }
10097 }
10098
10099 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
10100 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
10101 adv_dvc->max_dvc_qng);
10102 } else {
10103 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
10104 }
10105}
10106
10107/*
10108 * Set the number of commands to queue per device for the
10109 * specified host adapter.
10110 */
10111static int advansys_slave_configure(struct scsi_device *sdev)
10112{
10113 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040010114
Matthew Wilcox51219352007-10-02 21:55:22 -040010115 if (ASC_NARROW_BOARD(boardp))
10116 advansys_narrow_slave_configure(sdev,
10117 &boardp->dvc_var.asc_dvc_var);
10118 else
10119 advansys_wide_slave_configure(sdev,
10120 &boardp->dvc_var.adv_dvc_var);
10121
10122 return 0;
10123}
10124
Matthew Wilcox05848b62007-10-02 21:55:25 -040010125static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
10126 struct asc_scsi_q *asc_scsi_q)
Matthew Wilcox51219352007-10-02 21:55:22 -040010127{
Matthew Wilcox05848b62007-10-02 21:55:25 -040010128 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
Matthew Wilcox51219352007-10-02 21:55:22 -040010129
10130 /*
10131 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
10132 */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010133 asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040010134
10135 /*
10136 * Build the ASC_SCSI_Q request.
10137 */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010138 asc_scsi_q->cdbptr = &scp->cmnd[0];
10139 asc_scsi_q->q2.cdb_len = scp->cmd_len;
10140 asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
10141 asc_scsi_q->q1.target_lun = scp->device->lun;
10142 asc_scsi_q->q2.target_ix =
Matthew Wilcox51219352007-10-02 21:55:22 -040010143 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
Matthew Wilcox05848b62007-10-02 21:55:25 -040010144 asc_scsi_q->q1.sense_addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010145 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010146 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
Matthew Wilcox51219352007-10-02 21:55:22 -040010147
10148 /*
10149 * If there are any outstanding requests for the current target,
10150 * then every 255th request send an ORDERED request. This heuristic
10151 * tries to retain the benefit of request sorting while preventing
10152 * request starvation. 255 is the max number of tags or pending commands
10153 * a device may have outstanding.
10154 *
10155 * The request count is incremented below for every successfully
10156 * started request.
10157 *
10158 */
10159 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
10160 (boardp->reqcnt[scp->device->id] % 255) == 0) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010161 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010162 } else {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010163 asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG;
Matthew Wilcox51219352007-10-02 21:55:22 -040010164 }
10165
10166 /*
10167 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
10168 * buffer command.
10169 */
10170 if (scp->use_sg == 0) {
10171 /*
10172 * CDB request of single contiguous buffer.
10173 */
10174 ASC_STATS(scp->device->host, cont_cnt);
10175 scp->SCp.dma_handle = scp->request_bufflen ?
10176 dma_map_single(boardp->dev, scp->request_buffer,
10177 scp->request_bufflen,
10178 scp->sc_data_direction) : 0;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010179 asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
10180 asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen);
Matthew Wilcox51219352007-10-02 21:55:22 -040010181 ASC_STATS_ADD(scp->device->host, cont_xfer,
10182 ASC_CEILING(scp->request_bufflen, 512));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010183 asc_scsi_q->q1.sg_queue_cnt = 0;
10184 asc_scsi_q->sg_head = NULL;
Matthew Wilcox51219352007-10-02 21:55:22 -040010185 } else {
10186 /*
10187 * CDB scatter-gather request list.
10188 */
10189 int sgcnt;
10190 int use_sg;
10191 struct scatterlist *slp;
Matthew Wilcox05848b62007-10-02 21:55:25 -040010192 struct asc_sg_head *asc_sg_head;
Matthew Wilcox51219352007-10-02 21:55:22 -040010193
10194 slp = (struct scatterlist *)scp->request_buffer;
10195 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10196 scp->sc_data_direction);
10197
10198 if (use_sg > scp->device->host->sg_tablesize) {
10199 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
10200 "sg_tablesize %d\n", boardp->id, use_sg,
10201 scp->device->host->sg_tablesize);
10202 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10203 scp->sc_data_direction);
10204 scp->result = HOST_BYTE(DID_ERROR);
10205 return ASC_ERROR;
10206 }
10207
10208 ASC_STATS(scp->device->host, sg_cnt);
10209
Matthew Wilcox05848b62007-10-02 21:55:25 -040010210 asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
10211 use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
10212 if (!asc_sg_head) {
10213 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10214 scp->sc_data_direction);
10215 scp->result = HOST_BYTE(DID_SOFT_ERROR);
10216 return ASC_ERROR;
10217 }
Matthew Wilcox51219352007-10-02 21:55:22 -040010218
Matthew Wilcox05848b62007-10-02 21:55:25 -040010219 asc_scsi_q->q1.cntl |= QC_SG_HEAD;
10220 asc_scsi_q->sg_head = asc_sg_head;
10221 asc_scsi_q->q1.data_cnt = 0;
10222 asc_scsi_q->q1.data_addr = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040010223 /* This is a byte value, otherwise it would need to be swapped. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040010224 asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
Matthew Wilcox51219352007-10-02 21:55:22 -040010225 ASC_STATS_ADD(scp->device->host, sg_elem,
Matthew Wilcox05848b62007-10-02 21:55:25 -040010226 asc_sg_head->entry_cnt);
Matthew Wilcox51219352007-10-02 21:55:22 -040010227
10228 /*
10229 * Convert scatter-gather list into ASC_SG_HEAD list.
10230 */
10231 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
Matthew Wilcox05848b62007-10-02 21:55:25 -040010232 asc_sg_head->sg_list[sgcnt].addr =
Matthew Wilcox51219352007-10-02 21:55:22 -040010233 cpu_to_le32(sg_dma_address(slp));
Matthew Wilcox05848b62007-10-02 21:55:25 -040010234 asc_sg_head->sg_list[sgcnt].bytes =
Matthew Wilcox51219352007-10-02 21:55:22 -040010235 cpu_to_le32(sg_dma_len(slp));
10236 ASC_STATS_ADD(scp->device->host, sg_xfer,
10237 ASC_CEILING(sg_dma_len(slp), 512));
10238 }
10239 }
10240
10241 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
10242 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10243
10244 return ASC_NOERROR;
10245}
10246
10247/*
10248 * Build scatter-gather list for Adv Library (Wide Board).
10249 *
10250 * Additional ADV_SG_BLOCK structures will need to be allocated
10251 * if the total number of scatter-gather elements exceeds
10252 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
10253 * assumed to be physically contiguous.
10254 *
10255 * Return:
10256 * ADV_SUCCESS(1) - SG List successfully created
10257 * ADV_ERROR(-1) - SG List creation failed
10258 */
10259static int
10260adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
10261 int use_sg)
10262{
10263 adv_sgblk_t *sgblkp;
10264 ADV_SCSI_REQ_Q *scsiqp;
10265 struct scatterlist *slp;
10266 int sg_elem_cnt;
10267 ADV_SG_BLOCK *sg_block, *prev_sg_block;
10268 ADV_PADDR sg_block_paddr;
10269 int i;
10270
10271 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10272 slp = (struct scatterlist *)scp->request_buffer;
10273 sg_elem_cnt = use_sg;
10274 prev_sg_block = NULL;
10275 reqp->sgblkp = NULL;
10276
10277 for (;;) {
10278 /*
10279 * Allocate a 'adv_sgblk_t' structure from the board free
10280 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
10281 * (15) scatter-gather elements.
10282 */
10283 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
10284 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
10285 ASC_STATS(scp->device->host, adv_build_nosg);
10286
10287 /*
10288 * Allocation failed. Free 'adv_sgblk_t' structures
10289 * already allocated for the request.
10290 */
10291 while ((sgblkp = reqp->sgblkp) != NULL) {
10292 /* Remove 'sgblkp' from the request list. */
10293 reqp->sgblkp = sgblkp->next_sgblkp;
10294
10295 /* Add 'sgblkp' to the board free list. */
10296 sgblkp->next_sgblkp = boardp->adv_sgblkp;
10297 boardp->adv_sgblkp = sgblkp;
10298 }
10299 return ASC_BUSY;
10300 }
10301
10302 /* Complete 'adv_sgblk_t' board allocation. */
10303 boardp->adv_sgblkp = sgblkp->next_sgblkp;
10304 sgblkp->next_sgblkp = NULL;
10305
10306 /*
10307 * Get 8 byte aligned virtual and physical addresses
10308 * for the allocated ADV_SG_BLOCK structure.
10309 */
10310 sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
10311 sg_block_paddr = virt_to_bus(sg_block);
10312
10313 /*
10314 * Check if this is the first 'adv_sgblk_t' for the
10315 * request.
10316 */
10317 if (reqp->sgblkp == NULL) {
10318 /* Request's first scatter-gather block. */
10319 reqp->sgblkp = sgblkp;
10320
10321 /*
10322 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
10323 * address pointers.
10324 */
10325 scsiqp->sg_list_ptr = sg_block;
10326 scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
10327 } else {
10328 /* Request's second or later scatter-gather block. */
10329 sgblkp->next_sgblkp = reqp->sgblkp;
10330 reqp->sgblkp = sgblkp;
10331
10332 /*
10333 * Point the previous ADV_SG_BLOCK structure to
10334 * the newly allocated ADV_SG_BLOCK structure.
10335 */
10336 prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
10337 }
10338
10339 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
10340 sg_block->sg_list[i].sg_addr =
10341 cpu_to_le32(sg_dma_address(slp));
10342 sg_block->sg_list[i].sg_count =
10343 cpu_to_le32(sg_dma_len(slp));
10344 ASC_STATS_ADD(scp->device->host, sg_xfer,
10345 ASC_CEILING(sg_dma_len(slp), 512));
10346
10347 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
10348 sg_block->sg_cnt = i + 1;
10349 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
10350 return ADV_SUCCESS;
10351 }
10352 slp++;
10353 }
10354 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
10355 prev_sg_block = sg_block;
10356 }
10357}
10358
10359/*
10360 * Build a request structure for the Adv Library (Wide Board).
10361 *
10362 * If an adv_req_t can not be allocated to issue the request,
10363 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
10364 *
10365 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
10366 * microcode for DMA addresses or math operations are byte swapped
10367 * to little-endian order.
10368 */
10369static int
10370adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
10371 ADV_SCSI_REQ_Q **adv_scsiqpp)
10372{
10373 adv_req_t *reqp;
10374 ADV_SCSI_REQ_Q *scsiqp;
10375 int i;
10376 int ret;
10377
10378 /*
10379 * Allocate an adv_req_t structure from the board to execute
10380 * the command.
10381 */
10382 if (boardp->adv_reqp == NULL) {
10383 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
10384 ASC_STATS(scp->device->host, adv_build_noreq);
10385 return ASC_BUSY;
10386 } else {
10387 reqp = boardp->adv_reqp;
10388 boardp->adv_reqp = reqp->next_reqp;
10389 reqp->next_reqp = NULL;
10390 }
10391
10392 /*
10393 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
10394 */
10395 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
10396
10397 /*
10398 * Initialize the structure.
10399 */
10400 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
10401
10402 /*
10403 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
10404 */
10405 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
10406
10407 /*
10408 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
10409 */
10410 reqp->cmndp = scp;
10411
10412 /*
10413 * Build the ADV_SCSI_REQ_Q request.
10414 */
10415
10416 /* Set CDB length and copy it to the request structure. */
10417 scsiqp->cdb_len = scp->cmd_len;
10418 /* Copy first 12 CDB bytes to cdb[]. */
10419 for (i = 0; i < scp->cmd_len && i < 12; i++) {
10420 scsiqp->cdb[i] = scp->cmnd[i];
10421 }
10422 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
10423 for (; i < scp->cmd_len; i++) {
10424 scsiqp->cdb16[i - 12] = scp->cmnd[i];
10425 }
10426
10427 scsiqp->target_id = scp->device->id;
10428 scsiqp->target_lun = scp->device->lun;
10429
10430 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
10431 scsiqp->sense_len = sizeof(scp->sense_buffer);
10432
10433 /*
10434 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
10435 * buffer command.
10436 */
10437
10438 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10439 scsiqp->vdata_addr = scp->request_buffer;
10440 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
10441
10442 if (scp->use_sg == 0) {
10443 /*
10444 * CDB request of single contiguous buffer.
10445 */
10446 reqp->sgblkp = NULL;
10447 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
10448 if (scp->request_bufflen) {
10449 scsiqp->vdata_addr = scp->request_buffer;
10450 scp->SCp.dma_handle =
10451 dma_map_single(boardp->dev, scp->request_buffer,
10452 scp->request_bufflen,
10453 scp->sc_data_direction);
10454 } else {
10455 scsiqp->vdata_addr = NULL;
10456 scp->SCp.dma_handle = 0;
10457 }
10458 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
10459 scsiqp->sg_list_ptr = NULL;
10460 scsiqp->sg_real_addr = 0;
10461 ASC_STATS(scp->device->host, cont_cnt);
10462 ASC_STATS_ADD(scp->device->host, cont_xfer,
10463 ASC_CEILING(scp->request_bufflen, 512));
10464 } else {
10465 /*
10466 * CDB scatter-gather request list.
10467 */
10468 struct scatterlist *slp;
10469 int use_sg;
10470
10471 slp = (struct scatterlist *)scp->request_buffer;
10472 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
10473 scp->sc_data_direction);
10474
10475 if (use_sg > ADV_MAX_SG_LIST) {
10476 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
10477 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
10478 scp->device->host->sg_tablesize);
10479 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
10480 scp->sc_data_direction);
10481 scp->result = HOST_BYTE(DID_ERROR);
10482
10483 /*
10484 * Free the 'adv_req_t' structure by adding it back
10485 * to the board free list.
10486 */
10487 reqp->next_reqp = boardp->adv_reqp;
10488 boardp->adv_reqp = reqp;
10489
10490 return ASC_ERROR;
10491 }
10492
10493 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
10494 if (ret != ADV_SUCCESS) {
10495 /*
10496 * Free the adv_req_t structure by adding it back to
10497 * the board free list.
10498 */
10499 reqp->next_reqp = boardp->adv_reqp;
10500 boardp->adv_reqp = reqp;
10501
10502 return ret;
10503 }
10504
10505 ASC_STATS(scp->device->host, sg_cnt);
10506 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
10507 }
10508
10509 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
10510 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
10511
10512 *adv_scsiqpp = scsiqp;
10513
10514 return ASC_NOERROR;
10515}
10516
10517static int AscSgListToQueue(int sg_list)
10518{
10519 int n_sg_list_qs;
10520
10521 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
10522 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
10523 n_sg_list_qs++;
10524 return n_sg_list_qs + 1;
10525}
10526
10527static uint
10528AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
10529{
10530 uint cur_used_qs;
10531 uint cur_free_qs;
10532 ASC_SCSI_BIT_ID_TYPE target_id;
10533 uchar tid_no;
10534
10535 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
10536 tid_no = ASC_TIX_TO_TID(target_ix);
10537 if ((asc_dvc->unit_not_ready & target_id) ||
10538 (asc_dvc->queue_full_or_busy & target_id)) {
10539 return 0;
10540 }
10541 if (n_qs == 1) {
10542 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10543 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
10544 } else {
10545 cur_used_qs = (uint) asc_dvc->cur_total_qng +
10546 (uint) ASC_MIN_FREE_Q;
10547 }
10548 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
10549 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
10550 if (asc_dvc->cur_dvc_qng[tid_no] >=
10551 asc_dvc->max_dvc_qng[tid_no]) {
10552 return 0;
10553 }
10554 return cur_free_qs;
10555 }
10556 if (n_qs > 1) {
10557 if ((n_qs > asc_dvc->last_q_shortage)
10558 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
10559 asc_dvc->last_q_shortage = n_qs;
10560 }
10561 }
10562 return 0;
10563}
10564
10565static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
10566{
10567 ushort q_addr;
10568 uchar next_qp;
10569 uchar q_status;
10570
10571 q_addr = ASC_QNO_TO_QADDR(free_q_head);
10572 q_status = (uchar)AscReadLramByte(iop_base,
10573 (ushort)(q_addr +
10574 ASC_SCSIQ_B_STATUS));
10575 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
10576 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END))
10577 return next_qp;
10578 return ASC_QLINK_END;
10579}
10580
10581static uchar
10582AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
10583{
10584 uchar i;
10585
10586 for (i = 0; i < n_free_q; i++) {
10587 free_q_head = AscAllocFreeQueue(iop_base, free_q_head);
10588 if (free_q_head == ASC_QLINK_END)
10589 break;
10590 }
10591 return free_q_head;
10592}
10593
10594/*
10595 * void
10596 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10597 *
10598 * Calling/Exit State:
10599 * none
10600 *
10601 * Description:
10602 * Output an ASC_SCSI_Q structure to the chip
10603 */
10604static void
10605DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
10606{
10607 int i;
10608
10609 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
10610 AscSetChipLramAddr(iop_base, s_addr);
10611 for (i = 0; i < 2 * words; i += 2) {
10612 if (i == 4 || i == 20) {
10613 continue;
10614 }
10615 outpw(iop_base + IOP_RAM_DATA,
10616 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
10617 }
10618}
10619
10620static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10621{
10622 ushort q_addr;
10623 uchar tid_no;
10624 uchar sdtr_data;
10625 uchar syn_period_ix;
10626 uchar syn_offset;
10627 PortAddr iop_base;
10628
10629 iop_base = asc_dvc->iop_base;
10630 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
10631 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
10632 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
10633 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10634 syn_period_ix =
10635 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
10636 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
10637 AscMsgOutSDTR(asc_dvc,
10638 asc_dvc->sdtr_period_tbl[syn_period_ix],
10639 syn_offset);
10640 scsiq->q1.cntl |= QC_MSG_OUT;
10641 }
10642 q_addr = ASC_QNO_TO_QADDR(q_no);
10643 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
10644 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10645 }
10646 scsiq->q1.status = QS_FREE;
10647 AscMemWordCopyPtrToLram(iop_base,
10648 q_addr + ASC_SCSIQ_CDB_BEG,
10649 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
10650
10651 DvcPutScsiQ(iop_base,
10652 q_addr + ASC_SCSIQ_CPY_BEG,
10653 (uchar *)&scsiq->q1.cntl,
10654 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
10655 AscWriteLramWord(iop_base,
10656 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
10657 (ushort)(((ushort)scsiq->q1.
10658 q_no << 8) | (ushort)QS_READY));
10659 return 1;
10660}
10661
10662static int
10663AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
10664{
10665 int sta;
10666 int i;
10667 ASC_SG_HEAD *sg_head;
10668 ASC_SG_LIST_Q scsi_sg_q;
10669 ASC_DCNT saved_data_addr;
10670 ASC_DCNT saved_data_cnt;
10671 PortAddr iop_base;
10672 ushort sg_list_dwords;
10673 ushort sg_index;
10674 ushort sg_entry_cnt;
10675 ushort q_addr;
10676 uchar next_qp;
10677
10678 iop_base = asc_dvc->iop_base;
10679 sg_head = scsiq->sg_head;
10680 saved_data_addr = scsiq->q1.data_addr;
10681 saved_data_cnt = scsiq->q1.data_cnt;
10682 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
10683 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
10684#if CC_VERY_LONG_SG_LIST
10685 /*
10686 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
10687 * then not all SG elements will fit in the allocated queues.
10688 * The rest of the SG elements will be copied when the RISC
10689 * completes the SG elements that fit and halts.
10690 */
10691 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10692 /*
10693 * Set sg_entry_cnt to be the number of SG elements that
10694 * will fit in the allocated SG queues. It is minus 1, because
10695 * the first SG element is handled above. ASC_MAX_SG_LIST is
10696 * already inflated by 1 to account for this. For example it
10697 * may be 50 which is 1 + 7 queues * 7 SG elements.
10698 */
10699 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
10700
10701 /*
10702 * Keep track of remaining number of SG elements that will
10703 * need to be handled from a_isr.c.
10704 */
10705 scsiq->remain_sg_entry_cnt =
10706 sg_head->entry_cnt - ASC_MAX_SG_LIST;
10707 } else {
10708#endif /* CC_VERY_LONG_SG_LIST */
10709 /*
10710 * Set sg_entry_cnt to be the number of SG elements that
10711 * will fit in the allocated SG queues. It is minus 1, because
10712 * the first SG element is handled above.
10713 */
10714 sg_entry_cnt = sg_head->entry_cnt - 1;
10715#if CC_VERY_LONG_SG_LIST
10716 }
10717#endif /* CC_VERY_LONG_SG_LIST */
10718 if (sg_entry_cnt != 0) {
10719 scsiq->q1.cntl |= QC_SG_HEAD;
10720 q_addr = ASC_QNO_TO_QADDR(q_no);
10721 sg_index = 1;
10722 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
10723 scsi_sg_q.sg_head_qp = q_no;
10724 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
10725 for (i = 0; i < sg_head->queue_cnt; i++) {
10726 scsi_sg_q.seq_no = i + 1;
10727 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
10728 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
10729 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
10730 if (i == 0) {
10731 scsi_sg_q.sg_list_cnt =
10732 ASC_SG_LIST_PER_Q;
10733 scsi_sg_q.sg_cur_list_cnt =
10734 ASC_SG_LIST_PER_Q;
10735 } else {
10736 scsi_sg_q.sg_list_cnt =
10737 ASC_SG_LIST_PER_Q - 1;
10738 scsi_sg_q.sg_cur_list_cnt =
10739 ASC_SG_LIST_PER_Q - 1;
10740 }
10741 } else {
10742#if CC_VERY_LONG_SG_LIST
10743 /*
10744 * This is the last SG queue in the list of
10745 * allocated SG queues. If there are more
10746 * SG elements than will fit in the allocated
10747 * queues, then set the QCSG_SG_XFER_MORE flag.
10748 */
10749 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
10750 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
10751 } else {
10752#endif /* CC_VERY_LONG_SG_LIST */
10753 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
10754#if CC_VERY_LONG_SG_LIST
10755 }
10756#endif /* CC_VERY_LONG_SG_LIST */
10757 sg_list_dwords = sg_entry_cnt << 1;
10758 if (i == 0) {
10759 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
10760 scsi_sg_q.sg_cur_list_cnt =
10761 sg_entry_cnt;
10762 } else {
10763 scsi_sg_q.sg_list_cnt =
10764 sg_entry_cnt - 1;
10765 scsi_sg_q.sg_cur_list_cnt =
10766 sg_entry_cnt - 1;
10767 }
10768 sg_entry_cnt = 0;
10769 }
10770 next_qp = AscReadLramByte(iop_base,
10771 (ushort)(q_addr +
10772 ASC_SCSIQ_B_FWD));
10773 scsi_sg_q.q_no = next_qp;
10774 q_addr = ASC_QNO_TO_QADDR(next_qp);
10775 AscMemWordCopyPtrToLram(iop_base,
10776 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
10777 (uchar *)&scsi_sg_q,
10778 sizeof(ASC_SG_LIST_Q) >> 1);
10779 AscMemDWordCopyPtrToLram(iop_base,
10780 q_addr + ASC_SGQ_LIST_BEG,
10781 (uchar *)&sg_head->
10782 sg_list[sg_index],
10783 sg_list_dwords);
10784 sg_index += ASC_SG_LIST_PER_Q;
10785 scsiq->next_sg_index = sg_index;
10786 }
10787 } else {
10788 scsiq->q1.cntl &= ~QC_SG_HEAD;
10789 }
10790 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
10791 scsiq->q1.data_addr = saved_data_addr;
10792 scsiq->q1.data_cnt = saved_data_cnt;
10793 return (sta);
10794}
10795
10796static int
10797AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
10798{
10799 PortAddr iop_base;
10800 uchar free_q_head;
10801 uchar next_qp;
10802 uchar tid_no;
10803 uchar target_ix;
10804 int sta;
10805
10806 iop_base = asc_dvc->iop_base;
10807 target_ix = scsiq->q2.target_ix;
10808 tid_no = ASC_TIX_TO_TID(target_ix);
10809 sta = 0;
10810 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
10811 if (n_q_required > 1) {
10812 next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head,
10813 (uchar)n_q_required);
10814 if (next_qp != ASC_QLINK_END) {
10815 asc_dvc->last_q_shortage = 0;
10816 scsiq->sg_head->queue_cnt = n_q_required - 1;
10817 scsiq->q1.q_no = free_q_head;
10818 sta = AscPutReadySgListQueue(asc_dvc, scsiq,
10819 free_q_head);
10820 }
10821 } else if (n_q_required == 1) {
10822 next_qp = AscAllocFreeQueue(iop_base, free_q_head);
10823 if (next_qp != ASC_QLINK_END) {
10824 scsiq->q1.q_no = free_q_head;
10825 sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head);
10826 }
10827 }
10828 if (sta == 1) {
10829 AscPutVarFreeQHead(iop_base, next_qp);
10830 asc_dvc->cur_total_qng += n_q_required;
10831 asc_dvc->cur_dvc_qng[tid_no]++;
10832 }
10833 return sta;
10834}
10835
10836#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
10837static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
10838 INQUIRY,
10839 REQUEST_SENSE,
10840 READ_CAPACITY,
10841 READ_TOC,
10842 MODE_SELECT,
10843 MODE_SENSE,
10844 MODE_SELECT_10,
10845 MODE_SENSE_10,
10846 0xFF,
10847 0xFF,
10848 0xFF,
10849 0xFF,
10850 0xFF,
10851 0xFF,
10852 0xFF,
10853 0xFF
10854};
10855
10856static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
10857{
10858 PortAddr iop_base;
10859 int sta;
10860 int n_q_required;
10861 int disable_syn_offset_one_fix;
10862 int i;
10863 ASC_PADDR addr;
10864 ushort sg_entry_cnt = 0;
10865 ushort sg_entry_cnt_minus_one = 0;
10866 uchar target_ix;
10867 uchar tid_no;
10868 uchar sdtr_data;
10869 uchar extra_bytes;
10870 uchar scsi_cmd;
10871 uchar disable_cmd;
10872 ASC_SG_HEAD *sg_head;
10873 ASC_DCNT data_cnt;
10874
10875 iop_base = asc_dvc->iop_base;
10876 sg_head = scsiq->sg_head;
10877 if (asc_dvc->err_code != 0)
10878 return (ERR);
10879 scsiq->q1.q_no = 0;
10880 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
10881 scsiq->q1.extra_bytes = 0;
10882 }
10883 sta = 0;
10884 target_ix = scsiq->q2.target_ix;
10885 tid_no = ASC_TIX_TO_TID(target_ix);
10886 n_q_required = 1;
10887 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
10888 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
10889 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
10890 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10891 AscMsgOutSDTR(asc_dvc,
10892 asc_dvc->
10893 sdtr_period_tbl[(sdtr_data >> 4) &
10894 (uchar)(asc_dvc->
10895 max_sdtr_index -
10896 1)],
10897 (uchar)(sdtr_data & (uchar)
10898 ASC_SYN_MAX_OFFSET));
10899 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
10900 }
10901 }
10902 if (asc_dvc->in_critical_cnt != 0) {
10903 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
10904 return (ERR);
10905 }
10906 asc_dvc->in_critical_cnt++;
10907 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10908 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
10909 asc_dvc->in_critical_cnt--;
10910 return (ERR);
10911 }
10912#if !CC_VERY_LONG_SG_LIST
10913 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
10914 asc_dvc->in_critical_cnt--;
10915 return (ERR);
10916 }
10917#endif /* !CC_VERY_LONG_SG_LIST */
10918 if (sg_entry_cnt == 1) {
10919 scsiq->q1.data_addr =
10920 (ADV_PADDR)sg_head->sg_list[0].addr;
10921 scsiq->q1.data_cnt =
10922 (ADV_DCNT)sg_head->sg_list[0].bytes;
10923 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
10924 }
10925 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
10926 }
10927 scsi_cmd = scsiq->cdbptr[0];
10928 disable_syn_offset_one_fix = FALSE;
10929 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
10930 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
10931 if (scsiq->q1.cntl & QC_SG_HEAD) {
10932 data_cnt = 0;
10933 for (i = 0; i < sg_entry_cnt; i++) {
10934 data_cnt +=
10935 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
10936 bytes);
10937 }
10938 } else {
10939 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
10940 }
10941 if (data_cnt != 0UL) {
10942 if (data_cnt < 512UL) {
10943 disable_syn_offset_one_fix = TRUE;
10944 } else {
10945 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
10946 i++) {
10947 disable_cmd =
10948 _syn_offset_one_disable_cmd[i];
10949 if (disable_cmd == 0xFF) {
10950 break;
10951 }
10952 if (scsi_cmd == disable_cmd) {
10953 disable_syn_offset_one_fix =
10954 TRUE;
10955 break;
10956 }
10957 }
10958 }
10959 }
10960 }
10961 if (disable_syn_offset_one_fix) {
10962 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
10963 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
10964 ASC_TAG_FLAG_DISABLE_DISCONNECT);
10965 } else {
10966 scsiq->q2.tag_code &= 0x27;
10967 }
10968 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
10969 if (asc_dvc->bug_fix_cntl) {
10970 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
10971 if ((scsi_cmd == READ_6) ||
10972 (scsi_cmd == READ_10)) {
10973 addr =
10974 (ADV_PADDR)le32_to_cpu(sg_head->
10975 sg_list
10976 [sg_entry_cnt_minus_one].
10977 addr) +
10978 (ADV_DCNT)le32_to_cpu(sg_head->
10979 sg_list
10980 [sg_entry_cnt_minus_one].
10981 bytes);
10982 extra_bytes =
10983 (uchar)((ushort)addr & 0x0003);
10984 if ((extra_bytes != 0)
10985 &&
10986 ((scsiq->q2.
10987 tag_code &
10988 ASC_TAG_FLAG_EXTRA_BYTES)
10989 == 0)) {
10990 scsiq->q2.tag_code |=
10991 ASC_TAG_FLAG_EXTRA_BYTES;
10992 scsiq->q1.extra_bytes =
10993 extra_bytes;
10994 data_cnt =
10995 le32_to_cpu(sg_head->
10996 sg_list
10997 [sg_entry_cnt_minus_one].
10998 bytes);
10999 data_cnt -=
11000 (ASC_DCNT) extra_bytes;
11001 sg_head->
11002 sg_list
11003 [sg_entry_cnt_minus_one].
11004 bytes =
11005 cpu_to_le32(data_cnt);
11006 }
11007 }
11008 }
11009 }
11010 sg_head->entry_to_copy = sg_head->entry_cnt;
11011#if CC_VERY_LONG_SG_LIST
11012 /*
11013 * Set the sg_entry_cnt to the maximum possible. The rest of
11014 * the SG elements will be copied when the RISC completes the
11015 * SG elements that fit and halts.
11016 */
11017 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
11018 sg_entry_cnt = ASC_MAX_SG_LIST;
11019 }
11020#endif /* CC_VERY_LONG_SG_LIST */
11021 n_q_required = AscSgListToQueue(sg_entry_cnt);
11022 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
11023 (uint) n_q_required)
11024 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11025 if ((sta =
11026 AscSendScsiQueue(asc_dvc, scsiq,
11027 n_q_required)) == 1) {
11028 asc_dvc->in_critical_cnt--;
11029 return (sta);
11030 }
11031 }
11032 } else {
11033 if (asc_dvc->bug_fix_cntl) {
11034 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11035 if ((scsi_cmd == READ_6) ||
11036 (scsi_cmd == READ_10)) {
11037 addr =
11038 le32_to_cpu(scsiq->q1.data_addr) +
11039 le32_to_cpu(scsiq->q1.data_cnt);
11040 extra_bytes =
11041 (uchar)((ushort)addr & 0x0003);
11042 if ((extra_bytes != 0)
11043 &&
11044 ((scsiq->q2.
11045 tag_code &
11046 ASC_TAG_FLAG_EXTRA_BYTES)
11047 == 0)) {
11048 data_cnt =
11049 le32_to_cpu(scsiq->q1.
11050 data_cnt);
11051 if (((ushort)data_cnt & 0x01FF)
11052 == 0) {
11053 scsiq->q2.tag_code |=
11054 ASC_TAG_FLAG_EXTRA_BYTES;
11055 data_cnt -= (ASC_DCNT)
11056 extra_bytes;
11057 scsiq->q1.data_cnt =
11058 cpu_to_le32
11059 (data_cnt);
11060 scsiq->q1.extra_bytes =
11061 extra_bytes;
11062 }
11063 }
11064 }
11065 }
11066 }
11067 n_q_required = 1;
11068 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
11069 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11070 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11071 n_q_required)) == 1) {
11072 asc_dvc->in_critical_cnt--;
11073 return (sta);
11074 }
11075 }
11076 }
11077 asc_dvc->in_critical_cnt--;
11078 return (sta);
11079}
11080
11081/*
11082 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
11083 *
11084 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
11085 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
11086 * RISC to notify it a new command is ready to be executed.
11087 *
11088 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
11089 * set to SCSI_MAX_RETRY.
11090 *
11091 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
11092 * for DMA addresses or math operations are byte swapped to little-endian
11093 * order.
11094 *
11095 * Return:
11096 * ADV_SUCCESS(1) - The request was successfully queued.
11097 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
11098 * request completes.
11099 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
11100 * host IC error.
11101 */
11102static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
11103{
11104 AdvPortAddr iop_base;
11105 ADV_DCNT req_size;
11106 ADV_PADDR req_paddr;
11107 ADV_CARR_T *new_carrp;
11108
11109 /*
11110 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
11111 */
11112 if (scsiq->target_id > ADV_MAX_TID) {
11113 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
11114 scsiq->done_status = QD_WITH_ERROR;
11115 return ADV_ERROR;
11116 }
11117
11118 iop_base = asc_dvc->iop_base;
11119
11120 /*
11121 * Allocate a carrier ensuring at least one carrier always
11122 * remains on the freelist and initialize fields.
11123 */
11124 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
11125 return ADV_BUSY;
11126 }
11127 asc_dvc->carr_freelist = (ADV_CARR_T *)
11128 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
11129 asc_dvc->carr_pending_cnt++;
11130
11131 /*
11132 * Set the carrier to be a stopper by setting 'next_vpa'
11133 * to the stopper value. The current stopper will be changed
11134 * below to point to the new stopper.
11135 */
11136 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
11137
11138 /*
11139 * Clear the ADV_SCSI_REQ_Q done flag.
11140 */
11141 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
11142
11143 req_size = sizeof(ADV_SCSI_REQ_Q);
11144 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
11145 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
11146
11147 BUG_ON(req_paddr & 31);
11148 BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q));
11149
11150 /* Wait for assertion before making little-endian */
11151 req_paddr = cpu_to_le32(req_paddr);
11152
11153 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
11154 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
11155 scsiq->scsiq_rptr = req_paddr;
11156
11157 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
11158 /*
11159 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
11160 * order during initialization.
11161 */
11162 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
11163
11164 /*
11165 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
11166 * the microcode. The newly allocated stopper will become the new
11167 * stopper.
11168 */
11169 asc_dvc->icq_sp->areq_vpa = req_paddr;
11170
11171 /*
11172 * Set the 'next_vpa' pointer for the old stopper to be the
11173 * physical address of the new stopper. The RISC can only
11174 * follow physical addresses.
11175 */
11176 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
11177
11178 /*
11179 * Set the host adapter stopper pointer to point to the new carrier.
11180 */
11181 asc_dvc->icq_sp = new_carrp;
11182
11183 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
11184 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
11185 /*
11186 * Tickle the RISC to tell it to read its Command Queue Head pointer.
11187 */
11188 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
11189 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
11190 /*
11191 * Clear the tickle value. In the ASC-3550 the RISC flag
11192 * command 'clr_tickle_a' does not work unless the host
11193 * value is cleared.
11194 */
11195 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
11196 ADV_TICKLE_NOP);
11197 }
11198 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
11199 /*
11200 * Notify the RISC a carrier is ready by writing the physical
11201 * address of the new carrier stopper to the COMMA register.
11202 */
11203 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
11204 le32_to_cpu(new_carrp->carr_pa));
11205 }
11206
11207 return ADV_SUCCESS;
11208}
11209
11210/*
11211 * Execute a single 'Scsi_Cmnd'.
11212 *
11213 * The function 'done' is called when the request has been completed.
11214 *
11215 * Scsi_Cmnd:
11216 *
11217 * host - board controlling device
11218 * device - device to send command
11219 * target - target of device
11220 * lun - lun of device
11221 * cmd_len - length of SCSI CDB
11222 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
11223 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
11224 *
11225 * if (use_sg == 0) {
11226 * request_buffer - buffer address for request
11227 * request_bufflen - length of request buffer
11228 * } else {
11229 * request_buffer - pointer to scatterlist structure
11230 * }
11231 *
11232 * sense_buffer - sense command buffer
11233 *
11234 * result (4 bytes of an int):
11235 * Byte Meaning
11236 * 0 SCSI Status Byte Code
11237 * 1 SCSI One Byte Message Code
11238 * 2 Host Error Code
11239 * 3 Mid-Level Error Code
11240 *
11241 * host driver fields:
11242 * SCp - Scsi_Pointer used for command processing status
11243 * scsi_done - used to save caller's done function
11244 * host_scribble - used for pointer to another struct scsi_cmnd
11245 *
11246 * If this function returns ASC_NOERROR the request will be completed
11247 * from the interrupt handler.
11248 *
11249 * If this function returns ASC_ERROR the host error code has been set,
11250 * and the called must call asc_scsi_done.
11251 *
11252 * If ASC_BUSY is returned the request will be returned to the midlayer
11253 * and re-tried later.
11254 */
11255static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
11256{
Matthew Wilcox41d24932007-10-02 21:55:24 -040011257 int ret, err_code;
11258 asc_board_t *boardp = ASC_BOARDP(scp->device->host);
Matthew Wilcox51219352007-10-02 21:55:22 -040011259
Matthew Wilcox41d24932007-10-02 21:55:24 -040011260 ASC_DBG1(1, "asc_execute_scsi_cmnd: scp 0x%p\n", scp);
Matthew Wilcox51219352007-10-02 21:55:22 -040011261
11262 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011263 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox05848b62007-10-02 21:55:25 -040011264 struct asc_scsi_q asc_scsi_q;
Matthew Wilcox51219352007-10-02 21:55:22 -040011265
Matthew Wilcox41d24932007-10-02 21:55:24 -040011266 /* asc_build_req() can not return ASC_BUSY. */
Matthew Wilcox05848b62007-10-02 21:55:25 -040011267 ret = asc_build_req(boardp, scp, &asc_scsi_q);
11268 if (ret == ASC_ERROR) {
Matthew Wilcox51219352007-10-02 21:55:22 -040011269 ASC_STATS(scp->device->host, build_error);
11270 return ASC_ERROR;
11271 }
11272
Matthew Wilcox41d24932007-10-02 21:55:24 -040011273 ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
Matthew Wilcox05848b62007-10-02 21:55:25 -040011274 kfree(asc_scsi_q.sg_head);
Matthew Wilcox41d24932007-10-02 21:55:24 -040011275 err_code = asc_dvc->err_code;
Matthew Wilcox51219352007-10-02 21:55:22 -040011276 } else {
Matthew Wilcox41d24932007-10-02 21:55:24 -040011277 ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
11278 ADV_SCSI_REQ_Q *adv_scsiqp;
Matthew Wilcox51219352007-10-02 21:55:22 -040011279
Matthew Wilcox51219352007-10-02 21:55:22 -040011280 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
11281 case ASC_NOERROR:
11282 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
11283 "ASC_NOERROR\n");
11284 break;
11285 case ASC_BUSY:
11286 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
11287 "ASC_BUSY\n");
11288 /*
11289 * The asc_stats fields 'adv_build_noreq' and
11290 * 'adv_build_nosg' count wide board busy conditions.
11291 * They are updated in adv_build_req and
11292 * adv_get_sglist, respectively.
11293 */
11294 return ASC_BUSY;
11295 case ASC_ERROR:
11296 default:
11297 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
11298 "ASC_ERROR\n");
11299 ASC_STATS(scp->device->host, build_error);
11300 return ASC_ERROR;
11301 }
11302
Matthew Wilcox41d24932007-10-02 21:55:24 -040011303 ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp);
11304 err_code = adv_dvc->err_code;
11305 }
11306
11307 switch (ret) {
11308 case ASC_NOERROR:
11309 ASC_STATS(scp->device->host, exe_noerror);
11310 /*
11311 * Increment monotonically increasing per device
11312 * successful request counter. Wrapping doesn't matter.
11313 */
11314 boardp->reqcnt[scp->device->id]++;
11315 ASC_DBG(1, "asc_execute_scsi_cmnd: ExeScsiQueue(), "
11316 "ASC_NOERROR\n");
11317 break;
11318 case ASC_BUSY:
11319 ASC_STATS(scp->device->host, exe_busy);
11320 break;
11321 case ASC_ERROR:
11322 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11323 "ASC_ERROR, err_code 0x%x\n", boardp->id, err_code);
11324 ASC_STATS(scp->device->host, exe_error);
11325 scp->result = HOST_BYTE(DID_ERROR);
11326 break;
11327 default:
11328 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: ExeScsiQueue() "
11329 "unknown, err_code 0x%x\n", boardp->id, err_code);
11330 ASC_STATS(scp->device->host, exe_unknown);
11331 scp->result = HOST_BYTE(DID_ERROR);
11332 break;
Matthew Wilcox51219352007-10-02 21:55:22 -040011333 }
11334
11335 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
11336 return ret;
11337}
11338
11339/*
11340 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
11341 *
11342 * This function always returns 0. Command return status is saved
11343 * in the 'scp' result field.
11344 */
11345static int
11346advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
11347{
11348 struct Scsi_Host *shost = scp->device->host;
11349 asc_board_t *boardp = ASC_BOARDP(shost);
11350 unsigned long flags;
11351 int asc_res, result = 0;
11352
11353 ASC_STATS(shost, queuecommand);
11354 scp->scsi_done = done;
11355
11356 /*
11357 * host_lock taken by mid-level prior to call, but need
11358 * to protect against own ISR
11359 */
11360 spin_lock_irqsave(&boardp->lock, flags);
11361 asc_res = asc_execute_scsi_cmnd(scp);
11362 spin_unlock_irqrestore(&boardp->lock, flags);
11363
11364 switch (asc_res) {
11365 case ASC_NOERROR:
11366 break;
11367 case ASC_BUSY:
11368 result = SCSI_MLQUEUE_HOST_BUSY;
11369 break;
11370 case ASC_ERROR:
11371 default:
11372 asc_scsi_done(scp);
11373 break;
11374 }
11375
11376 return result;
11377}
11378
11379static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
11380{
11381 PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11382 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
11383 return inpw(eisa_cfg_iop);
11384}
11385
11386/*
11387 * Return the BIOS address of the adapter at the specified
11388 * I/O port and with the specified bus type.
11389 */
11390static unsigned short __devinit
11391AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
11392{
11393 unsigned short cfg_lsw;
11394 unsigned short bios_addr;
11395
11396 /*
11397 * The PCI BIOS is re-located by the motherboard BIOS. Because
11398 * of this the driver can not determine where a PCI BIOS is
11399 * loaded and executes.
11400 */
11401 if (bus_type & ASC_IS_PCI)
11402 return 0;
11403
11404 if ((bus_type & ASC_IS_EISA) != 0) {
11405 cfg_lsw = AscGetEisaChipCfg(iop_base);
11406 cfg_lsw &= 0x000F;
11407 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
11408 return bios_addr;
11409 }
11410
11411 cfg_lsw = AscGetChipCfgLsw(iop_base);
11412
11413 /*
11414 * ISA PnP uses the top bit as the 32K BIOS flag
11415 */
11416 if (bus_type == ASC_IS_ISAPNP)
11417 cfg_lsw &= 0x7FFF;
11418 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
11419 return bios_addr;
11420}
11421
11422static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
11423{
11424 ushort cfg_lsw;
11425
11426 if (AscGetChipScsiID(iop_base) == new_host_id) {
11427 return (new_host_id);
11428 }
11429 cfg_lsw = AscGetChipCfgLsw(iop_base);
11430 cfg_lsw &= 0xF8FF;
11431 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
11432 AscSetChipCfgLsw(iop_base, cfg_lsw);
11433 return (AscGetChipScsiID(iop_base));
11434}
11435
11436static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
11437{
11438 unsigned char sc;
11439
11440 AscSetBank(iop_base, 1);
11441 sc = inp(iop_base + IOP_REG_SC);
11442 AscSetBank(iop_base, 0);
11443 return sc;
11444}
11445
11446static unsigned char __devinit
11447AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
11448{
11449 if (bus_type & ASC_IS_EISA) {
11450 PortAddr eisa_iop;
11451 unsigned char revision;
11452 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
11453 (PortAddr) ASC_EISA_REV_IOP_MASK;
11454 revision = inp(eisa_iop);
11455 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
11456 }
11457 return AscGetChipVerNo(iop_base);
11458}
11459
Matthew Wilcox51219352007-10-02 21:55:22 -040011460#ifdef CONFIG_ISA
11461static void __devinit AscEnableIsaDma(uchar dma_channel)
11462{
11463 if (dma_channel < 4) {
11464 outp(0x000B, (ushort)(0xC0 | dma_channel));
11465 outp(0x000A, dma_channel);
11466 } else if (dma_channel < 8) {
11467 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
11468 outp(0x00D4, (ushort)(dma_channel - 4));
11469 }
11470 return;
11471}
11472#endif /* CONFIG_ISA */
11473
11474static int AscStopQueueExe(PortAddr iop_base)
11475{
11476 int count = 0;
11477
11478 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
11479 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
11480 ASC_STOP_REQ_RISC_STOP);
11481 do {
11482 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
11483 ASC_STOP_ACK_RISC_STOP) {
11484 return (1);
11485 }
11486 mdelay(100);
11487 } while (count++ < 20);
11488 }
11489 return (0);
11490}
11491
11492static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
11493{
11494 if (bus_type & ASC_IS_ISA)
11495 return ASC_MAX_ISA_DMA_COUNT;
11496 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
11497 return ASC_MAX_VL_DMA_COUNT;
11498 return ASC_MAX_PCI_DMA_COUNT;
11499}
11500
11501#ifdef CONFIG_ISA
11502static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
11503{
11504 ushort channel;
11505
11506 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
11507 if (channel == 0x03)
11508 return (0);
11509 else if (channel == 0x00)
11510 return (7);
11511 return (channel + 4);
11512}
11513
11514static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
11515{
11516 ushort cfg_lsw;
11517 uchar value;
11518
11519 if ((dma_channel >= 5) && (dma_channel <= 7)) {
11520 if (dma_channel == 7)
11521 value = 0x00;
11522 else
11523 value = dma_channel - 4;
11524 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
11525 cfg_lsw |= value;
11526 AscSetChipCfgLsw(iop_base, cfg_lsw);
11527 return (AscGetIsaDmaChannel(iop_base));
11528 }
11529 return 0;
11530}
11531
11532static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
11533{
11534 uchar speed_value;
11535
11536 AscSetBank(iop_base, 1);
11537 speed_value = AscReadChipDmaSpeed(iop_base);
11538 speed_value &= 0x07;
11539 AscSetBank(iop_base, 0);
11540 return speed_value;
11541}
11542
11543static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
11544{
11545 speed_value &= 0x07;
11546 AscSetBank(iop_base, 1);
11547 AscWriteChipDmaSpeed(iop_base, speed_value);
11548 AscSetBank(iop_base, 0);
11549 return AscGetIsaDmaSpeed(iop_base);
11550}
11551#endif /* CONFIG_ISA */
11552
11553static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
11554{
11555 int i;
11556 PortAddr iop_base;
11557 ushort warn_code;
11558 uchar chip_version;
11559
11560 iop_base = asc_dvc->iop_base;
11561 warn_code = 0;
11562 asc_dvc->err_code = 0;
11563 if ((asc_dvc->bus_type &
11564 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
11565 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
11566 }
11567 AscSetChipControl(iop_base, CC_HALT);
11568 AscSetChipStatus(iop_base, 0);
11569 asc_dvc->bug_fix_cntl = 0;
11570 asc_dvc->pci_fix_asyn_xfer = 0;
11571 asc_dvc->pci_fix_asyn_xfer_always = 0;
11572 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
11573 asc_dvc->sdtr_done = 0;
11574 asc_dvc->cur_total_qng = 0;
11575 asc_dvc->is_in_int = 0;
11576 asc_dvc->in_critical_cnt = 0;
11577 asc_dvc->last_q_shortage = 0;
11578 asc_dvc->use_tagged_qng = 0;
11579 asc_dvc->no_scam = 0;
11580 asc_dvc->unit_not_ready = 0;
11581 asc_dvc->queue_full_or_busy = 0;
11582 asc_dvc->redo_scam = 0;
11583 asc_dvc->res2 = 0;
11584 asc_dvc->host_init_sdtr_index = 0;
11585 asc_dvc->cfg->can_tagged_qng = 0;
11586 asc_dvc->cfg->cmd_qng_enabled = 0;
11587 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
11588 asc_dvc->init_sdtr = 0;
11589 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
11590 asc_dvc->scsi_reset_wait = 3;
11591 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
11592 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
11593 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
11594 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
11595 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
11596 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
11597 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
11598 ASC_LIB_VERSION_MINOR;
11599 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
11600 asc_dvc->cfg->chip_version = chip_version;
11601 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
11602 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
11603 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
11604 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
11605 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
11606 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
11607 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
11608 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
11609 asc_dvc->max_sdtr_index = 7;
11610 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
11611 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
11612 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
11613 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
11614 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
11615 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
11616 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
11617 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
11618 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
11619 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
11620 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
11621 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
11622 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
11623 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
11624 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
11625 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
11626 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
11627 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
11628 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
11629 asc_dvc->max_sdtr_index = 15;
11630 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
11631 AscSetExtraControl(iop_base,
11632 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11633 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
11634 AscSetExtraControl(iop_base,
11635 (SEC_ACTIVE_NEGATE |
11636 SEC_ENABLE_FILTER));
11637 }
11638 }
11639 if (asc_dvc->bus_type == ASC_IS_PCI) {
11640 AscSetExtraControl(iop_base,
11641 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
11642 }
11643
11644 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
11645#ifdef CONFIG_ISA
11646 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
11647 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
11648 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
11649 asc_dvc->bus_type = ASC_IS_ISAPNP;
11650 }
11651 asc_dvc->cfg->isa_dma_channel =
11652 (uchar)AscGetIsaDmaChannel(iop_base);
11653 }
11654#endif /* CONFIG_ISA */
11655 for (i = 0; i <= ASC_MAX_TID; i++) {
11656 asc_dvc->cur_dvc_qng[i] = 0;
11657 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
11658 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
11659 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
11660 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
11661 }
11662 return warn_code;
11663}
11664
11665static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
11666{
11667 int retry;
11668
11669 for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) {
11670 unsigned char read_back;
11671 AscSetChipEEPCmd(iop_base, cmd_reg);
11672 mdelay(1);
11673 read_back = AscGetChipEEPCmd(iop_base);
11674 if (read_back == cmd_reg)
11675 return 1;
11676 }
11677 return 0;
11678}
11679
11680static void __devinit AscWaitEEPRead(void)
11681{
11682 mdelay(1);
11683}
11684
11685static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
11686{
11687 ushort read_wval;
11688 uchar cmd_reg;
11689
11690 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11691 AscWaitEEPRead();
11692 cmd_reg = addr | ASC_EEP_CMD_READ;
11693 AscWriteEEPCmdReg(iop_base, cmd_reg);
11694 AscWaitEEPRead();
11695 read_wval = AscGetChipEEPData(iop_base);
11696 AscWaitEEPRead();
11697 return read_wval;
11698}
11699
11700static ushort __devinit
11701AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11702{
11703 ushort wval;
11704 ushort sum;
11705 ushort *wbuf;
11706 int cfg_beg;
11707 int cfg_end;
11708 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11709 int s_addr;
11710
11711 wbuf = (ushort *)cfg_buf;
11712 sum = 0;
11713 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
11714 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11715 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11716 sum += *wbuf;
11717 }
11718 if (bus_type & ASC_IS_VL) {
11719 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11720 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11721 } else {
11722 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11723 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11724 }
11725 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11726 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
11727 if (s_addr <= uchar_end_in_config) {
11728 /*
11729 * Swap all char fields - must unswap bytes already swapped
11730 * by AscReadEEPWord().
11731 */
11732 *wbuf = le16_to_cpu(wval);
11733 } else {
11734 /* Don't swap word field at the end - cntl field. */
11735 *wbuf = wval;
11736 }
11737 sum += wval; /* Checksum treats all EEPROM data as words. */
11738 }
11739 /*
11740 * Read the checksum word which will be compared against 'sum'
11741 * by the caller. Word field already swapped.
11742 */
11743 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
11744 return sum;
11745}
11746
11747static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
11748{
11749 PortAddr iop_base;
11750 ushort q_addr;
11751 ushort saved_word;
11752 int sta;
11753
11754 iop_base = asc_dvc->iop_base;
11755 sta = 0;
11756 q_addr = ASC_QNO_TO_QADDR(241);
11757 saved_word = AscReadLramWord(iop_base, q_addr);
11758 AscSetChipLramAddr(iop_base, q_addr);
11759 AscSetChipLramData(iop_base, 0x55AA);
11760 mdelay(10);
11761 AscSetChipLramAddr(iop_base, q_addr);
11762 if (AscGetChipLramData(iop_base) == 0x55AA) {
11763 sta = 1;
11764 AscWriteLramWord(iop_base, q_addr, saved_word);
11765 }
11766 return (sta);
11767}
11768
11769static void __devinit AscWaitEEPWrite(void)
11770{
11771 mdelay(20);
11772 return;
11773}
11774
11775static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
11776{
11777 ushort read_back;
11778 int retry;
11779
11780 retry = 0;
11781 while (TRUE) {
11782 AscSetChipEEPData(iop_base, data_reg);
11783 mdelay(1);
11784 read_back = AscGetChipEEPData(iop_base);
11785 if (read_back == data_reg) {
11786 return (1);
11787 }
11788 if (retry++ > ASC_EEP_MAX_RETRY) {
11789 return (0);
11790 }
11791 }
11792}
11793
11794static ushort __devinit
11795AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
11796{
11797 ushort read_wval;
11798
11799 read_wval = AscReadEEPWord(iop_base, addr);
11800 if (read_wval != word_val) {
11801 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
11802 AscWaitEEPRead();
11803 AscWriteEEPDataReg(iop_base, word_val);
11804 AscWaitEEPRead();
11805 AscWriteEEPCmdReg(iop_base,
11806 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
11807 AscWaitEEPWrite();
11808 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
11809 AscWaitEEPRead();
11810 return (AscReadEEPWord(iop_base, addr));
11811 }
11812 return (read_wval);
11813}
11814
11815static int __devinit
11816AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11817{
11818 int n_error;
11819 ushort *wbuf;
11820 ushort word;
11821 ushort sum;
11822 int s_addr;
11823 int cfg_beg;
11824 int cfg_end;
11825 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
11826
11827 wbuf = (ushort *)cfg_buf;
11828 n_error = 0;
11829 sum = 0;
11830 /* Write two config words; AscWriteEEPWord() will swap bytes. */
11831 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11832 sum += *wbuf;
11833 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11834 n_error++;
11835 }
11836 }
11837 if (bus_type & ASC_IS_VL) {
11838 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11839 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11840 } else {
11841 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11842 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11843 }
11844 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11845 if (s_addr <= uchar_end_in_config) {
11846 /*
11847 * This is a char field. Swap char fields before they are
11848 * swapped again by AscWriteEEPWord().
11849 */
11850 word = cpu_to_le16(*wbuf);
11851 if (word !=
11852 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
11853 n_error++;
11854 }
11855 } else {
11856 /* Don't swap word field at the end - cntl field. */
11857 if (*wbuf !=
11858 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
11859 n_error++;
11860 }
11861 }
11862 sum += *wbuf; /* Checksum calculated from word values. */
11863 }
11864 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
11865 *wbuf = sum;
11866 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
11867 n_error++;
11868 }
11869
11870 /* Read EEPROM back again. */
11871 wbuf = (ushort *)cfg_buf;
11872 /*
11873 * Read two config words; Byte-swapping done by AscReadEEPWord().
11874 */
11875 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
11876 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
11877 n_error++;
11878 }
11879 }
11880 if (bus_type & ASC_IS_VL) {
11881 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
11882 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
11883 } else {
11884 cfg_beg = ASC_EEP_DVC_CFG_BEG;
11885 cfg_end = ASC_EEP_MAX_DVC_ADDR;
11886 }
11887 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
11888 if (s_addr <= uchar_end_in_config) {
11889 /*
11890 * Swap all char fields. Must unswap bytes already swapped
11891 * by AscReadEEPWord().
11892 */
11893 word =
11894 le16_to_cpu(AscReadEEPWord
11895 (iop_base, (uchar)s_addr));
11896 } else {
11897 /* Don't swap word field at the end - cntl field. */
11898 word = AscReadEEPWord(iop_base, (uchar)s_addr);
11899 }
11900 if (*wbuf != word) {
11901 n_error++;
11902 }
11903 }
11904 /* Read checksum; Byte swapping not needed. */
11905 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
11906 n_error++;
11907 }
11908 return n_error;
11909}
11910
11911static int __devinit
11912AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
11913{
11914 int retry;
11915 int n_error;
11916
11917 retry = 0;
11918 while (TRUE) {
11919 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
11920 bus_type)) == 0) {
11921 break;
11922 }
11923 if (++retry > ASC_EEP_MAX_RETRY) {
11924 break;
11925 }
11926 }
11927 return n_error;
11928}
11929
11930static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
11931{
11932 ASCEEP_CONFIG eep_config_buf;
11933 ASCEEP_CONFIG *eep_config;
11934 PortAddr iop_base;
11935 ushort chksum;
11936 ushort warn_code;
11937 ushort cfg_msw, cfg_lsw;
11938 int i;
11939 int write_eep = 0;
11940
11941 iop_base = asc_dvc->iop_base;
11942 warn_code = 0;
11943 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
11944 AscStopQueueExe(iop_base);
11945 if ((AscStopChip(iop_base) == FALSE) ||
11946 (AscGetChipScsiCtrl(iop_base) != 0)) {
11947 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
11948 AscResetChipAndScsiBus(asc_dvc);
11949 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
11950 }
11951 if (AscIsChipHalted(iop_base) == FALSE) {
11952 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
11953 return (warn_code);
11954 }
11955 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11956 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11957 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
11958 return (warn_code);
11959 }
11960 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
11961 cfg_msw = AscGetChipCfgMsw(iop_base);
11962 cfg_lsw = AscGetChipCfgLsw(iop_base);
11963 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
11964 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11965 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
11966 AscSetChipCfgMsw(iop_base, cfg_msw);
11967 }
11968 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
11969 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
11970 if (chksum == 0) {
11971 chksum = 0xaa55;
11972 }
11973 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
11974 warn_code |= ASC_WARN_AUTO_CONFIG;
11975 if (asc_dvc->cfg->chip_version == 3) {
11976 if (eep_config->cfg_lsw != cfg_lsw) {
11977 warn_code |= ASC_WARN_EEPROM_RECOVER;
11978 eep_config->cfg_lsw =
11979 AscGetChipCfgLsw(iop_base);
11980 }
11981 if (eep_config->cfg_msw != cfg_msw) {
11982 warn_code |= ASC_WARN_EEPROM_RECOVER;
11983 eep_config->cfg_msw =
11984 AscGetChipCfgMsw(iop_base);
11985 }
11986 }
11987 }
11988 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
11989 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
11990 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
11991 eep_config->chksum);
11992 if (chksum != eep_config->chksum) {
11993 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
11994 ASC_CHIP_VER_PCI_ULTRA_3050) {
11995 ASC_DBG(1,
11996 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
11997 eep_config->init_sdtr = 0xFF;
11998 eep_config->disc_enable = 0xFF;
11999 eep_config->start_motor = 0xFF;
12000 eep_config->use_cmd_qng = 0;
12001 eep_config->max_total_qng = 0xF0;
12002 eep_config->max_tag_qng = 0x20;
12003 eep_config->cntl = 0xBFFF;
12004 ASC_EEP_SET_CHIP_ID(eep_config, 7);
12005 eep_config->no_scam = 0;
12006 eep_config->adapter_info[0] = 0;
12007 eep_config->adapter_info[1] = 0;
12008 eep_config->adapter_info[2] = 0;
12009 eep_config->adapter_info[3] = 0;
12010 eep_config->adapter_info[4] = 0;
12011 /* Indicate EEPROM-less board. */
12012 eep_config->adapter_info[5] = 0xBB;
12013 } else {
12014 ASC_PRINT
12015 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
12016 write_eep = 1;
12017 warn_code |= ASC_WARN_EEPROM_CHKSUM;
12018 }
12019 }
12020 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
12021 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
12022 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
12023 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
12024 asc_dvc->start_motor = eep_config->start_motor;
12025 asc_dvc->dvc_cntl = eep_config->cntl;
12026 asc_dvc->no_scam = eep_config->no_scam;
12027 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
12028 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
12029 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
12030 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
12031 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
12032 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
12033 if (!AscTestExternalLram(asc_dvc)) {
12034 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
12035 ASC_IS_PCI_ULTRA)) {
12036 eep_config->max_total_qng =
12037 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
12038 eep_config->max_tag_qng =
12039 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
12040 } else {
12041 eep_config->cfg_msw |= 0x0800;
12042 cfg_msw |= 0x0800;
12043 AscSetChipCfgMsw(iop_base, cfg_msw);
12044 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
12045 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
12046 }
12047 } else {
12048 }
12049 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
12050 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
12051 }
12052 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
12053 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
12054 }
12055 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
12056 eep_config->max_tag_qng = eep_config->max_total_qng;
12057 }
12058 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
12059 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
12060 }
12061 asc_dvc->max_total_qng = eep_config->max_total_qng;
12062 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
12063 eep_config->use_cmd_qng) {
12064 eep_config->disc_enable = eep_config->use_cmd_qng;
12065 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12066 }
Matthew Wilcox51219352007-10-02 21:55:22 -040012067 ASC_EEP_SET_CHIP_ID(eep_config,
12068 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
12069 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
12070 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
12071 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
12072 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
12073 }
12074
12075 for (i = 0; i <= ASC_MAX_TID; i++) {
12076 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
12077 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
12078 asc_dvc->cfg->sdtr_period_offset[i] =
12079 (uchar)(ASC_DEF_SDTR_OFFSET |
12080 (asc_dvc->host_init_sdtr_index << 4));
12081 }
12082 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
12083 if (write_eep) {
12084 if ((i = AscSetEEPConfig(iop_base, eep_config,
12085 asc_dvc->bus_type)) != 0) {
12086 ASC_PRINT1
12087 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
12088 i);
12089 } else {
12090 ASC_PRINT
12091 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
12092 }
12093 }
12094 return (warn_code);
12095}
12096
12097static int __devinit AscInitGetConfig(asc_board_t *boardp)
12098{
12099 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
12100 unsigned short warn_code = 0;
12101
12102 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
12103 if (asc_dvc->err_code != 0)
12104 return asc_dvc->err_code;
12105
12106 if (AscFindSignature(asc_dvc->iop_base)) {
12107 warn_code |= AscInitAscDvcVar(asc_dvc);
12108 warn_code |= AscInitFromEEP(asc_dvc);
12109 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
12110 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
12111 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
12112 } else {
12113 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12114 }
12115
12116 switch (warn_code) {
12117 case 0: /* No error */
12118 break;
12119 case ASC_WARN_IO_PORT_ROTATE:
12120 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
12121 "modified\n", boardp->id);
12122 break;
12123 case ASC_WARN_AUTO_CONFIG:
12124 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
12125 "switch enabled\n", boardp->id);
12126 break;
12127 case ASC_WARN_EEPROM_CHKSUM:
12128 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
12129 "error\n", boardp->id);
12130 break;
12131 case ASC_WARN_IRQ_MODIFIED:
12132 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
12133 boardp->id);
12134 break;
12135 case ASC_WARN_CMD_QNG_CONFLICT:
12136 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
12137 "w/o disconnects\n", boardp->id);
12138 break;
12139 default:
12140 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
12141 "0x%x\n", boardp->id, warn_code);
12142 break;
12143 }
12144
12145 if (asc_dvc->err_code != 0) {
12146 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
12147 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12148 asc_dvc->err_code);
12149 }
12150
12151 return asc_dvc->err_code;
12152}
12153
12154static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
12155{
12156 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
12157 PortAddr iop_base = asc_dvc->iop_base;
12158 unsigned short cfg_msw;
12159 unsigned short warn_code = 0;
12160
12161 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12162 if (asc_dvc->err_code != 0)
12163 return asc_dvc->err_code;
12164 if (!AscFindSignature(asc_dvc->iop_base)) {
12165 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12166 return asc_dvc->err_code;
12167 }
12168
12169 cfg_msw = AscGetChipCfgMsw(iop_base);
12170 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12171 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
12172 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12173 AscSetChipCfgMsw(iop_base, cfg_msw);
12174 }
12175 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12176 asc_dvc->cfg->cmd_qng_enabled) {
12177 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12178 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12179 }
12180 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12181 warn_code |= ASC_WARN_AUTO_CONFIG;
12182 }
Matthew Wilcox51219352007-10-02 21:55:22 -040012183#ifdef CONFIG_PCI
12184 if (asc_dvc->bus_type & ASC_IS_PCI) {
12185 cfg_msw &= 0xFFC0;
12186 AscSetChipCfgMsw(iop_base, cfg_msw);
12187 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12188 } else {
12189 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
12190 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
12191 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12192 asc_dvc->bug_fix_cntl |=
12193 ASC_BUG_FIX_ASYN_USE_SYN;
12194 }
12195 }
12196 } else
12197#endif /* CONFIG_PCI */
12198 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12199 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12200 == ASC_CHIP_VER_ASYN_BUG) {
12201 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12202 }
12203 }
12204 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12205 asc_dvc->cfg->chip_scsi_id) {
12206 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12207 }
12208#ifdef CONFIG_ISA
12209 if (asc_dvc->bus_type & ASC_IS_ISA) {
12210 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12211 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12212 }
12213#endif /* CONFIG_ISA */
12214
12215 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12216
12217 switch (warn_code) {
12218 case 0: /* No error. */
12219 break;
12220 case ASC_WARN_IO_PORT_ROTATE:
12221 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
12222 "modified\n", boardp->id);
12223 break;
12224 case ASC_WARN_AUTO_CONFIG:
12225 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
12226 "switch enabled\n", boardp->id);
12227 break;
12228 case ASC_WARN_EEPROM_CHKSUM:
12229 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
12230 "error\n", boardp->id);
12231 break;
12232 case ASC_WARN_IRQ_MODIFIED:
12233 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
12234 boardp->id);
12235 break;
12236 case ASC_WARN_CMD_QNG_CONFLICT:
12237 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
12238 "disconnects\n",
12239 boardp->id);
12240 break;
12241 default:
12242 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
12243 "0x%x\n", boardp->id, warn_code);
12244 break;
12245 }
12246
12247 if (asc_dvc->err_code != 0) {
12248 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
12249 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
12250 asc_dvc->err_code);
12251 }
12252
12253 return asc_dvc->err_code;
12254}
12255
12256/*
12257 * EEPROM Configuration.
12258 *
12259 * All drivers should use this structure to set the default EEPROM
12260 * configuration. The BIOS now uses this structure when it is built.
12261 * Additional structure information can be found in a_condor.h where
12262 * the structure is defined.
12263 *
12264 * The *_Field_IsChar structs are needed to correct for endianness.
12265 * These values are read from the board 16 bits at a time directly
12266 * into the structs. Because some fields are char, the values will be
12267 * in the wrong order. The *_Field_IsChar tells when to flip the
12268 * bytes. Data read and written to PCI memory is automatically swapped
12269 * on big-endian platforms so char fields read as words are actually being
12270 * unswapped on big-endian platforms.
12271 */
12272static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
12273 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
12274 0x0000, /* cfg_msw */
12275 0xFFFF, /* disc_enable */
12276 0xFFFF, /* wdtr_able */
12277 0xFFFF, /* sdtr_able */
12278 0xFFFF, /* start_motor */
12279 0xFFFF, /* tagqng_able */
12280 0xFFFF, /* bios_scan */
12281 0, /* scam_tolerant */
12282 7, /* adapter_scsi_id */
12283 0, /* bios_boot_delay */
12284 3, /* scsi_reset_delay */
12285 0, /* bios_id_lun */
12286 0, /* termination */
12287 0, /* reserved1 */
12288 0xFFE7, /* bios_ctrl */
12289 0xFFFF, /* ultra_able */
12290 0, /* reserved2 */
12291 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
12292 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12293 0, /* dvc_cntl */
12294 0, /* bug_fix */
12295 0, /* serial_number_word1 */
12296 0, /* serial_number_word2 */
12297 0, /* serial_number_word3 */
12298 0, /* check_sum */
12299 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12300 , /* oem_name[16] */
12301 0, /* dvc_err_code */
12302 0, /* adv_err_code */
12303 0, /* adv_err_addr */
12304 0, /* saved_dvc_err_code */
12305 0, /* saved_adv_err_code */
12306 0, /* saved_adv_err_addr */
12307 0 /* num_of_err */
12308};
12309
12310static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
12311 0, /* cfg_lsw */
12312 0, /* cfg_msw */
12313 0, /* -disc_enable */
12314 0, /* wdtr_able */
12315 0, /* sdtr_able */
12316 0, /* start_motor */
12317 0, /* tagqng_able */
12318 0, /* bios_scan */
12319 0, /* scam_tolerant */
12320 1, /* adapter_scsi_id */
12321 1, /* bios_boot_delay */
12322 1, /* scsi_reset_delay */
12323 1, /* bios_id_lun */
12324 1, /* termination */
12325 1, /* reserved1 */
12326 0, /* bios_ctrl */
12327 0, /* ultra_able */
12328 0, /* reserved2 */
12329 1, /* max_host_qng */
12330 1, /* max_dvc_qng */
12331 0, /* dvc_cntl */
12332 0, /* bug_fix */
12333 0, /* serial_number_word1 */
12334 0, /* serial_number_word2 */
12335 0, /* serial_number_word3 */
12336 0, /* check_sum */
12337 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12338 , /* oem_name[16] */
12339 0, /* dvc_err_code */
12340 0, /* adv_err_code */
12341 0, /* adv_err_addr */
12342 0, /* saved_dvc_err_code */
12343 0, /* saved_adv_err_code */
12344 0, /* saved_adv_err_addr */
12345 0 /* num_of_err */
12346};
12347
12348static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
12349 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12350 0x0000, /* 01 cfg_msw */
12351 0xFFFF, /* 02 disc_enable */
12352 0xFFFF, /* 03 wdtr_able */
12353 0x4444, /* 04 sdtr_speed1 */
12354 0xFFFF, /* 05 start_motor */
12355 0xFFFF, /* 06 tagqng_able */
12356 0xFFFF, /* 07 bios_scan */
12357 0, /* 08 scam_tolerant */
12358 7, /* 09 adapter_scsi_id */
12359 0, /* bios_boot_delay */
12360 3, /* 10 scsi_reset_delay */
12361 0, /* bios_id_lun */
12362 0, /* 11 termination_se */
12363 0, /* termination_lvd */
12364 0xFFE7, /* 12 bios_ctrl */
12365 0x4444, /* 13 sdtr_speed2 */
12366 0x4444, /* 14 sdtr_speed3 */
12367 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12368 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12369 0, /* 16 dvc_cntl */
12370 0x4444, /* 17 sdtr_speed4 */
12371 0, /* 18 serial_number_word1 */
12372 0, /* 19 serial_number_word2 */
12373 0, /* 20 serial_number_word3 */
12374 0, /* 21 check_sum */
12375 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12376 , /* 22-29 oem_name[16] */
12377 0, /* 30 dvc_err_code */
12378 0, /* 31 adv_err_code */
12379 0, /* 32 adv_err_addr */
12380 0, /* 33 saved_dvc_err_code */
12381 0, /* 34 saved_adv_err_code */
12382 0, /* 35 saved_adv_err_addr */
12383 0, /* 36 reserved */
12384 0, /* 37 reserved */
12385 0, /* 38 reserved */
12386 0, /* 39 reserved */
12387 0, /* 40 reserved */
12388 0, /* 41 reserved */
12389 0, /* 42 reserved */
12390 0, /* 43 reserved */
12391 0, /* 44 reserved */
12392 0, /* 45 reserved */
12393 0, /* 46 reserved */
12394 0, /* 47 reserved */
12395 0, /* 48 reserved */
12396 0, /* 49 reserved */
12397 0, /* 50 reserved */
12398 0, /* 51 reserved */
12399 0, /* 52 reserved */
12400 0, /* 53 reserved */
12401 0, /* 54 reserved */
12402 0, /* 55 reserved */
12403 0, /* 56 cisptr_lsw */
12404 0, /* 57 cisprt_msw */
12405 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12406 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
12407 0, /* 60 reserved */
12408 0, /* 61 reserved */
12409 0, /* 62 reserved */
12410 0 /* 63 reserved */
12411};
12412
12413static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
12414 0, /* 00 cfg_lsw */
12415 0, /* 01 cfg_msw */
12416 0, /* 02 disc_enable */
12417 0, /* 03 wdtr_able */
12418 0, /* 04 sdtr_speed1 */
12419 0, /* 05 start_motor */
12420 0, /* 06 tagqng_able */
12421 0, /* 07 bios_scan */
12422 0, /* 08 scam_tolerant */
12423 1, /* 09 adapter_scsi_id */
12424 1, /* bios_boot_delay */
12425 1, /* 10 scsi_reset_delay */
12426 1, /* bios_id_lun */
12427 1, /* 11 termination_se */
12428 1, /* termination_lvd */
12429 0, /* 12 bios_ctrl */
12430 0, /* 13 sdtr_speed2 */
12431 0, /* 14 sdtr_speed3 */
12432 1, /* 15 max_host_qng */
12433 1, /* max_dvc_qng */
12434 0, /* 16 dvc_cntl */
12435 0, /* 17 sdtr_speed4 */
12436 0, /* 18 serial_number_word1 */
12437 0, /* 19 serial_number_word2 */
12438 0, /* 20 serial_number_word3 */
12439 0, /* 21 check_sum */
12440 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12441 , /* 22-29 oem_name[16] */
12442 0, /* 30 dvc_err_code */
12443 0, /* 31 adv_err_code */
12444 0, /* 32 adv_err_addr */
12445 0, /* 33 saved_dvc_err_code */
12446 0, /* 34 saved_adv_err_code */
12447 0, /* 35 saved_adv_err_addr */
12448 0, /* 36 reserved */
12449 0, /* 37 reserved */
12450 0, /* 38 reserved */
12451 0, /* 39 reserved */
12452 0, /* 40 reserved */
12453 0, /* 41 reserved */
12454 0, /* 42 reserved */
12455 0, /* 43 reserved */
12456 0, /* 44 reserved */
12457 0, /* 45 reserved */
12458 0, /* 46 reserved */
12459 0, /* 47 reserved */
12460 0, /* 48 reserved */
12461 0, /* 49 reserved */
12462 0, /* 50 reserved */
12463 0, /* 51 reserved */
12464 0, /* 52 reserved */
12465 0, /* 53 reserved */
12466 0, /* 54 reserved */
12467 0, /* 55 reserved */
12468 0, /* 56 cisptr_lsw */
12469 0, /* 57 cisprt_msw */
12470 0, /* 58 subsysvid */
12471 0, /* 59 subsysid */
12472 0, /* 60 reserved */
12473 0, /* 61 reserved */
12474 0, /* 62 reserved */
12475 0 /* 63 reserved */
12476};
12477
12478static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
12479 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
12480 0x0000, /* 01 cfg_msw */
12481 0xFFFF, /* 02 disc_enable */
12482 0xFFFF, /* 03 wdtr_able */
12483 0x5555, /* 04 sdtr_speed1 */
12484 0xFFFF, /* 05 start_motor */
12485 0xFFFF, /* 06 tagqng_able */
12486 0xFFFF, /* 07 bios_scan */
12487 0, /* 08 scam_tolerant */
12488 7, /* 09 adapter_scsi_id */
12489 0, /* bios_boot_delay */
12490 3, /* 10 scsi_reset_delay */
12491 0, /* bios_id_lun */
12492 0, /* 11 termination_se */
12493 0, /* termination_lvd */
12494 0xFFE7, /* 12 bios_ctrl */
12495 0x5555, /* 13 sdtr_speed2 */
12496 0x5555, /* 14 sdtr_speed3 */
12497 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
12498 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
12499 0, /* 16 dvc_cntl */
12500 0x5555, /* 17 sdtr_speed4 */
12501 0, /* 18 serial_number_word1 */
12502 0, /* 19 serial_number_word2 */
12503 0, /* 20 serial_number_word3 */
12504 0, /* 21 check_sum */
12505 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
12506 , /* 22-29 oem_name[16] */
12507 0, /* 30 dvc_err_code */
12508 0, /* 31 adv_err_code */
12509 0, /* 32 adv_err_addr */
12510 0, /* 33 saved_dvc_err_code */
12511 0, /* 34 saved_adv_err_code */
12512 0, /* 35 saved_adv_err_addr */
12513 0, /* 36 reserved */
12514 0, /* 37 reserved */
12515 0, /* 38 reserved */
12516 0, /* 39 reserved */
12517 0, /* 40 reserved */
12518 0, /* 41 reserved */
12519 0, /* 42 reserved */
12520 0, /* 43 reserved */
12521 0, /* 44 reserved */
12522 0, /* 45 reserved */
12523 0, /* 46 reserved */
12524 0, /* 47 reserved */
12525 0, /* 48 reserved */
12526 0, /* 49 reserved */
12527 0, /* 50 reserved */
12528 0, /* 51 reserved */
12529 0, /* 52 reserved */
12530 0, /* 53 reserved */
12531 0, /* 54 reserved */
12532 0, /* 55 reserved */
12533 0, /* 56 cisptr_lsw */
12534 0, /* 57 cisprt_msw */
12535 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
12536 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
12537 0, /* 60 reserved */
12538 0, /* 61 reserved */
12539 0, /* 62 reserved */
12540 0 /* 63 reserved */
12541};
12542
12543static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
12544 0, /* 00 cfg_lsw */
12545 0, /* 01 cfg_msw */
12546 0, /* 02 disc_enable */
12547 0, /* 03 wdtr_able */
12548 0, /* 04 sdtr_speed1 */
12549 0, /* 05 start_motor */
12550 0, /* 06 tagqng_able */
12551 0, /* 07 bios_scan */
12552 0, /* 08 scam_tolerant */
12553 1, /* 09 adapter_scsi_id */
12554 1, /* bios_boot_delay */
12555 1, /* 10 scsi_reset_delay */
12556 1, /* bios_id_lun */
12557 1, /* 11 termination_se */
12558 1, /* termination_lvd */
12559 0, /* 12 bios_ctrl */
12560 0, /* 13 sdtr_speed2 */
12561 0, /* 14 sdtr_speed3 */
12562 1, /* 15 max_host_qng */
12563 1, /* max_dvc_qng */
12564 0, /* 16 dvc_cntl */
12565 0, /* 17 sdtr_speed4 */
12566 0, /* 18 serial_number_word1 */
12567 0, /* 19 serial_number_word2 */
12568 0, /* 20 serial_number_word3 */
12569 0, /* 21 check_sum */
12570 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
12571 , /* 22-29 oem_name[16] */
12572 0, /* 30 dvc_err_code */
12573 0, /* 31 adv_err_code */
12574 0, /* 32 adv_err_addr */
12575 0, /* 33 saved_dvc_err_code */
12576 0, /* 34 saved_adv_err_code */
12577 0, /* 35 saved_adv_err_addr */
12578 0, /* 36 reserved */
12579 0, /* 37 reserved */
12580 0, /* 38 reserved */
12581 0, /* 39 reserved */
12582 0, /* 40 reserved */
12583 0, /* 41 reserved */
12584 0, /* 42 reserved */
12585 0, /* 43 reserved */
12586 0, /* 44 reserved */
12587 0, /* 45 reserved */
12588 0, /* 46 reserved */
12589 0, /* 47 reserved */
12590 0, /* 48 reserved */
12591 0, /* 49 reserved */
12592 0, /* 50 reserved */
12593 0, /* 51 reserved */
12594 0, /* 52 reserved */
12595 0, /* 53 reserved */
12596 0, /* 54 reserved */
12597 0, /* 55 reserved */
12598 0, /* 56 cisptr_lsw */
12599 0, /* 57 cisprt_msw */
12600 0, /* 58 subsysvid */
12601 0, /* 59 subsysid */
12602 0, /* 60 reserved */
12603 0, /* 61 reserved */
12604 0, /* 62 reserved */
12605 0 /* 63 reserved */
12606};
12607
12608#ifdef CONFIG_PCI
12609/*
12610 * Wait for EEPROM command to complete
12611 */
12612static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
12613{
12614 int eep_delay_ms;
12615
12616 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
12617 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
12618 ASC_EEP_CMD_DONE) {
12619 break;
12620 }
12621 mdelay(1);
12622 }
12623 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
12624 0)
12625 BUG();
12626}
12627
12628/*
12629 * Read the EEPROM from specified location
12630 */
12631static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
12632{
12633 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12634 ASC_EEP_CMD_READ | eep_word_addr);
12635 AdvWaitEEPCmd(iop_base);
12636 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
12637}
12638
12639/*
12640 * Write the EEPROM from 'cfg_buf'.
12641 */
12642void __devinit
12643AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12644{
12645 ushort *wbuf;
12646 ushort addr, chksum;
12647 ushort *charfields;
12648
12649 wbuf = (ushort *)cfg_buf;
12650 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12651 chksum = 0;
12652
12653 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12654 AdvWaitEEPCmd(iop_base);
12655
12656 /*
12657 * Write EEPROM from word 0 to word 20.
12658 */
12659 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12660 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12661 ushort word;
12662
12663 if (*charfields++) {
12664 word = cpu_to_le16(*wbuf);
12665 } else {
12666 word = *wbuf;
12667 }
12668 chksum += *wbuf; /* Checksum is calculated from word values. */
12669 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12670 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12671 ASC_EEP_CMD_WRITE | addr);
12672 AdvWaitEEPCmd(iop_base);
12673 mdelay(ADV_EEP_DELAY_MS);
12674 }
12675
12676 /*
12677 * Write EEPROM checksum at word 21.
12678 */
12679 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12680 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12681 AdvWaitEEPCmd(iop_base);
12682 wbuf++;
12683 charfields++;
12684
12685 /*
12686 * Write EEPROM OEM name at words 22 to 29.
12687 */
12688 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12689 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12690 ushort word;
12691
12692 if (*charfields++) {
12693 word = cpu_to_le16(*wbuf);
12694 } else {
12695 word = *wbuf;
12696 }
12697 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12698 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12699 ASC_EEP_CMD_WRITE | addr);
12700 AdvWaitEEPCmd(iop_base);
12701 }
12702 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12703 AdvWaitEEPCmd(iop_base);
12704}
12705
12706/*
12707 * Write the EEPROM from 'cfg_buf'.
12708 */
12709void __devinit
12710AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12711{
12712 ushort *wbuf;
12713 ushort *charfields;
12714 ushort addr, chksum;
12715
12716 wbuf = (ushort *)cfg_buf;
12717 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12718 chksum = 0;
12719
12720 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12721 AdvWaitEEPCmd(iop_base);
12722
12723 /*
12724 * Write EEPROM from word 0 to word 20.
12725 */
12726 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12727 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12728 ushort word;
12729
12730 if (*charfields++) {
12731 word = cpu_to_le16(*wbuf);
12732 } else {
12733 word = *wbuf;
12734 }
12735 chksum += *wbuf; /* Checksum is calculated from word values. */
12736 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12737 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12738 ASC_EEP_CMD_WRITE | addr);
12739 AdvWaitEEPCmd(iop_base);
12740 mdelay(ADV_EEP_DELAY_MS);
12741 }
12742
12743 /*
12744 * Write EEPROM checksum at word 21.
12745 */
12746 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12747 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12748 AdvWaitEEPCmd(iop_base);
12749 wbuf++;
12750 charfields++;
12751
12752 /*
12753 * Write EEPROM OEM name at words 22 to 29.
12754 */
12755 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12756 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12757 ushort word;
12758
12759 if (*charfields++) {
12760 word = cpu_to_le16(*wbuf);
12761 } else {
12762 word = *wbuf;
12763 }
12764 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12765 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12766 ASC_EEP_CMD_WRITE | addr);
12767 AdvWaitEEPCmd(iop_base);
12768 }
12769 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12770 AdvWaitEEPCmd(iop_base);
12771}
12772
12773/*
12774 * Write the EEPROM from 'cfg_buf'.
12775 */
12776void __devinit
12777AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12778{
12779 ushort *wbuf;
12780 ushort *charfields;
12781 ushort addr, chksum;
12782
12783 wbuf = (ushort *)cfg_buf;
12784 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12785 chksum = 0;
12786
12787 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
12788 AdvWaitEEPCmd(iop_base);
12789
12790 /*
12791 * Write EEPROM from word 0 to word 20.
12792 */
12793 for (addr = ADV_EEP_DVC_CFG_BEGIN;
12794 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
12795 ushort word;
12796
12797 if (*charfields++) {
12798 word = cpu_to_le16(*wbuf);
12799 } else {
12800 word = *wbuf;
12801 }
12802 chksum += *wbuf; /* Checksum is calculated from word values. */
12803 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12804 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12805 ASC_EEP_CMD_WRITE | addr);
12806 AdvWaitEEPCmd(iop_base);
12807 mdelay(ADV_EEP_DELAY_MS);
12808 }
12809
12810 /*
12811 * Write EEPROM checksum at word 21.
12812 */
12813 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
12814 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
12815 AdvWaitEEPCmd(iop_base);
12816 wbuf++;
12817 charfields++;
12818
12819 /*
12820 * Write EEPROM OEM name at words 22 to 29.
12821 */
12822 for (addr = ADV_EEP_DVC_CTL_BEGIN;
12823 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
12824 ushort word;
12825
12826 if (*charfields++) {
12827 word = cpu_to_le16(*wbuf);
12828 } else {
12829 word = *wbuf;
12830 }
12831 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
12832 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
12833 ASC_EEP_CMD_WRITE | addr);
12834 AdvWaitEEPCmd(iop_base);
12835 }
12836 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
12837 AdvWaitEEPCmd(iop_base);
12838}
12839
12840/*
12841 * Read EEPROM configuration into the specified buffer.
12842 *
12843 * Return a checksum based on the EEPROM configuration read.
12844 */
12845static ushort __devinit
12846AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
12847{
12848 ushort wval, chksum;
12849 ushort *wbuf;
12850 int eep_addr;
12851 ushort *charfields;
12852
12853 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
12854 wbuf = (ushort *)cfg_buf;
12855 chksum = 0;
12856
12857 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12858 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12859 wval = AdvReadEEPWord(iop_base, eep_addr);
12860 chksum += wval; /* Checksum is calculated from word values. */
12861 if (*charfields++) {
12862 *wbuf = le16_to_cpu(wval);
12863 } else {
12864 *wbuf = wval;
12865 }
12866 }
12867 /* Read checksum word. */
12868 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12869 wbuf++;
12870 charfields++;
12871
12872 /* Read rest of EEPROM not covered by the checksum. */
12873 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12874 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12875 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12876 if (*charfields++) {
12877 *wbuf = le16_to_cpu(*wbuf);
12878 }
12879 }
12880 return chksum;
12881}
12882
12883/*
12884 * Read EEPROM configuration into the specified buffer.
12885 *
12886 * Return a checksum based on the EEPROM configuration read.
12887 */
12888static ushort __devinit
12889AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
12890{
12891 ushort wval, chksum;
12892 ushort *wbuf;
12893 int eep_addr;
12894 ushort *charfields;
12895
12896 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
12897 wbuf = (ushort *)cfg_buf;
12898 chksum = 0;
12899
12900 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12901 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12902 wval = AdvReadEEPWord(iop_base, eep_addr);
12903 chksum += wval; /* Checksum is calculated from word values. */
12904 if (*charfields++) {
12905 *wbuf = le16_to_cpu(wval);
12906 } else {
12907 *wbuf = wval;
12908 }
12909 }
12910 /* Read checksum word. */
12911 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12912 wbuf++;
12913 charfields++;
12914
12915 /* Read rest of EEPROM not covered by the checksum. */
12916 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12917 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12918 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12919 if (*charfields++) {
12920 *wbuf = le16_to_cpu(*wbuf);
12921 }
12922 }
12923 return chksum;
12924}
12925
12926/*
12927 * Read EEPROM configuration into the specified buffer.
12928 *
12929 * Return a checksum based on the EEPROM configuration read.
12930 */
12931static ushort __devinit
12932AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
12933{
12934 ushort wval, chksum;
12935 ushort *wbuf;
12936 int eep_addr;
12937 ushort *charfields;
12938
12939 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
12940 wbuf = (ushort *)cfg_buf;
12941 chksum = 0;
12942
12943 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
12944 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
12945 wval = AdvReadEEPWord(iop_base, eep_addr);
12946 chksum += wval; /* Checksum is calculated from word values. */
12947 if (*charfields++) {
12948 *wbuf = le16_to_cpu(wval);
12949 } else {
12950 *wbuf = wval;
12951 }
12952 }
12953 /* Read checksum word. */
12954 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12955 wbuf++;
12956 charfields++;
12957
12958 /* Read rest of EEPROM not covered by the checksum. */
12959 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
12960 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
12961 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
12962 if (*charfields++) {
12963 *wbuf = le16_to_cpu(*wbuf);
12964 }
12965 }
12966 return chksum;
12967}
12968
12969/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070012970 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12971 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12972 * all of this is done.
12973 *
12974 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12975 *
12976 * For a non-fatal error return a warning code. If there are no warnings
12977 * then 0 is returned.
12978 *
12979 * Note: Chip is stopped on entry.
12980 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012981static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012982{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012983 AdvPortAddr iop_base;
12984 ushort warn_code;
12985 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012986
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012987 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012988
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012989 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012991 /*
12992 * Read the board's EEPROM configuration.
12993 *
12994 * Set default values if a bad checksum is found.
12995 */
12996 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12997 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012998
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012999 /*
13000 * Set EEPROM default values.
13001 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013002 memcpy(&eep_config, &Default_3550_EEPROM_Config,
13003 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013004
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013005 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013006 * Assume the 6 byte board serial number that was read from
13007 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013008 */
13009 eep_config.serial_number_word3 =
13010 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013011
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013012 eep_config.serial_number_word2 =
13013 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013014
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013015 eep_config.serial_number_word1 =
13016 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013017
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013018 AdvSet3550EEPConfig(iop_base, &eep_config);
13019 }
13020 /*
13021 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13022 * EEPROM configuration that was read.
13023 *
13024 * This is the mapping of EEPROM fields to Adv Library fields.
13025 */
13026 asc_dvc->wdtr_able = eep_config.wdtr_able;
13027 asc_dvc->sdtr_able = eep_config.sdtr_able;
13028 asc_dvc->ultra_able = eep_config.ultra_able;
13029 asc_dvc->tagqng_able = eep_config.tagqng_able;
13030 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13031 asc_dvc->max_host_qng = eep_config.max_host_qng;
13032 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13033 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13034 asc_dvc->start_motor = eep_config.start_motor;
13035 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13036 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13037 asc_dvc->no_scam = eep_config.scam_tolerant;
13038 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13039 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13040 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013041
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013042 /*
13043 * Set the host maximum queuing (max. 253, min. 16) and the per device
13044 * maximum queuing (max. 63, min. 4).
13045 */
13046 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13047 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13048 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13049 /* If the value is zero, assume it is uninitialized. */
13050 if (eep_config.max_host_qng == 0) {
13051 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13052 } else {
13053 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13054 }
13055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013056
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013057 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13058 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13059 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13060 /* If the value is zero, assume it is uninitialized. */
13061 if (eep_config.max_dvc_qng == 0) {
13062 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13063 } else {
13064 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13065 }
13066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013067
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013068 /*
13069 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13070 * set 'max_dvc_qng' to 'max_host_qng'.
13071 */
13072 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13073 eep_config.max_dvc_qng = eep_config.max_host_qng;
13074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013075
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013076 /*
13077 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13078 * values based on possibly adjusted EEPROM values.
13079 */
13080 asc_dvc->max_host_qng = eep_config.max_host_qng;
13081 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013082
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013083 /*
13084 * If the EEPROM 'termination' field is set to automatic (0), then set
13085 * the ADV_DVC_CFG 'termination' field to automatic also.
13086 *
13087 * If the termination is specified with a non-zero 'termination'
13088 * value check that a legal value is set and set the ADV_DVC_CFG
13089 * 'termination' field appropriately.
13090 */
13091 if (eep_config.termination == 0) {
13092 asc_dvc->cfg->termination = 0; /* auto termination */
13093 } else {
13094 /* Enable manual control with low off / high off. */
13095 if (eep_config.termination == 1) {
13096 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013097
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013098 /* Enable manual control with low off / high on. */
13099 } else if (eep_config.termination == 2) {
13100 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013102 /* Enable manual control with low on / high on. */
13103 } else if (eep_config.termination == 3) {
13104 asc_dvc->cfg->termination =
13105 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
13106 } else {
13107 /*
13108 * The EEPROM 'termination' field contains a bad value. Use
13109 * automatic termination instead.
13110 */
13111 asc_dvc->cfg->termination = 0;
13112 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13113 }
13114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013115
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013116 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013117}
13118
13119/*
13120 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13121 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13122 * all of this is done.
13123 *
13124 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13125 *
13126 * For a non-fatal error return a warning code. If there are no warnings
13127 * then 0 is returned.
13128 *
13129 * Note: Chip is stopped on entry.
13130 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013131static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013132{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013133 AdvPortAddr iop_base;
13134 ushort warn_code;
13135 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013136 uchar tid, termination;
13137 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013138
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013139 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013140
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013141 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013142
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013143 /*
13144 * Read the board's EEPROM configuration.
13145 *
13146 * Set default values if a bad checksum is found.
13147 */
13148 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13149 eep_config.check_sum) {
13150 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013151
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013152 /*
13153 * Set EEPROM default values.
13154 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013155 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13156 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013157
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013158 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013159 * Assume the 6 byte board serial number that was read from
13160 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013161 */
13162 eep_config.serial_number_word3 =
13163 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013164
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013165 eep_config.serial_number_word2 =
13166 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013167
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013168 eep_config.serial_number_word1 =
13169 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013170
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013171 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13172 }
13173 /*
13174 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13175 * EEPROM configuration that was read.
13176 *
13177 * This is the mapping of EEPROM fields to Adv Library fields.
13178 */
13179 asc_dvc->wdtr_able = eep_config.wdtr_able;
13180 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13181 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13182 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13183 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13184 asc_dvc->tagqng_able = eep_config.tagqng_able;
13185 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13186 asc_dvc->max_host_qng = eep_config.max_host_qng;
13187 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13188 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13189 asc_dvc->start_motor = eep_config.start_motor;
13190 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13191 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13192 asc_dvc->no_scam = eep_config.scam_tolerant;
13193 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13194 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13195 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013197 /*
13198 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13199 * are set, then set an 'sdtr_able' bit for it.
13200 */
13201 asc_dvc->sdtr_able = 0;
13202 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13203 if (tid == 0) {
13204 sdtr_speed = asc_dvc->sdtr_speed1;
13205 } else if (tid == 4) {
13206 sdtr_speed = asc_dvc->sdtr_speed2;
13207 } else if (tid == 8) {
13208 sdtr_speed = asc_dvc->sdtr_speed3;
13209 } else if (tid == 12) {
13210 sdtr_speed = asc_dvc->sdtr_speed4;
13211 }
13212 if (sdtr_speed & ADV_MAX_TID) {
13213 asc_dvc->sdtr_able |= (1 << tid);
13214 }
13215 sdtr_speed >>= 4;
13216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013217
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013218 /*
13219 * Set the host maximum queuing (max. 253, min. 16) and the per device
13220 * maximum queuing (max. 63, min. 4).
13221 */
13222 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13223 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13224 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13225 /* If the value is zero, assume it is uninitialized. */
13226 if (eep_config.max_host_qng == 0) {
13227 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13228 } else {
13229 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13230 }
13231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013232
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013233 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13234 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13235 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13236 /* If the value is zero, assume it is uninitialized. */
13237 if (eep_config.max_dvc_qng == 0) {
13238 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13239 } else {
13240 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13241 }
13242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013243
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013244 /*
13245 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13246 * set 'max_dvc_qng' to 'max_host_qng'.
13247 */
13248 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13249 eep_config.max_dvc_qng = eep_config.max_host_qng;
13250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013251
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013252 /*
13253 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13254 * values based on possibly adjusted EEPROM values.
13255 */
13256 asc_dvc->max_host_qng = eep_config.max_host_qng;
13257 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013258
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013259 /*
13260 * If the EEPROM 'termination' field is set to automatic (0), then set
13261 * the ADV_DVC_CFG 'termination' field to automatic also.
13262 *
13263 * If the termination is specified with a non-zero 'termination'
13264 * value check that a legal value is set and set the ADV_DVC_CFG
13265 * 'termination' field appropriately.
13266 */
13267 if (eep_config.termination_se == 0) {
13268 termination = 0; /* auto termination for SE */
13269 } else {
13270 /* Enable manual control with low off / high off. */
13271 if (eep_config.termination_se == 1) {
13272 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013273
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013274 /* Enable manual control with low off / high on. */
13275 } else if (eep_config.termination_se == 2) {
13276 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013277
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013278 /* Enable manual control with low on / high on. */
13279 } else if (eep_config.termination_se == 3) {
13280 termination = TERM_SE;
13281 } else {
13282 /*
13283 * The EEPROM 'termination_se' field contains a bad value.
13284 * Use automatic termination instead.
13285 */
13286 termination = 0;
13287 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13288 }
13289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013290
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013291 if (eep_config.termination_lvd == 0) {
13292 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13293 } else {
13294 /* Enable manual control with low off / high off. */
13295 if (eep_config.termination_lvd == 1) {
13296 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013298 /* Enable manual control with low off / high on. */
13299 } else if (eep_config.termination_lvd == 2) {
13300 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013301
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013302 /* Enable manual control with low on / high on. */
13303 } else if (eep_config.termination_lvd == 3) {
13304 asc_dvc->cfg->termination = termination | TERM_LVD;
13305 } else {
13306 /*
13307 * The EEPROM 'termination_lvd' field contains a bad value.
13308 * Use automatic termination instead.
13309 */
13310 asc_dvc->cfg->termination = termination;
13311 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13312 }
13313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013314
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013315 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013316}
13317
13318/*
13319 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13320 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13321 * all of this is done.
13322 *
13323 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13324 *
13325 * For a non-fatal error return a warning code. If there are no warnings
13326 * then 0 is returned.
13327 *
13328 * Note: Chip is stopped on entry.
13329 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013330static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013331{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013332 AdvPortAddr iop_base;
13333 ushort warn_code;
13334 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013335 uchar tid, termination;
13336 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013337
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013338 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013339
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013340 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013341
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013342 /*
13343 * Read the board's EEPROM configuration.
13344 *
13345 * Set default values if a bad checksum is found.
13346 */
13347 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13348 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013349 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013350 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013351
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013352 /*
13353 * Set EEPROM default values.
13354 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013355 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13356 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013357
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013358 if (PCI_FUNC(pdev->devfn) != 0) {
13359 u8 ints;
13360 /*
13361 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13362 * and old Mac system booting problem. The Expansion
13363 * ROM must be disabled in Function 1 for these systems
13364 */
13365 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13366 /*
13367 * Clear the INTAB (bit 11) if the GPIO 0 input
13368 * indicates the Function 1 interrupt line is wired
13369 * to INTB.
13370 *
13371 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13372 * 1 - Function 1 interrupt line wired to INT A.
13373 * 0 - Function 1 interrupt line wired to INT B.
13374 *
13375 * Note: Function 0 is always wired to INTA.
13376 * Put all 5 GPIO bits in input mode and then read
13377 * their input values.
13378 */
13379 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13380 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13381 if ((ints & 0x01) == 0)
13382 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013384
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013385 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013386 * Assume the 6 byte board serial number that was read from
13387 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013388 */
13389 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013390 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013391 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013392 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013393 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013394 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013396 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013398
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013399 /*
13400 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13401 * EEPROM configuration that was read.
13402 *
13403 * This is the mapping of EEPROM fields to Adv Library fields.
13404 */
13405 asc_dvc->wdtr_able = eep_config.wdtr_able;
13406 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13407 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13408 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13409 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13410 asc_dvc->ppr_able = 0;
13411 asc_dvc->tagqng_able = eep_config.tagqng_able;
13412 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13413 asc_dvc->max_host_qng = eep_config.max_host_qng;
13414 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13415 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13416 asc_dvc->start_motor = eep_config.start_motor;
13417 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13418 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13419 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013420
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013421 /*
13422 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13423 * are set, then set an 'sdtr_able' bit for it.
13424 */
13425 asc_dvc->sdtr_able = 0;
13426 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13427 if (tid == 0) {
13428 sdtr_speed = asc_dvc->sdtr_speed1;
13429 } else if (tid == 4) {
13430 sdtr_speed = asc_dvc->sdtr_speed2;
13431 } else if (tid == 8) {
13432 sdtr_speed = asc_dvc->sdtr_speed3;
13433 } else if (tid == 12) {
13434 sdtr_speed = asc_dvc->sdtr_speed4;
13435 }
13436 if (sdtr_speed & ASC_MAX_TID) {
13437 asc_dvc->sdtr_able |= (1 << tid);
13438 }
13439 sdtr_speed >>= 4;
13440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013441
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013442 /*
13443 * Set the host maximum queuing (max. 253, min. 16) and the per device
13444 * maximum queuing (max. 63, min. 4).
13445 */
13446 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13447 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13448 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13449 /* If the value is zero, assume it is uninitialized. */
13450 if (eep_config.max_host_qng == 0) {
13451 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13452 } else {
13453 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13454 }
13455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013456
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013457 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13458 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13459 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13460 /* If the value is zero, assume it is uninitialized. */
13461 if (eep_config.max_dvc_qng == 0) {
13462 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13463 } else {
13464 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13465 }
13466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013467
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013468 /*
13469 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13470 * set 'max_dvc_qng' to 'max_host_qng'.
13471 */
13472 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13473 eep_config.max_dvc_qng = eep_config.max_host_qng;
13474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013475
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013476 /*
13477 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13478 * values based on possibly adjusted EEPROM values.
13479 */
13480 asc_dvc->max_host_qng = eep_config.max_host_qng;
13481 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013482
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013483 /*
13484 * If the EEPROM 'termination' field is set to automatic (0), then set
13485 * the ASC_DVC_CFG 'termination' field to automatic also.
13486 *
13487 * If the termination is specified with a non-zero 'termination'
13488 * value check that a legal value is set and set the ASC_DVC_CFG
13489 * 'termination' field appropriately.
13490 */
13491 if (eep_config.termination_se == 0) {
13492 termination = 0; /* auto termination for SE */
13493 } else {
13494 /* Enable manual control with low off / high off. */
13495 if (eep_config.termination_se == 1) {
13496 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013497
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013498 /* Enable manual control with low off / high on. */
13499 } else if (eep_config.termination_se == 2) {
13500 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013501
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013502 /* Enable manual control with low on / high on. */
13503 } else if (eep_config.termination_se == 3) {
13504 termination = TERM_SE;
13505 } else {
13506 /*
13507 * The EEPROM 'termination_se' field contains a bad value.
13508 * Use automatic termination instead.
13509 */
13510 termination = 0;
13511 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13512 }
13513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013514
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013515 if (eep_config.termination_lvd == 0) {
13516 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13517 } else {
13518 /* Enable manual control with low off / high off. */
13519 if (eep_config.termination_lvd == 1) {
13520 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013521
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013522 /* Enable manual control with low off / high on. */
13523 } else if (eep_config.termination_lvd == 2) {
13524 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013525
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013526 /* Enable manual control with low on / high on. */
13527 } else if (eep_config.termination_lvd == 3) {
13528 asc_dvc->cfg->termination = termination | TERM_LVD;
13529 } else {
13530 /*
13531 * The EEPROM 'termination_lvd' field contains a bad value.
13532 * Use automatic termination instead.
13533 */
13534 asc_dvc->cfg->termination = termination;
13535 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13536 }
13537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013538
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013539 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013540}
13541
13542/*
Matthew Wilcox51219352007-10-02 21:55:22 -040013543 * Initialize the ADV_DVC_VAR structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013544 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013545 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013546 *
Matthew Wilcox51219352007-10-02 21:55:22 -040013547 * For a non-fatal error return a warning code. If there are no warnings
13548 * then 0 is returned.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013549 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013550static int __devinit
13551AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013552{
Matthew Wilcox51219352007-10-02 21:55:22 -040013553 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
13554 unsigned short warn_code = 0;
13555 AdvPortAddr iop_base = asc_dvc->iop_base;
13556 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013557 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013558
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013559 asc_dvc->err_code = 0;
Matthew Wilcox51219352007-10-02 21:55:22 -040013560
13561 /*
13562 * Save the state of the PCI Configuration Command Register
13563 * "Parity Error Response Control" Bit. If the bit is clear (0),
13564 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
13565 * DMA parity errors.
13566 */
13567 asc_dvc->cfg->control_flag = 0;
13568 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
13569 if ((cmd & PCI_COMMAND_PARITY) == 0)
13570 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
13571
13572 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
13573 ADV_LIB_VERSION_MINOR;
13574 asc_dvc->cfg->chip_version =
13575 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
13576
13577 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
13578 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
13579 (ushort)ADV_CHIP_ID_BYTE);
13580
13581 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
13582 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
13583 (ushort)ADV_CHIP_ID_WORD);
13584
13585 /*
13586 * Reset the chip to start and allow register writes.
13587 */
13588 if (AdvFindSignature(iop_base) == 0) {
13589 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13590 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013591 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013592 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013593 * The caller must set 'chip_type' to a valid setting.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013594 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013595 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
13596 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
13597 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
13598 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
13599 return ADV_ERROR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013601
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013602 /*
Matthew Wilcox51219352007-10-02 21:55:22 -040013603 * Reset Chip.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013604 */
Matthew Wilcox51219352007-10-02 21:55:22 -040013605 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13606 ADV_CTRL_REG_CMD_RESET);
13607 mdelay(100);
13608 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13609 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013610
Matthew Wilcox51219352007-10-02 21:55:22 -040013611 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13612 status = AdvInitFrom38C1600EEP(asc_dvc);
13613 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13614 status = AdvInitFrom38C0800EEP(asc_dvc);
13615 } else {
13616 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013617 }
Matthew Wilcox51219352007-10-02 21:55:22 -040013618 warn_code |= status;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013620
Matthew Wilcox51219352007-10-02 21:55:22 -040013621 if (warn_code != 0) {
13622 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
13623 boardp->id, warn_code);
13624 }
13625
13626 if (asc_dvc->err_code) {
13627 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
13628 boardp->id, asc_dvc->err_code);
13629 }
13630
13631 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013632}
Matthew Wilcox51219352007-10-02 21:55:22 -040013633#endif
13634
13635static struct scsi_host_template advansys_template = {
13636 .proc_name = DRV_NAME,
13637#ifdef CONFIG_PROC_FS
13638 .proc_info = advansys_proc_info,
13639#endif
13640 .name = DRV_NAME,
13641 .info = advansys_info,
13642 .queuecommand = advansys_queuecommand,
13643 .eh_bus_reset_handler = advansys_reset,
13644 .bios_param = advansys_biosparam,
13645 .slave_configure = advansys_slave_configure,
13646 /*
13647 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
13648 * must be set. The flag will be cleared in advansys_board_found
13649 * for non-ISA adapters.
13650 */
13651 .unchecked_isa_dma = 1,
13652 /*
13653 * All adapters controlled by this driver are capable of large
13654 * scatter-gather lists. According to the mid-level SCSI documentation
13655 * this obviates any performance gain provided by setting
13656 * 'use_clustering'. But empirically while CPU utilization is increased
13657 * by enabling clustering, I/O throughput increases as well.
13658 */
13659 .use_clustering = ENABLE_CLUSTERING,
13660};
Linus Torvalds1da177e2005-04-16 15:20:36 -070013661
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013662static int __devinit
13663advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
13664{
13665 int req_cnt = 0;
13666 adv_req_t *reqp = NULL;
13667 int sg_cnt = 0;
13668 adv_sgblk_t *sgp;
13669 int warn_code, err_code;
13670
13671 /*
13672 * Allocate buffer carrier structures. The total size
13673 * is about 4 KB, so allocate all at once.
13674 */
13675 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
13676 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
13677
13678 if (!boardp->carrp)
13679 goto kmalloc_failed;
13680
13681 /*
13682 * Allocate up to 'max_host_qng' request structures for the Wide
13683 * board. The total size is about 16 KB, so allocate all at once.
13684 * If the allocation fails decrement and try again.
13685 */
13686 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
13687 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
13688
13689 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
13690 "bytes %lu\n", reqp, req_cnt,
13691 (ulong)sizeof(adv_req_t) * req_cnt);
13692
13693 if (reqp)
13694 break;
13695 }
13696
13697 if (!reqp)
13698 goto kmalloc_failed;
13699
13700 boardp->orig_reqp = reqp;
13701
13702 /*
13703 * Allocate up to ADV_TOT_SG_BLOCK request structures for
13704 * the Wide board. Each structure is about 136 bytes.
13705 */
13706 boardp->adv_sgblkp = NULL;
13707 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
13708 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
13709
13710 if (!sgp)
13711 break;
13712
13713 sgp->next_sgblkp = boardp->adv_sgblkp;
13714 boardp->adv_sgblkp = sgp;
13715
13716 }
13717
13718 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
13719 sg_cnt, sizeof(adv_sgblk_t),
13720 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
13721
13722 if (!boardp->adv_sgblkp)
13723 goto kmalloc_failed;
13724
13725 adv_dvc_varp->carrier_buf = boardp->carrp;
13726
13727 /*
13728 * Point 'adv_reqp' to the request structures and
13729 * link them together.
13730 */
13731 req_cnt--;
13732 reqp[req_cnt].next_reqp = NULL;
13733 for (; req_cnt > 0; req_cnt--) {
13734 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
13735 }
13736 boardp->adv_reqp = &reqp[0];
13737
13738 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
13739 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
13740 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
13741 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
13742 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
13743 "\n");
13744 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
13745 } else {
13746 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
13747 "\n");
13748 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
13749 }
13750 err_code = adv_dvc_varp->err_code;
13751
13752 if (warn_code || err_code) {
13753 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
13754 " error 0x%x\n", boardp->id, warn_code, err_code);
13755 }
13756
13757 goto exit;
13758
13759 kmalloc_failed:
13760 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
13761 "failed\n", boardp->id);
13762 err_code = ADV_ERROR;
13763 exit:
13764 return err_code;
13765}
13766
13767static void advansys_wide_free_mem(asc_board_t *boardp)
13768{
13769 kfree(boardp->carrp);
13770 boardp->carrp = NULL;
13771 kfree(boardp->orig_reqp);
13772 boardp->orig_reqp = boardp->adv_reqp = NULL;
13773 while (boardp->adv_sgblkp) {
13774 adv_sgblk_t *sgp = boardp->adv_sgblkp;
13775 boardp->adv_sgblkp = sgp->next_sgblkp;
13776 kfree(sgp);
13777 }
13778}
13779
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013780static int __devinit advansys_board_found(struct Scsi_Host *shost,
13781 unsigned int iop, int bus_type)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013782{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013783 struct pci_dev *pdev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013784 asc_board_t *boardp;
13785 ASC_DVC_VAR *asc_dvc_varp = NULL;
13786 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013787 int share_irq, warn_code, ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013788
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013789 boardp = ASC_BOARDP(shost);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013790 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013791 spin_lock_init(&boardp->lock);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013792 pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013793
13794 if (ASC_NARROW_BOARD(boardp)) {
13795 ASC_DBG(1, "advansys_board_found: narrow board\n");
13796 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
13797 asc_dvc_varp->bus_type = bus_type;
13798 asc_dvc_varp->drv_ptr = boardp;
13799 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
13800 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
13801 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013802 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013803#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013804 ASC_DBG(1, "advansys_board_found: wide board\n");
13805 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
13806 adv_dvc_varp->drv_ptr = boardp;
13807 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013808 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
13809 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
13810 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
13811 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
13812 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
13813 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
13814 } else {
13815 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
13816 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
13817 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013818
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013819 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
13820 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
13821 boardp->asc_n_io_port);
13822 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013823 ASC_PRINT3
13824 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013825 boardp->id, pci_resource_start(pdev, 1),
13826 boardp->asc_n_io_port);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013827 ret = -ENODEV;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013828 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013829 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013830 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060013831 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013832 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013833
13834 /*
13835 * Even though it isn't used to access wide boards, other
13836 * than for the debug line below, save I/O Port address so
13837 * that it can be reported.
13838 */
13839 boardp->ioport = iop;
13840
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040013841 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
13842 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
13843 (ushort)inpw(iop));
13844#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013845 }
13846
13847#ifdef CONFIG_PROC_FS
13848 /*
13849 * Allocate buffer for printing information from
13850 * /proc/scsi/advansys/[0...].
13851 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013852 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
13853 if (!boardp->prtbuf) {
13854 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
13855 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013856 ret = -ENOMEM;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013857 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013858 }
13859#endif /* CONFIG_PROC_FS */
13860
13861 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013862 /*
13863 * Set the board bus type and PCI IRQ before
13864 * calling AscInitGetConfig().
13865 */
13866 switch (asc_dvc_varp->bus_type) {
13867#ifdef CONFIG_ISA
13868 case ASC_IS_ISA:
13869 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013870 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013871 break;
13872 case ASC_IS_VL:
13873 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013874 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013875 break;
13876 case ASC_IS_EISA:
13877 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013878 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013879 break;
13880#endif /* CONFIG_ISA */
13881#ifdef CONFIG_PCI
13882 case ASC_IS_PCI:
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013883 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013884 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013885 break;
13886#endif /* CONFIG_PCI */
13887 default:
13888 ASC_PRINT2
13889 ("advansys_board_found: board %d: unknown adapter type: %d\n",
13890 boardp->id, asc_dvc_varp->bus_type);
13891 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060013892 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013893 break;
13894 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013895
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013896 /*
13897 * NOTE: AscInitGetConfig() may change the board's
13898 * bus_type value. The bus_type value should no
13899 * longer be used. If the bus_type field must be
13900 * referenced only use the bit-wise AND operator "&".
13901 */
13902 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013903 ret = AscInitGetConfig(boardp) ? -ENODEV : 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013904 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013905#ifdef CONFIG_PCI
13906 /*
13907 * For Wide boards set PCI information before calling
13908 * AdvInitGetConfig().
13909 */
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013910 shost->unchecked_isa_dma = FALSE;
13911 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013912 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040013913
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013914 ret = AdvInitGetConfig(pdev, boardp) ? -ENODEV : 0;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060013915#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013916 }
13917
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013918 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013919 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013920
13921 /*
13922 * Save the EEPROM configuration so that it can be displayed
13923 * from /proc/scsi/advansys/[0...].
13924 */
13925 if (ASC_NARROW_BOARD(boardp)) {
13926
13927 ASCEEP_CONFIG *ep;
13928
13929 /*
13930 * Set the adapter's target id bit in the 'init_tidmask' field.
13931 */
13932 boardp->init_tidmask |=
13933 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
13934
13935 /*
13936 * Save EEPROM settings for the board.
13937 */
13938 ep = &boardp->eep_config.asc_eep;
13939
13940 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
13941 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
13942 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
13943 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
13944 ep->start_motor = asc_dvc_varp->start_motor;
13945 ep->cntl = asc_dvc_varp->dvc_cntl;
13946 ep->no_scam = asc_dvc_varp->no_scam;
13947 ep->max_total_qng = asc_dvc_varp->max_total_qng;
13948 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
13949 /* 'max_tag_qng' is set to the same value for every device. */
13950 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
13951 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
13952 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
13953 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
13954 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
13955 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
13956 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
13957
13958 /*
13959 * Modify board configuration.
13960 */
13961 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxd361db42007-10-02 21:55:29 -040013962 ret = AscInitSetConfig(pdev, boardp) ? -ENODEV : 0;
13963 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060013964 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013965 } else {
13966 ADVEEP_3550_CONFIG *ep_3550;
13967 ADVEEP_38C0800_CONFIG *ep_38C0800;
13968 ADVEEP_38C1600_CONFIG *ep_38C1600;
13969
13970 /*
13971 * Save Wide EEP Configuration Information.
13972 */
13973 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
13974 ep_3550 = &boardp->eep_config.adv_3550_eep;
13975
13976 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
13977 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
13978 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
13979 ep_3550->termination = adv_dvc_varp->cfg->termination;
13980 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
13981 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
13982 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
13983 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
13984 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
13985 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
13986 ep_3550->start_motor = adv_dvc_varp->start_motor;
13987 ep_3550->scsi_reset_delay =
13988 adv_dvc_varp->scsi_reset_wait;
13989 ep_3550->serial_number_word1 =
13990 adv_dvc_varp->cfg->serial1;
13991 ep_3550->serial_number_word2 =
13992 adv_dvc_varp->cfg->serial2;
13993 ep_3550->serial_number_word3 =
13994 adv_dvc_varp->cfg->serial3;
13995 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
13996 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
13997
13998 ep_38C0800->adapter_scsi_id =
13999 adv_dvc_varp->chip_scsi_id;
14000 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
14001 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14002 ep_38C0800->termination_lvd =
14003 adv_dvc_varp->cfg->termination;
14004 ep_38C0800->disc_enable =
14005 adv_dvc_varp->cfg->disc_enable;
14006 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
14007 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
14008 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14009 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14010 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14011 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14012 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14013 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14014 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
14015 ep_38C0800->scsi_reset_delay =
14016 adv_dvc_varp->scsi_reset_wait;
14017 ep_38C0800->serial_number_word1 =
14018 adv_dvc_varp->cfg->serial1;
14019 ep_38C0800->serial_number_word2 =
14020 adv_dvc_varp->cfg->serial2;
14021 ep_38C0800->serial_number_word3 =
14022 adv_dvc_varp->cfg->serial3;
14023 } else {
14024 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
14025
14026 ep_38C1600->adapter_scsi_id =
14027 adv_dvc_varp->chip_scsi_id;
14028 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
14029 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14030 ep_38C1600->termination_lvd =
14031 adv_dvc_varp->cfg->termination;
14032 ep_38C1600->disc_enable =
14033 adv_dvc_varp->cfg->disc_enable;
14034 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
14035 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
14036 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14037 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14038 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14039 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14040 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14041 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14042 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
14043 ep_38C1600->scsi_reset_delay =
14044 adv_dvc_varp->scsi_reset_wait;
14045 ep_38C1600->serial_number_word1 =
14046 adv_dvc_varp->cfg->serial1;
14047 ep_38C1600->serial_number_word2 =
14048 adv_dvc_varp->cfg->serial2;
14049 ep_38C1600->serial_number_word3 =
14050 adv_dvc_varp->cfg->serial3;
14051 }
14052
14053 /*
14054 * Set the adapter's target id bit in the 'init_tidmask' field.
14055 */
14056 boardp->init_tidmask |=
14057 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014058 }
14059
14060 /*
14061 * Channels are numbered beginning with 0. For AdvanSys one host
14062 * structure supports one channel. Multi-channel boards have a
14063 * separate host structure for each channel.
14064 */
14065 shost->max_channel = 0;
14066 if (ASC_NARROW_BOARD(boardp)) {
14067 shost->max_id = ASC_MAX_TID + 1;
14068 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014069 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014070
14071 shost->io_port = asc_dvc_varp->iop_base;
14072 boardp->asc_n_io_port = ASC_IOADR_GAP;
14073 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
14074
14075 /* Set maximum number of queues the adapter can handle. */
14076 shost->can_queue = asc_dvc_varp->max_total_qng;
14077 } else {
14078 shost->max_id = ADV_MAX_TID + 1;
14079 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014080 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014081
14082 /*
14083 * Save the I/O Port address and length even though
14084 * I/O ports are not used to access Wide boards.
14085 * Instead the Wide boards are accessed with
14086 * PCI Memory Mapped I/O.
14087 */
14088 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014089
14090 shost->this_id = adv_dvc_varp->chip_scsi_id;
14091
14092 /* Set maximum number of queues the adapter can handle. */
14093 shost->can_queue = adv_dvc_varp->max_host_qng;
14094 }
14095
14096 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014097 * Following v1.3.89, 'cmd_per_lun' is no longer needed
14098 * and should be set to zero.
14099 *
14100 * But because of a bug introduced in v1.3.89 if the driver is
14101 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
14102 * SCSI function 'allocate_device' will panic. To allow the driver
14103 * to work as a module in these kernels set 'cmd_per_lun' to 1.
14104 *
14105 * Note: This is wrong. cmd_per_lun should be set to the depth
14106 * you want on untagged devices always.
14107 #ifdef MODULE
14108 */
14109 shost->cmd_per_lun = 1;
14110/* #else
14111 shost->cmd_per_lun = 0;
14112#endif */
14113
14114 /*
14115 * Set the maximum number of scatter-gather elements the
14116 * adapter can handle.
14117 */
14118 if (ASC_NARROW_BOARD(boardp)) {
14119 /*
14120 * Allow two commands with 'sg_tablesize' scatter-gather
14121 * elements to be executed simultaneously. This value is
14122 * the theoretical hardware limit. It may be decreased
14123 * below.
14124 */
14125 shost->sg_tablesize =
14126 (((asc_dvc_varp->max_total_qng - 2) / 2) *
14127 ASC_SG_LIST_PER_Q) + 1;
14128 } else {
14129 shost->sg_tablesize = ADV_MAX_SG_LIST;
14130 }
14131
14132 /*
14133 * The value of 'sg_tablesize' can not exceed the SCSI
14134 * mid-level driver definition of SG_ALL. SG_ALL also
14135 * must not be exceeded, because it is used to define the
14136 * size of the scatter-gather table in 'struct asc_sg_head'.
14137 */
14138 if (shost->sg_tablesize > SG_ALL) {
14139 shost->sg_tablesize = SG_ALL;
14140 }
14141
14142 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
14143
14144 /* BIOS start address. */
14145 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014146 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
14147 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014148 } else {
14149 /*
14150 * Fill-in BIOS board variables. The Wide BIOS saves
14151 * information in LRAM that is used by the driver.
14152 */
14153 AdvReadWordLram(adv_dvc_varp->iop_base,
14154 BIOS_SIGNATURE, boardp->bios_signature);
14155 AdvReadWordLram(adv_dvc_varp->iop_base,
14156 BIOS_VERSION, boardp->bios_version);
14157 AdvReadWordLram(adv_dvc_varp->iop_base,
14158 BIOS_CODESEG, boardp->bios_codeseg);
14159 AdvReadWordLram(adv_dvc_varp->iop_base,
14160 BIOS_CODELEN, boardp->bios_codelen);
14161
14162 ASC_DBG2(1,
14163 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
14164 boardp->bios_signature, boardp->bios_version);
14165
14166 ASC_DBG2(1,
14167 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
14168 boardp->bios_codeseg, boardp->bios_codelen);
14169
14170 /*
14171 * If the BIOS saved a valid signature, then fill in
14172 * the BIOS code segment base address.
14173 */
14174 if (boardp->bios_signature == 0x55AA) {
14175 /*
14176 * Convert x86 realmode code segment to a linear
14177 * address by shifting left 4.
14178 */
14179 shost->base = ((ulong)boardp->bios_codeseg << 4);
14180 } else {
14181 shost->base = 0;
14182 }
14183 }
14184
14185 /*
14186 * Register Board Resources - I/O Port, DMA, IRQ
14187 */
14188
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189 /* Register DMA Channel for Narrow boards. */
14190 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14191#ifdef CONFIG_ISA
14192 if (ASC_NARROW_BOARD(boardp)) {
14193 /* Register DMA channel for ISA bus. */
14194 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14195 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014196 ret = request_dma(shost->dma_channel, DRV_NAME);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014197 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014198 ASC_PRINT3
14199 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14200 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014201 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014202 }
14203 AscEnableIsaDma(shost->dma_channel);
14204 }
14205 }
14206#endif /* CONFIG_ISA */
14207
14208 /* Register IRQ Number. */
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014209 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", boardp->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014210
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014211 ret = request_irq(boardp->irq, advansys_interrupt, share_irq,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014212 DRV_NAME, shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014213
14214 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014215 if (ret == -EBUSY) {
14216 ASC_PRINT2
14217 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014218 boardp->id, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014219 } else if (ret == -EINVAL) {
14220 ASC_PRINT2
14221 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014222 boardp->id, boardp->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014223 } else {
14224 ASC_PRINT3
14225 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014226 boardp->id, boardp->irq, ret);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014227 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014228 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014229 }
14230
14231 /*
14232 * Initialize board RISC chip and enable interrupts.
14233 */
14234 if (ASC_NARROW_BOARD(boardp)) {
14235 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
14236 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014237
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014238 if (warn_code || asc_dvc_varp->err_code) {
14239 ASC_PRINT4("advansys_board_found: board %d error: "
14240 "init_state 0x%x, warn 0x%x, error 0x%x\n",
14241 boardp->id, asc_dvc_varp->init_state,
14242 warn_code, asc_dvc_varp->err_code);
14243 if (asc_dvc_varp->err_code)
14244 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014245 }
14246 } else {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014247 if (advansys_wide_init_chip(boardp, adv_dvc_varp))
14248 ret = -ENODEV;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014249 }
14250
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014251 if (ret)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014252 goto err_free_wide_mem;
14253
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014254 ASC_DBG_PRT_SCSI_HOST(2, shost);
14255
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014256 ret = scsi_add_host(shost, boardp->dev);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014257 if (ret)
14258 goto err_free_wide_mem;
14259
14260 scsi_scan_host(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014261 return 0;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014262
14263 err_free_wide_mem:
14264 advansys_wide_free_mem(boardp);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014265 free_irq(boardp->irq, shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014266 err_free_dma:
14267 if (shost->dma_channel != NO_ISA_DMA)
14268 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014269 err_free_proc:
14270 kfree(boardp->prtbuf);
14271 err_unmap:
14272 if (boardp->ioremap_addr)
14273 iounmap(boardp->ioremap_addr);
14274 err_shost:
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014275 return ret;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014276}
14277
14278/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014279 * advansys_release()
14280 *
14281 * Release resources allocated for a single AdvanSys adapter.
14282 */
14283static int advansys_release(struct Scsi_Host *shost)
14284{
14285 asc_board_t *boardp;
14286
14287 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014288 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014289 boardp = ASC_BOARDP(shost);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014290 free_irq(boardp->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014291 if (shost->dma_channel != NO_ISA_DMA) {
14292 ASC_DBG(1, "advansys_release: free_dma()\n");
14293 free_dma(shost->dma_channel);
14294 }
Matthew Wilcox9a256fa2007-10-02 21:55:28 -040014295 if (!ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014296 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014297 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014298 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014299 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014300 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014301 ASC_DBG(1, "advansys_release: end\n");
14302 return 0;
14303}
14304
Matthew Wilcox95c9f162007-09-09 08:56:39 -060014305#define ASC_IOADR_TABLE_MAX_IX 11
14306
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014307static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
14308 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
14309 0x0210, 0x0230, 0x0250, 0x0330
14310};
14311
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014312/*
14313 * The ISA IRQ number is found in bits 2 and 3 of the CfgLsw. It decodes as:
14314 * 00: 10
14315 * 01: 11
14316 * 10: 12
14317 * 11: 15
14318 */
14319static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
14320{
14321 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14322 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
14323 if (chip_irq == 13)
14324 chip_irq = 15;
14325 return chip_irq;
14326}
14327
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014328static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
14329{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014330 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014331 PortAddr iop_base = _asc_def_iop_base[id];
14332 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014333 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014334
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014335 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014336 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
14337 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014338 return -ENODEV;
14339 }
14340 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014341 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014342 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014343 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014344 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014345
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014346 err = -ENOMEM;
14347 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014348 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014349 goto release_region;
14350
14351 board = ASC_BOARDP(shost);
14352 board->irq = advansys_isa_irq_no(iop_base);
14353 board->dev = dev;
14354
14355 err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
14356 if (err)
14357 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014358
14359 dev_set_drvdata(dev, shost);
14360 return 0;
14361
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014362 free_host:
14363 scsi_host_put(shost);
14364 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014365 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014366 return err;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014367}
14368
14369static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
14370{
Matthew Wilcox71f36112007-07-30 08:04:53 -060014371 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014372 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014373 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014374 return 0;
14375}
14376
14377static struct isa_driver advansys_isa_driver = {
14378 .probe = advansys_isa_probe,
14379 .remove = __devexit_p(advansys_isa_remove),
14380 .driver = {
14381 .owner = THIS_MODULE,
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014382 .name = DRV_NAME,
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014383 },
14384};
14385
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014386/*
14387 * The VLB IRQ number is found in bits 2 to 4 of the CfgLsw. It decodes as:
14388 * 000: invalid
14389 * 001: 10
14390 * 010: 11
14391 * 011: 12
14392 * 100: invalid
14393 * 101: 14
14394 * 110: 15
14395 * 111: invalid
14396 */
14397static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
14398{
14399 unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
14400 unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
14401 if ((chip_irq < 10) || (chip_irq == 13) || (chip_irq > 15))
14402 return 0;
14403 return chip_irq;
14404}
14405
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014406static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
14407{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014408 int err = -ENODEV;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014409 PortAddr iop_base = _asc_def_iop_base[id];
14410 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014411 struct asc_board *board;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014412
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014413 if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014414 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
14415 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014416 return -ENODEV;
14417 }
14418 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014419 if (!AscFindSignature(iop_base))
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014420 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014421 /*
14422 * I don't think this condition can actually happen, but the old
14423 * driver did it, and the chances of finding a VLB setup in 2007
14424 * to do testing with is slight to none.
14425 */
14426 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014427 goto release_region;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014428
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014429 err = -ENOMEM;
14430 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014431 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014432 goto release_region;
14433
14434 board = ASC_BOARDP(shost);
14435 board->irq = advansys_vlb_irq_no(iop_base);
14436 board->dev = dev;
14437
14438 err = advansys_board_found(shost, iop_base, ASC_IS_VL);
14439 if (err)
14440 goto free_host;
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014441
14442 dev_set_drvdata(dev, shost);
14443 return 0;
14444
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014445 free_host:
14446 scsi_host_put(shost);
14447 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014448 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014449 return -ENODEV;
14450}
14451
14452static struct isa_driver advansys_vlb_driver = {
14453 .probe = advansys_vlb_probe,
14454 .remove = __devexit_p(advansys_isa_remove),
14455 .driver = {
14456 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060014457 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014458 },
14459};
14460
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014461static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
14462 { "ABP7401" },
14463 { "ABP7501" },
14464 { "" }
14465};
14466
14467MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
14468
14469/*
14470 * EISA is a little more tricky than PCI; each EISA device may have two
14471 * channels, and this driver is written to make each channel its own Scsi_Host
14472 */
14473struct eisa_scsi_data {
14474 struct Scsi_Host *host[2];
14475};
14476
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014477/*
14478 * The EISA IRQ number is found in bits 8 to 10 of the CfgLsw. It decodes as:
14479 * 000: 10
14480 * 001: 11
14481 * 010: 12
14482 * 011: invalid
14483 * 100: 14
14484 * 101: 15
14485 * 110: invalid
14486 * 111: invalid
14487 */
14488static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
14489{
14490 unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
14491 unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
14492 if ((chip_irq == 13) || (chip_irq > 15))
14493 return 0;
14494 return chip_irq;
14495}
14496
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014497static int __devinit advansys_eisa_probe(struct device *dev)
14498{
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014499 int i, ioport, irq = 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014500 int err;
14501 struct eisa_device *edev = to_eisa_device(dev);
14502 struct eisa_scsi_data *data;
14503
14504 err = -ENOMEM;
14505 data = kzalloc(sizeof(*data), GFP_KERNEL);
14506 if (!data)
14507 goto fail;
14508 ioport = edev->base_addr + 0xc30;
14509
14510 err = -ENODEV;
14511 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014512 struct asc_board *board;
14513 struct Scsi_Host *shost;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014514 if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014515 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
14516 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014517 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014518 }
14519 if (!AscFindSignature(ioport)) {
14520 release_region(ioport, ASC_IOADR_GAP);
14521 continue;
14522 }
14523
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014524 /*
14525 * I don't know why we need to do this for EISA chips, but
14526 * not for any others. It looks to be equivalent to
14527 * AscGetChipCfgMsw, but I may have overlooked something,
14528 * so I'm not converting it until I get an EISA board to
14529 * test with.
14530 */
14531 inw(ioport + 4);
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014532
14533 if (!irq)
14534 irq = advansys_eisa_irq_no(edev);
14535
14536 err = -ENOMEM;
14537 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
14538 if (!shost)
14539 goto release_region;
14540
14541 board = ASC_BOARDP(shost);
14542 board->irq = irq;
14543 board->dev = dev;
14544
14545 err = advansys_board_found(shost, ioport, ASC_IS_EISA);
14546 if (!err) {
14547 data->host[i] = shost;
14548 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014549 }
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014550
14551 scsi_host_put(shost);
14552 release_region:
14553 release_region(ioport, ASC_IOADR_GAP);
14554 break;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014555 }
14556
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014557 if (err)
14558 goto free_data;
14559 dev_set_drvdata(dev, data);
14560 return 0;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014561
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014562 free_data:
14563 kfree(data->host[0]);
14564 kfree(data->host[1]);
14565 kfree(data);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014566 fail:
14567 return err;
14568}
14569
14570static __devexit int advansys_eisa_remove(struct device *dev)
14571{
14572 int i;
14573 struct eisa_scsi_data *data = dev_get_drvdata(dev);
14574
14575 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060014576 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014577 struct Scsi_Host *shost = data->host[i];
14578 if (!shost)
14579 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060014580 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014581 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014582 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014583 }
14584
14585 kfree(data);
14586 return 0;
14587}
14588
14589static struct eisa_driver advansys_eisa_driver = {
14590 .id_table = advansys_eisa_table,
14591 .driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014592 .name = DRV_NAME,
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014593 .probe = advansys_eisa_probe,
14594 .remove = __devexit_p(advansys_eisa_remove),
14595 }
14596};
14597
Dave Jones2672ea82006-08-02 17:11:49 -040014598/* PCI Devices supported by this driver */
14599static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014600 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
14601 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14602 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
14603 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14604 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
14605 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14606 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
14607 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14608 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
14609 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14610 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
14611 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
14612 {}
Dave Jones2672ea82006-08-02 17:11:49 -040014613};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014614
Dave Jones2672ea82006-08-02 17:11:49 -040014615MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014616
Matthew Wilcox9649af32007-07-26 21:51:47 -060014617static void __devinit advansys_set_latency(struct pci_dev *pdev)
14618{
14619 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
14620 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
14621 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
14622 } else {
14623 u8 latency;
14624 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
14625 if (latency < 0x20)
14626 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
14627 }
14628}
14629
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014630static int __devinit
14631advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14632{
14633 int err, ioport;
14634 struct Scsi_Host *shost;
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014635 struct asc_board *board;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014636
14637 err = pci_enable_device(pdev);
14638 if (err)
14639 goto fail;
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014640 err = pci_request_regions(pdev, DRV_NAME);
Matthew Wilcox71f36112007-07-30 08:04:53 -060014641 if (err)
14642 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060014643 pci_set_master(pdev);
14644 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014645
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014646 err = -ENODEV;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014647 if (pci_resource_len(pdev, 0) == 0)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014648 goto release_region;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014649
14650 ioport = pci_resource_start(pdev, 0);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014651
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014652 err = -ENOMEM;
14653 shost = scsi_host_alloc(&advansys_template, sizeof(*board));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014654 if (!shost)
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014655 goto release_region;
14656
14657 board = ASC_BOARDP(shost);
14658 board->irq = pdev->irq;
14659 board->dev = &pdev->dev;
14660
14661 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14662 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14663 pdev->device == PCI_DEVICE_ID_38C1600_REV1) {
14664 board->flags |= ASC_IS_WIDE_BOARD;
14665 }
14666
14667 err = advansys_board_found(shost, ioport, ASC_IS_PCI);
14668 if (err)
14669 goto free_host;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014670
14671 pci_set_drvdata(pdev, shost);
14672 return 0;
14673
Matthew Wilcoxd361db42007-10-02 21:55:29 -040014674 free_host:
14675 scsi_host_put(shost);
14676 release_region:
Matthew Wilcox71f36112007-07-30 08:04:53 -060014677 pci_release_regions(pdev);
14678 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014679 pci_disable_device(pdev);
14680 fail:
14681 return err;
14682}
14683
14684static void __devexit advansys_pci_remove(struct pci_dev *pdev)
14685{
14686 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060014687 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014688 pci_disable_device(pdev);
14689}
14690
14691static struct pci_driver advansys_pci_driver = {
Matthew Wilcox01fbfe02007-09-09 08:56:40 -060014692 .name = DRV_NAME,
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014693 .id_table = advansys_pci_tbl,
14694 .probe = advansys_pci_probe,
14695 .remove = __devexit_p(advansys_pci_remove),
14696};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014697
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014698static int __init advansys_init(void)
14699{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014700 int error;
14701
14702 error = isa_register_driver(&advansys_isa_driver,
14703 ASC_IOADR_TABLE_MAX_IX);
14704 if (error)
14705 goto fail;
14706
14707 error = isa_register_driver(&advansys_vlb_driver,
14708 ASC_IOADR_TABLE_MAX_IX);
14709 if (error)
14710 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014711
14712 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014713 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014714 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014715
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014716 error = pci_register_driver(&advansys_pci_driver);
14717 if (error)
14718 goto unregister_eisa;
14719
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014720 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014721
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014722 unregister_eisa:
14723 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014724 unregister_vlb:
14725 isa_unregister_driver(&advansys_vlb_driver);
14726 unregister_isa:
14727 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014728 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014729 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014730}
14731
14732static void __exit advansys_exit(void)
14733{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014734 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060014735 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014736 isa_unregister_driver(&advansys_vlb_driver);
14737 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014738}
14739
14740module_init(advansys_init);
14741module_exit(advansys_exit);
14742
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040014743MODULE_LICENSE("GPL");