blob: 90f05c52be7ef04d33e2af71304191fbf164da0f [file] [log] [blame]
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04001#define ASC_VERSION "3.4" /* AdvanSys Driver Version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3/*
4 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
5 *
6 * Copyright (c) 1995-2000 Advanced System Products, Inc.
7 * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -04008 * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * All Rights Reserved.
10 *
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
19 * changed its name to ConnectCom Solutions, Inc.
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040020 * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 */
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/string.h>
25#include <linux/kernel.h>
26#include <linux/types.h>
27#include <linux/ioport.h>
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <linux/slab.h>
31#include <linux/mm.h>
32#include <linux/proc_fs.h>
33#include <linux/init.h>
34#include <linux/blkdev.h>
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060035#include <linux/isa.h>
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060036#include <linux/eisa.h>
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040037#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/spinlock.h>
39#include <linux/dma-mapping.h>
40
41#include <asm/io.h>
42#include <asm/system.h>
43#include <asm/dma.h>
44
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040045#include <scsi/scsi_cmnd.h>
46#include <scsi/scsi_device.h>
47#include <scsi/scsi_tcq.h>
48#include <scsi/scsi.h>
49#include <scsi/scsi_host.h>
50
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060051/* FIXME:
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 *
Matthew Wilcox4bd6d7f2007-07-30 08:41:03 -060053 * 1. Although all of the necessary command mapping places have the
54 * appropriate dma_map.. APIs, the driver still processes its internal
55 * queue using bus_to_virt() and virt_to_bus() which are illegal under
56 * the API. The entire queue processing structure will need to be
57 * altered to fix this.
58 * 2. Need to add memory mapping workaround. Test the memory mapping.
59 * If it doesn't work revert to I/O port access. Can a test be done
60 * safely?
61 * 3. Handle an interrupt not working. Keep an interrupt counter in
62 * the interrupt handler. In the timeout function if the interrupt
63 * has not occurred then print a message and run in polled mode.
64 * 4. Need to add support for target mode commands, cf. CAM XPT.
65 * 5. check DMA mapping functions for failure
66 * 6. Remove internal queueing
67 * 7. Use scsi_transport_spi
68 * 8. advansys_info is not safe against multiple simultaneous callers
69 * 9. Kill boardp->id
70 * 10. 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 assertions. */
75#define ADVANSYS_ASSERT
76
77/* Enable driver /proc statistics. */
78#define ADVANSYS_STATS
79
80/* Enable driver tracing. */
81/* #define ADVANSYS_DEBUG */
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083/*
84 * --- Asc Library Constants and Macros
85 */
86
87#define ASC_LIB_VERSION_MAJOR 1
88#define ASC_LIB_VERSION_MINOR 24
89#define ASC_LIB_SERIAL_NUMBER 123
90
91/*
92 * Portable Data Types
93 *
94 * Any instance where a 32-bit long or pointer type is assumed
95 * for precision or HW defined structures, the following define
96 * types must be used. In Linux the char, short, and int types
97 * are all consistent at 8, 16, and 32 bits respectively. Pointers
98 * and long types are 64 bits on Alpha and UltraSPARC.
99 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400100#define ASC_PADDR __u32 /* Physical/Bus address data type. */
101#define ASC_VADDR __u32 /* Virtual address data type. */
102#define ASC_DCNT __u32 /* Unsigned Data count type. */
103#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105/*
106 * These macros are used to convert a virtual address to a
107 * 32-bit value. This currently can be used on Linux Alpha
108 * which uses 64-bit virtual address but a 32-bit bus address.
109 * This is likely to break in the future, but doing this now
110 * will give us time to change the HW and FW to handle 64-bit
111 * addresses.
112 */
113#define ASC_VADDR_TO_U32 virt_to_bus
114#define ASC_U32_TO_VADDR bus_to_virt
115
116typedef unsigned char uchar;
117
118#ifndef TRUE
119#define TRUE (1)
120#endif
121#ifndef FALSE
122#define FALSE (0)
123#endif
124
125#define EOF (-1)
126#define ERR (-1)
127#define UW_ERR (uint)(0xFFFF)
128#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
130#define ASC_DVCLIB_CALL_DONE (1)
131#define ASC_DVCLIB_CALL_FAILED (0)
132#define ASC_DVCLIB_CALL_ERROR (-1)
133
Dave Jones2672ea82006-08-02 17:11:49 -0400134#define PCI_VENDOR_ID_ASP 0x10cd
135#define PCI_DEVICE_ID_ASP_1200A 0x1100
136#define PCI_DEVICE_ID_ASP_ABP940 0x1200
137#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
138#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
139#define PCI_DEVICE_ID_38C0800_REV1 0x2500
140#define PCI_DEVICE_ID_38C1600_REV1 0x2700
141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142/*
143 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
144 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
145 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
146 * SRB structure.
147 */
148#define CC_VERY_LONG_SG_LIST 0
149#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
150
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400151#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152#define inp(port) inb(port)
153#define outp(port, byte) outb((byte), (port))
154
155#define inpw(port) inw(port)
156#define outpw(port, word) outw((word), (port))
157
158#define ASC_MAX_SG_QUEUE 7
159#define ASC_MAX_SG_LIST 255
160
161#define ASC_CS_TYPE unsigned short
162
163#define ASC_IS_ISA (0x0001)
164#define ASC_IS_ISAPNP (0x0081)
165#define ASC_IS_EISA (0x0002)
166#define ASC_IS_PCI (0x0004)
167#define ASC_IS_PCI_ULTRA (0x0104)
168#define ASC_IS_PCMCIA (0x0008)
169#define ASC_IS_MCA (0x0020)
170#define ASC_IS_VL (0x0040)
171#define ASC_ISA_PNP_PORT_ADDR (0x279)
172#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
173#define ASC_IS_WIDESCSI_16 (0x0100)
174#define ASC_IS_WIDESCSI_32 (0x0200)
175#define ASC_IS_BIG_ENDIAN (0x8000)
176#define ASC_CHIP_MIN_VER_VL (0x01)
177#define ASC_CHIP_MAX_VER_VL (0x07)
178#define ASC_CHIP_MIN_VER_PCI (0x09)
179#define ASC_CHIP_MAX_VER_PCI (0x0F)
180#define ASC_CHIP_VER_PCI_BIT (0x08)
181#define ASC_CHIP_MIN_VER_ISA (0x11)
182#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
183#define ASC_CHIP_MAX_VER_ISA (0x27)
184#define ASC_CHIP_VER_ISA_BIT (0x30)
185#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
186#define ASC_CHIP_VER_ASYN_BUG (0x21)
187#define ASC_CHIP_VER_PCI 0x08
188#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
189#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
190#define ASC_CHIP_MIN_VER_EISA (0x41)
191#define ASC_CHIP_MAX_VER_EISA (0x47)
192#define ASC_CHIP_VER_EISA_BIT (0x40)
193#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
194#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
195#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
196#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
197#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
198#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
199#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
200#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
201#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
202#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
203#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
204
205#define ASC_SCSI_ID_BITS 3
206#define ASC_SCSI_TIX_TYPE uchar
207#define ASC_ALL_DEVICE_BIT_SET 0xFF
208#define ASC_SCSI_BIT_ID_TYPE uchar
209#define ASC_MAX_TID 7
210#define ASC_MAX_LUN 7
211#define ASC_SCSI_WIDTH_BIT_SET 0xFF
212#define ASC_MAX_SENSE_LEN 32
213#define ASC_MIN_SENSE_LEN 14
214#define ASC_MAX_CDB_LEN 12
215#define ASC_SCSI_RESET_HOLD_TIME_US 60
216
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217/*
218 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
219 * and CmdDt (Command Support Data) field bit definitions.
220 */
221#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
222#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
223#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
224#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
225
226#define ASC_SCSIDIR_NOCHK 0x00
227#define ASC_SCSIDIR_T2H 0x08
228#define ASC_SCSIDIR_H2T 0x10
229#define ASC_SCSIDIR_NODATA 0x18
230#define SCSI_ASC_NOMEDIA 0x3A
231#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
232#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
233#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
234#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
238#define ASC_SG_LIST_PER_Q 7
239#define QS_FREE 0x00
240#define QS_READY 0x01
241#define QS_DISC1 0x02
242#define QS_DISC2 0x04
243#define QS_BUSY 0x08
244#define QS_ABORTED 0x40
245#define QS_DONE 0x80
246#define QC_NO_CALLBACK 0x01
247#define QC_SG_SWAP_QUEUE 0x02
248#define QC_SG_HEAD 0x04
249#define QC_DATA_IN 0x08
250#define QC_DATA_OUT 0x10
251#define QC_URGENT 0x20
252#define QC_MSG_OUT 0x40
253#define QC_REQ_SENSE 0x80
254#define QCSG_SG_XFER_LIST 0x02
255#define QCSG_SG_XFER_MORE 0x04
256#define QCSG_SG_XFER_END 0x08
257#define QD_IN_PROGRESS 0x00
258#define QD_NO_ERROR 0x01
259#define QD_ABORTED_BY_HOST 0x02
260#define QD_WITH_ERROR 0x04
261#define QD_INVALID_REQUEST 0x80
262#define QD_INVALID_HOST_NUM 0x81
263#define QD_INVALID_DEVICE 0x82
264#define QD_ERR_INTERNAL 0xFF
265#define QHSTA_NO_ERROR 0x00
266#define QHSTA_M_SEL_TIMEOUT 0x11
267#define QHSTA_M_DATA_OVER_RUN 0x12
268#define QHSTA_M_DATA_UNDER_RUN 0x12
269#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
270#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
271#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
272#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
273#define QHSTA_D_HOST_ABORT_FAILED 0x23
274#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
275#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
276#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
277#define QHSTA_M_WTM_TIMEOUT 0x41
278#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
279#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
280#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
281#define QHSTA_M_TARGET_STATUS_BUSY 0x45
282#define QHSTA_M_BAD_TAG_CODE 0x46
283#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
284#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
285#define QHSTA_D_LRAM_CMP_ERROR 0x81
286#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
287#define ASC_FLAG_SCSIQ_REQ 0x01
288#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
289#define ASC_FLAG_BIOS_ASYNC_IO 0x04
290#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
291#define ASC_FLAG_WIN16 0x10
292#define ASC_FLAG_WIN32 0x20
293#define ASC_FLAG_ISA_OVER_16MB 0x40
294#define ASC_FLAG_DOS_VM_CALLBACK 0x80
295#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
296#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
297#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
298#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
299#define ASC_SCSIQ_CPY_BEG 4
300#define ASC_SCSIQ_SGHD_CPY_BEG 2
301#define ASC_SCSIQ_B_FWD 0
302#define ASC_SCSIQ_B_BWD 1
303#define ASC_SCSIQ_B_STATUS 2
304#define ASC_SCSIQ_B_QNO 3
305#define ASC_SCSIQ_B_CNTL 4
306#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
307#define ASC_SCSIQ_D_DATA_ADDR 8
308#define ASC_SCSIQ_D_DATA_CNT 12
309#define ASC_SCSIQ_B_SENSE_LEN 20
310#define ASC_SCSIQ_DONE_INFO_BEG 22
311#define ASC_SCSIQ_D_SRBPTR 22
312#define ASC_SCSIQ_B_TARGET_IX 26
313#define ASC_SCSIQ_B_CDB_LEN 28
314#define ASC_SCSIQ_B_TAG_CODE 29
315#define ASC_SCSIQ_W_VM_ID 30
316#define ASC_SCSIQ_DONE_STATUS 32
317#define ASC_SCSIQ_HOST_STATUS 33
318#define ASC_SCSIQ_SCSI_STATUS 34
319#define ASC_SCSIQ_CDB_BEG 36
320#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
321#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
322#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
323#define ASC_SCSIQ_B_SG_WK_QP 49
324#define ASC_SCSIQ_B_SG_WK_IX 50
325#define ASC_SCSIQ_W_ALT_DC1 52
326#define ASC_SCSIQ_B_LIST_CNT 6
327#define ASC_SCSIQ_B_CUR_LIST_CNT 7
328#define ASC_SGQ_B_SG_CNTL 4
329#define ASC_SGQ_B_SG_HEAD_QP 5
330#define ASC_SGQ_B_SG_LIST_CNT 6
331#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
332#define ASC_SGQ_LIST_BEG 8
333#define ASC_DEF_SCSI1_QNG 4
334#define ASC_MAX_SCSI1_QNG 4
335#define ASC_DEF_SCSI2_QNG 16
336#define ASC_MAX_SCSI2_QNG 32
337#define ASC_TAG_CODE_MASK 0x23
338#define ASC_STOP_REQ_RISC_STOP 0x01
339#define ASC_STOP_ACK_RISC_STOP 0x03
340#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
341#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
342#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
343#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
344#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
345#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
346#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
347#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
348#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
349#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
350
351typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400352 uchar status;
353 uchar q_no;
354 uchar cntl;
355 uchar sg_queue_cnt;
356 uchar target_id;
357 uchar target_lun;
358 ASC_PADDR data_addr;
359 ASC_DCNT data_cnt;
360 ASC_PADDR sense_addr;
361 uchar sense_len;
362 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363} ASC_SCSIQ_1;
364
365typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400366 ASC_VADDR srb_ptr;
367 uchar target_ix;
368 uchar flag;
369 uchar cdb_len;
370 uchar tag_code;
371 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372} ASC_SCSIQ_2;
373
374typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400375 uchar done_stat;
376 uchar host_stat;
377 uchar scsi_stat;
378 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379} ASC_SCSIQ_3;
380
381typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400382 uchar cdb[ASC_MAX_CDB_LEN];
383 uchar y_first_sg_list_qp;
384 uchar y_working_sg_qp;
385 uchar y_working_sg_ix;
386 uchar y_res;
387 ushort x_req_count;
388 ushort x_reconnect_rtn;
389 ASC_PADDR x_saved_data_addr;
390 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391} ASC_SCSIQ_4;
392
393typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400394 ASC_SCSIQ_2 d2;
395 ASC_SCSIQ_3 d3;
396 uchar q_status;
397 uchar q_no;
398 uchar cntl;
399 uchar sense_len;
400 uchar extra_bytes;
401 uchar res;
402 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403} ASC_QDONE_INFO;
404
405typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400406 ASC_PADDR addr;
407 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408} ASC_SG_LIST;
409
410typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400411 ushort entry_cnt;
412 ushort queue_cnt;
413 ushort entry_to_copy;
414 ushort res;
415 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416} ASC_SG_HEAD;
417
418#define ASC_MIN_SG_LIST 2
419
420typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400421 ushort entry_cnt;
422 ushort queue_cnt;
423 ushort entry_to_copy;
424 ushort res;
425 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426} ASC_MIN_SG_HEAD;
427
428#define QCX_SORT (0x0001)
429#define QCX_COALEASE (0x0002)
430
431typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400432 ASC_SCSIQ_1 q1;
433 ASC_SCSIQ_2 q2;
434 uchar *cdbptr;
435 ASC_SG_HEAD *sg_head;
436 ushort remain_sg_entry_cnt;
437 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438} ASC_SCSI_Q;
439
440typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400441 ASC_SCSIQ_1 r1;
442 ASC_SCSIQ_2 r2;
443 uchar *cdbptr;
444 ASC_SG_HEAD *sg_head;
445 uchar *sense_ptr;
446 ASC_SCSIQ_3 r3;
447 uchar cdb[ASC_MAX_CDB_LEN];
448 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449} ASC_SCSI_REQ_Q;
450
451typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400452 ASC_SCSIQ_1 r1;
453 ASC_SCSIQ_2 r2;
454 uchar *cdbptr;
455 ASC_SG_HEAD *sg_head;
456 uchar *sense_ptr;
457 ASC_SCSIQ_3 r3;
458 uchar cdb[ASC_MAX_CDB_LEN];
459 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460} ASC_SCSI_BIOS_REQ_Q;
461
462typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400463 uchar fwd;
464 uchar bwd;
465 ASC_SCSIQ_1 i1;
466 ASC_SCSIQ_2 i2;
467 ASC_SCSIQ_3 i3;
468 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469} ASC_RISC_Q;
470
471typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400472 uchar seq_no;
473 uchar q_no;
474 uchar cntl;
475 uchar sg_head_qp;
476 uchar sg_list_cnt;
477 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478} ASC_SG_LIST_Q;
479
480typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400481 uchar fwd;
482 uchar bwd;
483 ASC_SG_LIST_Q sg;
484 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485} ASC_RISC_SG_LIST_Q;
486
487#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
488#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
489#define ASCQ_ERR_NO_ERROR 0
490#define ASCQ_ERR_IO_NOT_FOUND 1
491#define ASCQ_ERR_LOCAL_MEM 2
492#define ASCQ_ERR_CHKSUM 3
493#define ASCQ_ERR_START_CHIP 4
494#define ASCQ_ERR_INT_TARGET_ID 5
495#define ASCQ_ERR_INT_LOCAL_MEM 6
496#define ASCQ_ERR_HALT_RISC 7
497#define ASCQ_ERR_GET_ASPI_ENTRY 8
498#define ASCQ_ERR_CLOSE_ASPI 9
499#define ASCQ_ERR_HOST_INQUIRY 0x0A
500#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
501#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
502#define ASCQ_ERR_Q_STATUS 0x0D
503#define ASCQ_ERR_WR_SCSIQ 0x0E
504#define ASCQ_ERR_PC_ADDR 0x0F
505#define ASCQ_ERR_SYN_OFFSET 0x10
506#define ASCQ_ERR_SYN_XFER_TIME 0x11
507#define ASCQ_ERR_LOCK_DMA 0x12
508#define ASCQ_ERR_UNLOCK_DMA 0x13
509#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
510#define ASCQ_ERR_MICRO_CODE_HALT 0x15
511#define ASCQ_ERR_SET_LRAM_ADDR 0x16
512#define ASCQ_ERR_CUR_QNG 0x17
513#define ASCQ_ERR_SG_Q_LINKS 0x18
514#define ASCQ_ERR_SCSIQ_PTR 0x19
515#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
516#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
517#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
518#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
519#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
520#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
521#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
522#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
523#define ASCQ_ERR_SEND_SCSI_Q 0x22
524#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
525#define ASCQ_ERR_RESET_SDTR 0x24
526
527/*
528 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
529 */
530#define ASC_WARN_NO_ERROR 0x0000
531#define ASC_WARN_IO_PORT_ROTATE 0x0001
532#define ASC_WARN_EEPROM_CHKSUM 0x0002
533#define ASC_WARN_IRQ_MODIFIED 0x0004
534#define ASC_WARN_AUTO_CONFIG 0x0008
535#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
536#define ASC_WARN_EEPROM_RECOVER 0x0020
537#define ASC_WARN_CFG_MSW_RECOVER 0x0040
538#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
539
540/*
541 * Error code values are set in ASC_DVC_VAR 'err_code'.
542 */
543#define ASC_IERR_WRITE_EEPROM 0x0001
544#define ASC_IERR_MCODE_CHKSUM 0x0002
545#define ASC_IERR_SET_PC_ADDR 0x0004
546#define ASC_IERR_START_STOP_CHIP 0x0008
547#define ASC_IERR_IRQ_NO 0x0010
548#define ASC_IERR_SET_IRQ_NO 0x0020
549#define ASC_IERR_CHIP_VERSION 0x0040
550#define ASC_IERR_SET_SCSI_ID 0x0080
551#define ASC_IERR_GET_PHY_ADDR 0x0100
552#define ASC_IERR_BAD_SIGNATURE 0x0200
553#define ASC_IERR_NO_BUS_TYPE 0x0400
554#define ASC_IERR_SCAM 0x0800
555#define ASC_IERR_SET_SDTR 0x1000
556#define ASC_IERR_RW_LRAM 0x8000
557
558#define ASC_DEF_IRQ_NO 10
559#define ASC_MAX_IRQ_NO 15
560#define ASC_MIN_IRQ_NO 10
561#define ASC_MIN_REMAIN_Q (0x02)
562#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
563#define ASC_MIN_TAG_Q_PER_DVC (0x04)
564#define ASC_DEF_TAG_Q_PER_DVC (0x04)
565#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
566#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
567#define ASC_MAX_TOTAL_QNG 240
568#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
569#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
570#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
571#define ASC_MAX_INRAM_TAG_QNG 16
572#define ASC_IOADR_TABLE_MAX_IX 11
573#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574#define ASC_LIB_SCSIQ_WK_SP 256
575#define ASC_MAX_SYN_XFER_NO 16
576#define ASC_SYN_MAX_OFFSET 0x0F
577#define ASC_DEF_SDTR_OFFSET 0x0F
578#define ASC_DEF_SDTR_INDEX 0x00
579#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
580#define SYN_XFER_NS_0 25
581#define SYN_XFER_NS_1 30
582#define SYN_XFER_NS_2 35
583#define SYN_XFER_NS_3 40
584#define SYN_XFER_NS_4 50
585#define SYN_XFER_NS_5 60
586#define SYN_XFER_NS_6 70
587#define SYN_XFER_NS_7 85
588#define SYN_ULTRA_XFER_NS_0 12
589#define SYN_ULTRA_XFER_NS_1 19
590#define SYN_ULTRA_XFER_NS_2 25
591#define SYN_ULTRA_XFER_NS_3 32
592#define SYN_ULTRA_XFER_NS_4 38
593#define SYN_ULTRA_XFER_NS_5 44
594#define SYN_ULTRA_XFER_NS_6 50
595#define SYN_ULTRA_XFER_NS_7 57
596#define SYN_ULTRA_XFER_NS_8 63
597#define SYN_ULTRA_XFER_NS_9 69
598#define SYN_ULTRA_XFER_NS_10 75
599#define SYN_ULTRA_XFER_NS_11 82
600#define SYN_ULTRA_XFER_NS_12 88
601#define SYN_ULTRA_XFER_NS_13 94
602#define SYN_ULTRA_XFER_NS_14 100
603#define SYN_ULTRA_XFER_NS_15 107
604
605typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400606 uchar msg_type;
607 uchar msg_len;
608 uchar msg_req;
609 union {
610 struct {
611 uchar sdtr_xfer_period;
612 uchar sdtr_req_ack_offset;
613 } sdtr;
614 struct {
615 uchar wdtr_width;
616 } wdtr;
617 struct {
618 uchar mdp_b3;
619 uchar mdp_b2;
620 uchar mdp_b1;
621 uchar mdp_b0;
622 } mdp;
623 } u_ext_msg;
624 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625} EXT_MSG;
626
627#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
628#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
629#define wdtr_width u_ext_msg.wdtr.wdtr_width
630#define mdp_b3 u_ext_msg.mdp_b3
631#define mdp_b2 u_ext_msg.mdp_b2
632#define mdp_b1 u_ext_msg.mdp_b1
633#define mdp_b0 u_ext_msg.mdp_b0
634
635typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400636 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
637 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
638 ASC_SCSI_BIT_ID_TYPE disc_enable;
639 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
640 uchar chip_scsi_id;
641 uchar isa_dma_speed;
642 uchar isa_dma_channel;
643 uchar chip_version;
644 ushort lib_serial_no;
645 ushort lib_version;
646 ushort mcode_date;
647 ushort mcode_version;
648 uchar max_tag_qng[ASC_MAX_TID + 1];
649 uchar *overrun_buf;
650 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400651 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652} ASC_DVC_CFG;
653
654#define ASC_DEF_DVC_CNTL 0xFFFF
655#define ASC_DEF_CHIP_SCSI_ID 7
656#define ASC_DEF_ISA_DMA_SPEED 4
657#define ASC_INIT_STATE_NULL 0x0000
658#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
659#define ASC_INIT_STATE_END_GET_CFG 0x0002
660#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
661#define ASC_INIT_STATE_END_SET_CFG 0x0008
662#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
663#define ASC_INIT_STATE_END_LOAD_MC 0x0020
664#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
665#define ASC_INIT_STATE_END_INQUIRY 0x0080
666#define ASC_INIT_RESET_SCSI_DONE 0x0100
667#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
669#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
670#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
671#define ASC_MIN_TAGGED_CMD 7
672#define ASC_MAX_SCSI_RESET_WAIT 30
673
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400674struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400677 PortAddr iop_base;
678 ushort err_code;
679 ushort dvc_cntl;
680 ushort bug_fix_cntl;
681 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400682 ASC_SCSI_BIT_ID_TYPE init_sdtr;
683 ASC_SCSI_BIT_ID_TYPE sdtr_done;
684 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
685 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
686 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
687 ASC_SCSI_BIT_ID_TYPE start_motor;
688 uchar scsi_reset_wait;
689 uchar chip_no;
690 char is_in_int;
691 uchar max_total_qng;
692 uchar cur_total_qng;
693 uchar in_critical_cnt;
694 uchar irq_no;
695 uchar last_q_shortage;
696 ushort init_state;
697 uchar cur_dvc_qng[ASC_MAX_TID + 1];
698 uchar max_dvc_qng[ASC_MAX_TID + 1];
699 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
700 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
701 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
702 ASC_DVC_CFG *cfg;
703 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
704 char redo_scam;
705 ushort res2;
706 uchar dos_int13_table[ASC_MAX_TID + 1];
707 ASC_DCNT max_dma_count;
708 ASC_SCSI_BIT_ID_TYPE no_scam;
709 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
710 uchar max_sdtr_index;
711 uchar host_init_sdtr_index;
712 struct asc_board *drv_ptr;
713 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714} ASC_DVC_VAR;
715
716typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400717 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718} ASC_DVC_INQ_INFO;
719
720typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400721 ASC_DCNT lba;
722 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723} ASC_CAP_INFO;
724
725typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400726 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727} ASC_CAP_INFO_ARRAY;
728
729#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
730#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
731#define ASC_CNTL_INITIATOR (ushort)0x0001
732#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
733#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
734#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
735#define ASC_CNTL_NO_SCAM (ushort)0x0010
736#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
737#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
738#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
739#define ASC_CNTL_RESET_SCSI (ushort)0x0200
740#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
741#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
742#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
743#define ASC_CNTL_BURST_MODE (ushort)0x2000
744#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
745#define ASC_EEP_DVC_CFG_BEG_VL 2
746#define ASC_EEP_MAX_DVC_ADDR_VL 15
747#define ASC_EEP_DVC_CFG_BEG 32
748#define ASC_EEP_MAX_DVC_ADDR 45
749#define ASC_EEP_DEFINED_WORDS 10
750#define ASC_EEP_MAX_ADDR 63
751#define ASC_EEP_RES_WORDS 0
752#define ASC_EEP_MAX_RETRY 20
753#define ASC_MAX_INIT_BUSY_RETRY 8
754#define ASC_EEP_ISA_PNP_WSIZE 16
755
756/*
757 * These macros keep the chip SCSI id and ISA DMA speed
758 * bitfields in board order. C bitfields aren't portable
759 * between big and little-endian platforms so they are
760 * not used.
761 */
762
763#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
764#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
765#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
766 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
767#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
768 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
769
770typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400771 ushort cfg_lsw;
772 ushort cfg_msw;
773 uchar init_sdtr;
774 uchar disc_enable;
775 uchar use_cmd_qng;
776 uchar start_motor;
777 uchar max_total_qng;
778 uchar max_tag_qng;
779 uchar bios_scan;
780 uchar power_up_wait;
781 uchar no_scam;
782 uchar id_speed; /* low order 4 bits is chip scsi id */
783 /* high order 4 bits is isa dma speed */
784 uchar dos_int13_table[ASC_MAX_TID + 1];
785 uchar adapter_info[6];
786 ushort cntl;
787 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788} ASCEEP_CONFIG;
789
790#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
791#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
792#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
793
794#define ASC_EEP_CMD_READ 0x80
795#define ASC_EEP_CMD_WRITE 0x40
796#define ASC_EEP_CMD_WRITE_ABLE 0x30
797#define ASC_EEP_CMD_WRITE_DISABLE 0x00
798#define ASC_OVERRUN_BSIZE 0x00000048UL
799#define ASC_CTRL_BREAK_ONCE 0x0001
800#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
801#define ASCV_MSGOUT_BEG 0x0000
802#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
803#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
804#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
805#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
806#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
807#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
808#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
809#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
810#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
811#define ASCV_BREAK_ADDR (ushort)0x0028
812#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
813#define ASCV_BREAK_CONTROL (ushort)0x002C
814#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
815
816#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
817#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
818#define ASCV_MCODE_SIZE_W (ushort)0x0034
819#define ASCV_STOP_CODE_B (ushort)0x0036
820#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
821#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
822#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
823#define ASCV_HALTCODE_W (ushort)0x0040
824#define ASCV_CHKSUM_W (ushort)0x0042
825#define ASCV_MC_DATE_W (ushort)0x0044
826#define ASCV_MC_VER_W (ushort)0x0046
827#define ASCV_NEXTRDY_B (ushort)0x0048
828#define ASCV_DONENEXT_B (ushort)0x0049
829#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
830#define ASCV_SCSIBUSY_B (ushort)0x004B
831#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
832#define ASCV_CURCDB_B (ushort)0x004D
833#define ASCV_RCLUN_B (ushort)0x004E
834#define ASCV_BUSY_QHEAD_B (ushort)0x004F
835#define ASCV_DISC1_QHEAD_B (ushort)0x0050
836#define ASCV_DISC_ENABLE_B (ushort)0x0052
837#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
838#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
839#define ASCV_MCODE_CNTL_B (ushort)0x0056
840#define ASCV_NULL_TARGET_B (ushort)0x0057
841#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
842#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
843#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
844#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
845#define ASCV_HOST_FLAG_B (ushort)0x005D
846#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
847#define ASCV_VER_SERIAL_B (ushort)0x0065
848#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
849#define ASCV_WTM_FLAG_B (ushort)0x0068
850#define ASCV_RISC_FLAG_B (ushort)0x006A
851#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
852#define ASC_HOST_FLAG_IN_ISR 0x01
853#define ASC_HOST_FLAG_ACK_INT 0x02
854#define ASC_RISC_FLAG_GEN_INT 0x01
855#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
856#define IOP_CTRL (0x0F)
857#define IOP_STATUS (0x0E)
858#define IOP_INT_ACK IOP_STATUS
859#define IOP_REG_IFC (0x0D)
860#define IOP_SYN_OFFSET (0x0B)
861#define IOP_EXTRA_CONTROL (0x0D)
862#define IOP_REG_PC (0x0C)
863#define IOP_RAM_ADDR (0x0A)
864#define IOP_RAM_DATA (0x08)
865#define IOP_EEP_DATA (0x06)
866#define IOP_EEP_CMD (0x07)
867#define IOP_VERSION (0x03)
868#define IOP_CONFIG_HIGH (0x04)
869#define IOP_CONFIG_LOW (0x02)
870#define IOP_SIG_BYTE (0x01)
871#define IOP_SIG_WORD (0x00)
872#define IOP_REG_DC1 (0x0E)
873#define IOP_REG_DC0 (0x0C)
874#define IOP_REG_SB (0x0B)
875#define IOP_REG_DA1 (0x0A)
876#define IOP_REG_DA0 (0x08)
877#define IOP_REG_SC (0x09)
878#define IOP_DMA_SPEED (0x07)
879#define IOP_REG_FLAG (0x07)
880#define IOP_FIFO_H (0x06)
881#define IOP_FIFO_L (0x04)
882#define IOP_REG_ID (0x05)
883#define IOP_REG_QP (0x03)
884#define IOP_REG_IH (0x02)
885#define IOP_REG_IX (0x01)
886#define IOP_REG_AX (0x00)
887#define IFC_REG_LOCK (0x00)
888#define IFC_REG_UNLOCK (0x09)
889#define IFC_WR_EN_FILTER (0x10)
890#define IFC_RD_NO_EEPROM (0x10)
891#define IFC_SLEW_RATE (0x20)
892#define IFC_ACT_NEG (0x40)
893#define IFC_INP_FILTER (0x80)
894#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
895#define SC_SEL (uchar)(0x80)
896#define SC_BSY (uchar)(0x40)
897#define SC_ACK (uchar)(0x20)
898#define SC_REQ (uchar)(0x10)
899#define SC_ATN (uchar)(0x08)
900#define SC_IO (uchar)(0x04)
901#define SC_CD (uchar)(0x02)
902#define SC_MSG (uchar)(0x01)
903#define SEC_SCSI_CTL (uchar)(0x80)
904#define SEC_ACTIVE_NEGATE (uchar)(0x40)
905#define SEC_SLEW_RATE (uchar)(0x20)
906#define SEC_ENABLE_FILTER (uchar)(0x10)
907#define ASC_HALT_EXTMSG_IN (ushort)0x8000
908#define ASC_HALT_CHK_CONDITION (ushort)0x8100
909#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
910#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
911#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
912#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
913#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
914#define ASC_MAX_QNO 0xF8
915#define ASC_DATA_SEC_BEG (ushort)0x0080
916#define ASC_DATA_SEC_END (ushort)0x0080
917#define ASC_CODE_SEC_BEG (ushort)0x0080
918#define ASC_CODE_SEC_END (ushort)0x0080
919#define ASC_QADR_BEG (0x4000)
920#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
921#define ASC_QADR_END (ushort)0x7FFF
922#define ASC_QLAST_ADR (ushort)0x7FC0
923#define ASC_QBLK_SIZE 0x40
924#define ASC_BIOS_DATA_QBEG 0xF8
925#define ASC_MIN_ACTIVE_QNO 0x01
926#define ASC_QLINK_END 0xFF
927#define ASC_EEPROM_WORDS 0x10
928#define ASC_MAX_MGS_LEN 0x10
929#define ASC_BIOS_ADDR_DEF 0xDC00
930#define ASC_BIOS_SIZE 0x3800
931#define ASC_BIOS_RAM_OFF 0x3800
932#define ASC_BIOS_RAM_SIZE 0x800
933#define ASC_BIOS_MIN_ADDR 0xC000
934#define ASC_BIOS_MAX_ADDR 0xEC00
935#define ASC_BIOS_BANK_SIZE 0x0400
936#define ASC_MCODE_START_ADDR 0x0080
937#define ASC_CFG0_HOST_INT_ON 0x0020
938#define ASC_CFG0_BIOS_ON 0x0040
939#define ASC_CFG0_VERA_BURST_ON 0x0080
940#define ASC_CFG0_SCSI_PARITY_ON 0x0800
941#define ASC_CFG1_SCSI_TARGET_ON 0x0080
942#define ASC_CFG1_LRAM_8BITS_ON 0x0800
943#define ASC_CFG_MSW_CLR_MASK 0x3080
944#define CSW_TEST1 (ASC_CS_TYPE)0x8000
945#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
946#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
947#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
948#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
949#define CSW_TEST2 (ASC_CS_TYPE)0x0400
950#define CSW_TEST3 (ASC_CS_TYPE)0x0200
951#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
952#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
953#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
954#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
955#define CSW_HALTED (ASC_CS_TYPE)0x0010
956#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
957#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
958#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
959#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
960#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
961#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
962#define CIW_TEST1 (ASC_CS_TYPE)0x0200
963#define CIW_TEST2 (ASC_CS_TYPE)0x0400
964#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
965#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
966#define CC_CHIP_RESET (uchar)0x80
967#define CC_SCSI_RESET (uchar)0x40
968#define CC_HALT (uchar)0x20
969#define CC_SINGLE_STEP (uchar)0x10
970#define CC_DMA_ABLE (uchar)0x08
971#define CC_TEST (uchar)0x04
972#define CC_BANK_ONE (uchar)0x02
973#define CC_DIAG (uchar)0x01
974#define ASC_1000_ID0W 0x04C1
975#define ASC_1000_ID0W_FIX 0x00C1
976#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977#define ASC_EISA_REV_IOP_MASK (0x0C83)
978#define ASC_EISA_PID_IOP_MASK (0x0C80)
979#define ASC_EISA_CFG_IOP_MASK (0x0C86)
980#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981#define INS_HALTINT (ushort)0x6281
982#define INS_HALT (ushort)0x6280
983#define INS_SINT (ushort)0x6200
984#define INS_RFLAG_WTM (ushort)0x7380
985#define ASC_MC_SAVE_CODE_WSIZE 0x500
986#define ASC_MC_SAVE_DATA_WSIZE 0x40
987
988typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400989 ushort data[ASC_MC_SAVE_DATA_WSIZE];
990 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991} ASC_MC_SAVED;
992
993#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
994#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
995#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
996#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
997#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
998#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
999#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1000#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1001#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1002#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1003#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1004#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1005#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1006#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1007#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1008#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1009#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1010#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1011#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1012#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1013#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1014#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1015#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1016#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1017#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1018#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1019#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1020#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1021#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1022#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1023#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1024#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1025#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1026#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1027#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1028#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1029#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1030#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1031#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1032#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1033#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1034#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1035#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1036#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1037#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1038#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1039#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1040#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1041#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1042#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1043#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1044#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1045#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1046#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1047#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1048#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1049#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1050#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1051#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1052#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1053#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1054#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1055#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1056#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1057#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1058#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1059#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1060#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001062static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1063static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1064static void AscWaitEEPRead(void);
1065static void AscWaitEEPWrite(void);
1066static ushort AscReadEEPWord(PortAddr, uchar);
1067static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1068static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1069static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1070static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1071static int AscStartChip(PortAddr);
1072static int AscStopChip(PortAddr);
1073static void AscSetChipIH(PortAddr, ushort);
1074static int AscIsChipHalted(PortAddr);
1075static void AscAckInterrupt(PortAddr);
1076static void AscDisableInterrupt(PortAddr);
1077static void AscEnableInterrupt(PortAddr);
1078static void AscSetBank(PortAddr, uchar);
1079static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001081static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001083static uchar AscReadLramByte(PortAddr, ushort);
1084static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001086static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001088static void AscWriteLramWord(PortAddr, ushort, ushort);
1089static void AscWriteLramByte(PortAddr, ushort, uchar);
1090static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1091static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1092static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1093static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1094static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1095static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1096static ushort AscInitFromEEP(ASC_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001097static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1098static int AscTestExternalLram(ASC_DVC_VAR *);
1099static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1100static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1101static void AscSetChipSDTR(PortAddr, uchar, uchar);
1102static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1103static uchar AscAllocFreeQueue(PortAddr, uchar);
1104static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1105static int AscHostReqRiscHalt(PortAddr);
1106static int AscStopQueueExe(PortAddr);
1107static int AscSendScsiQueue(ASC_DVC_VAR *,
1108 ASC_SCSI_Q *scsiq, uchar n_q_required);
1109static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1110static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1111static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1112static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1113static ushort AscInitLram(ASC_DVC_VAR *);
1114static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1115static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1116static int AscIsrChipHalted(ASC_DVC_VAR *);
1117static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1118 ASC_QDONE_INFO *, ASC_DCNT);
1119static int AscIsrQDone(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001121static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001123static uchar AscGetChipScsiCtrl(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001124static uchar AscGetChipVersion(PortAddr, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001125static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001126static void AscToggleIRQAct(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001127static inline ulong DvcEnterCritical(void);
1128static inline void DvcLeaveCritical(ulong);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001129static void DvcSleepMilliSecond(ASC_DCNT);
1130static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
1131static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1132static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001133static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04001134static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001135static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1136static int AscISR(ASC_DVC_VAR *);
1137static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1138static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001140static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001142static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
1144/*
1145 * --- Adv Library Constants and Macros
1146 */
1147
1148#define ADV_LIB_VERSION_MAJOR 5
1149#define ADV_LIB_VERSION_MINOR 14
1150
1151/*
1152 * Define Adv Library required special types.
1153 */
1154
1155/*
1156 * Portable Data Types
1157 *
1158 * Any instance where a 32-bit long or pointer type is assumed
1159 * for precision or HW defined structures, the following define
1160 * types must be used. In Linux the char, short, and int types
1161 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1162 * and long types are 64 bits on Alpha and UltraSPARC.
1163 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001164#define ADV_PADDR __u32 /* Physical address data type. */
1165#define ADV_VADDR __u32 /* Virtual address data type. */
1166#define ADV_DCNT __u32 /* Unsigned Data count type. */
1167#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
1169/*
1170 * These macros are used to convert a virtual address to a
1171 * 32-bit value. This currently can be used on Linux Alpha
1172 * which uses 64-bit virtual address but a 32-bit bus address.
1173 * This is likely to break in the future, but doing this now
1174 * will give us time to change the HW and FW to handle 64-bit
1175 * addresses.
1176 */
1177#define ADV_VADDR_TO_U32 virt_to_bus
1178#define ADV_U32_TO_VADDR bus_to_virt
1179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001180#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182/*
1183 * Define Adv Library required memory access macros.
1184 */
1185#define ADV_MEM_READB(addr) readb(addr)
1186#define ADV_MEM_READW(addr) readw(addr)
1187#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1188#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1189#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1190
1191#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1192
1193/*
1194 * For wide boards a CDB length maximum of 16 bytes
1195 * is supported.
1196 */
1197#define ADV_MAX_CDB_LEN 16
1198
1199/*
1200 * Define total number of simultaneous maximum element scatter-gather
1201 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1202 * maximum number of outstanding commands per wide host adapter. Each
1203 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1204 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1205 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1206 * structures or 255 scatter-gather elements.
1207 *
1208 */
1209#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1210
1211/*
1212 * Define Adv Library required maximum number of scatter-gather
1213 * elements per request.
1214 */
1215#define ADV_MAX_SG_LIST 255
1216
1217/* Number of SG blocks needed. */
1218#define ADV_NUM_SG_BLOCK \
1219 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1220
1221/* Total contiguous memory needed for SG blocks. */
1222#define ADV_SG_TOTAL_MEM_SIZE \
1223 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1224
1225#define ADV_PAGE_SIZE PAGE_SIZE
1226
1227#define ADV_NUM_PAGE_CROSSING \
1228 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1229
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1231#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001232#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1234
1235#define ADV_EEP_DELAY_MS 100
1236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001237#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1238#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239/*
1240 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1241 * For later ICs Bit 13 controls whether the CIS (Card Information
1242 * Service Section) is loaded from EEPROM.
1243 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001244#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1245#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246/*
1247 * ASC38C1600 Bit 11
1248 *
1249 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1250 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1251 * Function 0 will specify INT B.
1252 *
1253 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1254 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1255 * Function 1 will specify INT A.
1256 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001257#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001259typedef struct adveep_3550_config {
1260 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001262 ushort cfg_lsw; /* 00 power up initialization */
1263 /* bit 13 set - Term Polarity Control */
1264 /* bit 14 set - BIOS Enable */
1265 /* bit 15 set - Big Endian Mode */
1266 ushort cfg_msw; /* 01 unused */
1267 ushort disc_enable; /* 02 disconnect enable */
1268 ushort wdtr_able; /* 03 Wide DTR able */
1269 ushort sdtr_able; /* 04 Synchronous DTR able */
1270 ushort start_motor; /* 05 send start up motor */
1271 ushort tagqng_able; /* 06 tag queuing able */
1272 ushort bios_scan; /* 07 BIOS device control */
1273 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001275 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1276 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001278 uchar scsi_reset_delay; /* 10 reset delay */
1279 uchar bios_id_lun; /* first boot device scsi id & lun */
1280 /* high nibble is lun */
1281 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001283 uchar termination; /* 11 0 - automatic */
1284 /* 1 - low off / high off */
1285 /* 2 - low off / high on */
1286 /* 3 - low on / high on */
1287 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001289 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001291 ushort bios_ctrl; /* 12 BIOS control bits */
1292 /* bit 0 BIOS don't act as initiator. */
1293 /* bit 1 BIOS > 1 GB support */
1294 /* bit 2 BIOS > 2 Disk Support */
1295 /* bit 3 BIOS don't support removables */
1296 /* bit 4 BIOS support bootable CD */
1297 /* bit 5 BIOS scan enabled */
1298 /* bit 6 BIOS support multiple LUNs */
1299 /* bit 7 BIOS display of message */
1300 /* bit 8 SCAM disabled */
1301 /* bit 9 Reset SCSI bus during init. */
1302 /* bit 10 */
1303 /* bit 11 No verbose initialization. */
1304 /* bit 12 SCSI parity enabled */
1305 /* bit 13 */
1306 /* bit 14 */
1307 /* bit 15 */
1308 ushort ultra_able; /* 13 ULTRA speed able */
1309 ushort reserved2; /* 14 reserved */
1310 uchar max_host_qng; /* 15 maximum host queuing */
1311 uchar max_dvc_qng; /* maximum per device queuing */
1312 ushort dvc_cntl; /* 16 control bit for driver */
1313 ushort bug_fix; /* 17 control bit for bug fix */
1314 ushort serial_number_word1; /* 18 Board serial number word 1 */
1315 ushort serial_number_word2; /* 19 Board serial number word 2 */
1316 ushort serial_number_word3; /* 20 Board serial number word 3 */
1317 ushort check_sum; /* 21 EEP check sum */
1318 uchar oem_name[16]; /* 22 OEM name */
1319 ushort dvc_err_code; /* 30 last device driver error code */
1320 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1321 ushort adv_err_addr; /* 32 last uc error address */
1322 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1323 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1324 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1325 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326} ADVEEP_3550_CONFIG;
1327
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001328typedef struct adveep_38C0800_config {
1329 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001331 ushort cfg_lsw; /* 00 power up initialization */
1332 /* bit 13 set - Load CIS */
1333 /* bit 14 set - BIOS Enable */
1334 /* bit 15 set - Big Endian Mode */
1335 ushort cfg_msw; /* 01 unused */
1336 ushort disc_enable; /* 02 disconnect enable */
1337 ushort wdtr_able; /* 03 Wide DTR able */
1338 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1339 ushort start_motor; /* 05 send start up motor */
1340 ushort tagqng_able; /* 06 tag queuing able */
1341 ushort bios_scan; /* 07 BIOS device control */
1342 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001344 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1345 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001347 uchar scsi_reset_delay; /* 10 reset delay */
1348 uchar bios_id_lun; /* first boot device scsi id & lun */
1349 /* high nibble is lun */
1350 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001352 uchar termination_se; /* 11 0 - automatic */
1353 /* 1 - low off / high off */
1354 /* 2 - low off / high on */
1355 /* 3 - low on / high on */
1356 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001358 uchar termination_lvd; /* 11 0 - automatic */
1359 /* 1 - low off / high off */
1360 /* 2 - low off / high on */
1361 /* 3 - low on / high on */
1362 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001364 ushort bios_ctrl; /* 12 BIOS control bits */
1365 /* bit 0 BIOS don't act as initiator. */
1366 /* bit 1 BIOS > 1 GB support */
1367 /* bit 2 BIOS > 2 Disk Support */
1368 /* bit 3 BIOS don't support removables */
1369 /* bit 4 BIOS support bootable CD */
1370 /* bit 5 BIOS scan enabled */
1371 /* bit 6 BIOS support multiple LUNs */
1372 /* bit 7 BIOS display of message */
1373 /* bit 8 SCAM disabled */
1374 /* bit 9 Reset SCSI bus during init. */
1375 /* bit 10 */
1376 /* bit 11 No verbose initialization. */
1377 /* bit 12 SCSI parity enabled */
1378 /* bit 13 */
1379 /* bit 14 */
1380 /* bit 15 */
1381 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1382 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1383 uchar max_host_qng; /* 15 maximum host queueing */
1384 uchar max_dvc_qng; /* maximum per device queuing */
1385 ushort dvc_cntl; /* 16 control bit for driver */
1386 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1387 ushort serial_number_word1; /* 18 Board serial number word 1 */
1388 ushort serial_number_word2; /* 19 Board serial number word 2 */
1389 ushort serial_number_word3; /* 20 Board serial number word 3 */
1390 ushort check_sum; /* 21 EEP check sum */
1391 uchar oem_name[16]; /* 22 OEM name */
1392 ushort dvc_err_code; /* 30 last device driver error code */
1393 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1394 ushort adv_err_addr; /* 32 last uc error address */
1395 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1396 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1397 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1398 ushort reserved36; /* 36 reserved */
1399 ushort reserved37; /* 37 reserved */
1400 ushort reserved38; /* 38 reserved */
1401 ushort reserved39; /* 39 reserved */
1402 ushort reserved40; /* 40 reserved */
1403 ushort reserved41; /* 41 reserved */
1404 ushort reserved42; /* 42 reserved */
1405 ushort reserved43; /* 43 reserved */
1406 ushort reserved44; /* 44 reserved */
1407 ushort reserved45; /* 45 reserved */
1408 ushort reserved46; /* 46 reserved */
1409 ushort reserved47; /* 47 reserved */
1410 ushort reserved48; /* 48 reserved */
1411 ushort reserved49; /* 49 reserved */
1412 ushort reserved50; /* 50 reserved */
1413 ushort reserved51; /* 51 reserved */
1414 ushort reserved52; /* 52 reserved */
1415 ushort reserved53; /* 53 reserved */
1416 ushort reserved54; /* 54 reserved */
1417 ushort reserved55; /* 55 reserved */
1418 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1419 ushort cisprt_msw; /* 57 CIS PTR MSW */
1420 ushort subsysvid; /* 58 SubSystem Vendor ID */
1421 ushort subsysid; /* 59 SubSystem ID */
1422 ushort reserved60; /* 60 reserved */
1423 ushort reserved61; /* 61 reserved */
1424 ushort reserved62; /* 62 reserved */
1425 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426} ADVEEP_38C0800_CONFIG;
1427
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001428typedef struct adveep_38C1600_config {
1429 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001431 ushort cfg_lsw; /* 00 power up initialization */
1432 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1433 /* clear - Func. 0 INTA, Func. 1 INTB */
1434 /* bit 13 set - Load CIS */
1435 /* bit 14 set - BIOS Enable */
1436 /* bit 15 set - Big Endian Mode */
1437 ushort cfg_msw; /* 01 unused */
1438 ushort disc_enable; /* 02 disconnect enable */
1439 ushort wdtr_able; /* 03 Wide DTR able */
1440 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1441 ushort start_motor; /* 05 send start up motor */
1442 ushort tagqng_able; /* 06 tag queuing able */
1443 ushort bios_scan; /* 07 BIOS device control */
1444 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001446 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1447 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001449 uchar scsi_reset_delay; /* 10 reset delay */
1450 uchar bios_id_lun; /* first boot device scsi id & lun */
1451 /* high nibble is lun */
1452 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001454 uchar termination_se; /* 11 0 - automatic */
1455 /* 1 - low off / high off */
1456 /* 2 - low off / high on */
1457 /* 3 - low on / high on */
1458 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001460 uchar termination_lvd; /* 11 0 - automatic */
1461 /* 1 - low off / high off */
1462 /* 2 - low off / high on */
1463 /* 3 - low on / high on */
1464 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001466 ushort bios_ctrl; /* 12 BIOS control bits */
1467 /* bit 0 BIOS don't act as initiator. */
1468 /* bit 1 BIOS > 1 GB support */
1469 /* bit 2 BIOS > 2 Disk Support */
1470 /* bit 3 BIOS don't support removables */
1471 /* bit 4 BIOS support bootable CD */
1472 /* bit 5 BIOS scan enabled */
1473 /* bit 6 BIOS support multiple LUNs */
1474 /* bit 7 BIOS display of message */
1475 /* bit 8 SCAM disabled */
1476 /* bit 9 Reset SCSI bus during init. */
1477 /* bit 10 Basic Integrity Checking disabled */
1478 /* bit 11 No verbose initialization. */
1479 /* bit 12 SCSI parity enabled */
1480 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1481 /* bit 14 */
1482 /* bit 15 */
1483 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1484 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1485 uchar max_host_qng; /* 15 maximum host queueing */
1486 uchar max_dvc_qng; /* maximum per device queuing */
1487 ushort dvc_cntl; /* 16 control bit for driver */
1488 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1489 ushort serial_number_word1; /* 18 Board serial number word 1 */
1490 ushort serial_number_word2; /* 19 Board serial number word 2 */
1491 ushort serial_number_word3; /* 20 Board serial number word 3 */
1492 ushort check_sum; /* 21 EEP check sum */
1493 uchar oem_name[16]; /* 22 OEM name */
1494 ushort dvc_err_code; /* 30 last device driver error code */
1495 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1496 ushort adv_err_addr; /* 32 last uc error address */
1497 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1498 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1499 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1500 ushort reserved36; /* 36 reserved */
1501 ushort reserved37; /* 37 reserved */
1502 ushort reserved38; /* 38 reserved */
1503 ushort reserved39; /* 39 reserved */
1504 ushort reserved40; /* 40 reserved */
1505 ushort reserved41; /* 41 reserved */
1506 ushort reserved42; /* 42 reserved */
1507 ushort reserved43; /* 43 reserved */
1508 ushort reserved44; /* 44 reserved */
1509 ushort reserved45; /* 45 reserved */
1510 ushort reserved46; /* 46 reserved */
1511 ushort reserved47; /* 47 reserved */
1512 ushort reserved48; /* 48 reserved */
1513 ushort reserved49; /* 49 reserved */
1514 ushort reserved50; /* 50 reserved */
1515 ushort reserved51; /* 51 reserved */
1516 ushort reserved52; /* 52 reserved */
1517 ushort reserved53; /* 53 reserved */
1518 ushort reserved54; /* 54 reserved */
1519 ushort reserved55; /* 55 reserved */
1520 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1521 ushort cisprt_msw; /* 57 CIS PTR MSW */
1522 ushort subsysvid; /* 58 SubSystem Vendor ID */
1523 ushort subsysid; /* 59 SubSystem ID */
1524 ushort reserved60; /* 60 reserved */
1525 ushort reserved61; /* 61 reserved */
1526 ushort reserved62; /* 62 reserved */
1527 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528} ADVEEP_38C1600_CONFIG;
1529
1530/*
1531 * EEPROM Commands
1532 */
1533#define ASC_EEP_CMD_DONE 0x0200
1534#define ASC_EEP_CMD_DONE_ERR 0x0001
1535
1536/* cfg_word */
1537#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
1538
1539/* bios_ctrl */
1540#define BIOS_CTRL_BIOS 0x0001
1541#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1542#define BIOS_CTRL_GT_2_DISK 0x0004
1543#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1544#define BIOS_CTRL_BOOTABLE_CD 0x0010
1545#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1546#define BIOS_CTRL_DISPLAY_MSG 0x0080
1547#define BIOS_CTRL_NO_SCAM 0x0100
1548#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1549#define BIOS_CTRL_INIT_VERBOSE 0x0800
1550#define BIOS_CTRL_SCSI_PARITY 0x1000
1551#define BIOS_CTRL_AIPP_DIS 0x2000
1552
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001553#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001555#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
1557/*
1558 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1559 * a special 16K Adv Library and Microcode version. After the issue is
1560 * resolved, should restore 32K support.
1561 *
1562 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1563 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001564#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
1566/*
1567 * Byte I/O register address from base of 'iop_base'.
1568 */
1569#define IOPB_INTR_STATUS_REG 0x00
1570#define IOPB_CHIP_ID_1 0x01
1571#define IOPB_INTR_ENABLES 0x02
1572#define IOPB_CHIP_TYPE_REV 0x03
1573#define IOPB_RES_ADDR_4 0x04
1574#define IOPB_RES_ADDR_5 0x05
1575#define IOPB_RAM_DATA 0x06
1576#define IOPB_RES_ADDR_7 0x07
1577#define IOPB_FLAG_REG 0x08
1578#define IOPB_RES_ADDR_9 0x09
1579#define IOPB_RISC_CSR 0x0A
1580#define IOPB_RES_ADDR_B 0x0B
1581#define IOPB_RES_ADDR_C 0x0C
1582#define IOPB_RES_ADDR_D 0x0D
1583#define IOPB_SOFT_OVER_WR 0x0E
1584#define IOPB_RES_ADDR_F 0x0F
1585#define IOPB_MEM_CFG 0x10
1586#define IOPB_RES_ADDR_11 0x11
1587#define IOPB_GPIO_DATA 0x12
1588#define IOPB_RES_ADDR_13 0x13
1589#define IOPB_FLASH_PAGE 0x14
1590#define IOPB_RES_ADDR_15 0x15
1591#define IOPB_GPIO_CNTL 0x16
1592#define IOPB_RES_ADDR_17 0x17
1593#define IOPB_FLASH_DATA 0x18
1594#define IOPB_RES_ADDR_19 0x19
1595#define IOPB_RES_ADDR_1A 0x1A
1596#define IOPB_RES_ADDR_1B 0x1B
1597#define IOPB_RES_ADDR_1C 0x1C
1598#define IOPB_RES_ADDR_1D 0x1D
1599#define IOPB_RES_ADDR_1E 0x1E
1600#define IOPB_RES_ADDR_1F 0x1F
1601#define IOPB_DMA_CFG0 0x20
1602#define IOPB_DMA_CFG1 0x21
1603#define IOPB_TICKLE 0x22
1604#define IOPB_DMA_REG_WR 0x23
1605#define IOPB_SDMA_STATUS 0x24
1606#define IOPB_SCSI_BYTE_CNT 0x25
1607#define IOPB_HOST_BYTE_CNT 0x26
1608#define IOPB_BYTE_LEFT_TO_XFER 0x27
1609#define IOPB_BYTE_TO_XFER_0 0x28
1610#define IOPB_BYTE_TO_XFER_1 0x29
1611#define IOPB_BYTE_TO_XFER_2 0x2A
1612#define IOPB_BYTE_TO_XFER_3 0x2B
1613#define IOPB_ACC_GRP 0x2C
1614#define IOPB_RES_ADDR_2D 0x2D
1615#define IOPB_DEV_ID 0x2E
1616#define IOPB_RES_ADDR_2F 0x2F
1617#define IOPB_SCSI_DATA 0x30
1618#define IOPB_RES_ADDR_31 0x31
1619#define IOPB_RES_ADDR_32 0x32
1620#define IOPB_SCSI_DATA_HSHK 0x33
1621#define IOPB_SCSI_CTRL 0x34
1622#define IOPB_RES_ADDR_35 0x35
1623#define IOPB_RES_ADDR_36 0x36
1624#define IOPB_RES_ADDR_37 0x37
1625#define IOPB_RAM_BIST 0x38
1626#define IOPB_PLL_TEST 0x39
1627#define IOPB_PCI_INT_CFG 0x3A
1628#define IOPB_RES_ADDR_3B 0x3B
1629#define IOPB_RFIFO_CNT 0x3C
1630#define IOPB_RES_ADDR_3D 0x3D
1631#define IOPB_RES_ADDR_3E 0x3E
1632#define IOPB_RES_ADDR_3F 0x3F
1633
1634/*
1635 * Word I/O register address from base of 'iop_base'.
1636 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001637#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1638#define IOPW_CTRL_REG 0x02 /* CC */
1639#define IOPW_RAM_ADDR 0x04 /* LA */
1640#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001642#define IOPW_RISC_CSR 0x0A /* CSR */
1643#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1644#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001646#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001648#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001650#define IOPW_EE_CMD 0x1A /* EC */
1651#define IOPW_EE_DATA 0x1C /* ED */
1652#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001654#define IOPW_Q_BASE 0x22 /* QB */
1655#define IOPW_QP 0x24 /* QP */
1656#define IOPW_IX 0x26 /* IX */
1657#define IOPW_SP 0x28 /* SP */
1658#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659#define IOPW_RES_ADDR_2C 0x2C
1660#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001661#define IOPW_SCSI_DATA 0x30 /* SD */
1662#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1663#define IOPW_SCSI_CTRL 0x34 /* SC */
1664#define IOPW_HSHK_CFG 0x36 /* HCFG */
1665#define IOPW_SXFR_STATUS 0x36 /* SXS */
1666#define IOPW_SXFR_CNTL 0x38 /* SXL */
1667#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001669#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
1671/*
1672 * Doubleword I/O register address from base of 'iop_base'.
1673 */
1674#define IOPDW_RES_ADDR_0 0x00
1675#define IOPDW_RAM_DATA 0x04
1676#define IOPDW_RES_ADDR_8 0x08
1677#define IOPDW_RES_ADDR_C 0x0C
1678#define IOPDW_RES_ADDR_10 0x10
1679#define IOPDW_COMMA 0x14
1680#define IOPDW_COMMB 0x18
1681#define IOPDW_RES_ADDR_1C 0x1C
1682#define IOPDW_SDMA_ADDR0 0x20
1683#define IOPDW_SDMA_ADDR1 0x24
1684#define IOPDW_SDMA_COUNT 0x28
1685#define IOPDW_SDMA_ERROR 0x2C
1686#define IOPDW_RDMA_ADDR0 0x30
1687#define IOPDW_RDMA_ADDR1 0x34
1688#define IOPDW_RDMA_COUNT 0x38
1689#define IOPDW_RDMA_ERROR 0x3C
1690
1691#define ADV_CHIP_ID_BYTE 0x25
1692#define ADV_CHIP_ID_WORD 0x04C1
1693
1694#define ADV_SC_SCSI_BUS_RESET 0x2000
1695
1696#define ADV_INTR_ENABLE_HOST_INTR 0x01
1697#define ADV_INTR_ENABLE_SEL_INTR 0x02
1698#define ADV_INTR_ENABLE_DPR_INTR 0x04
1699#define ADV_INTR_ENABLE_RTA_INTR 0x08
1700#define ADV_INTR_ENABLE_RMA_INTR 0x10
1701#define ADV_INTR_ENABLE_RST_INTR 0x20
1702#define ADV_INTR_ENABLE_DPE_INTR 0x40
1703#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1704
1705#define ADV_INTR_STATUS_INTRA 0x01
1706#define ADV_INTR_STATUS_INTRB 0x02
1707#define ADV_INTR_STATUS_INTRC 0x04
1708
1709#define ADV_RISC_CSR_STOP (0x0000)
1710#define ADV_RISC_TEST_COND (0x2000)
1711#define ADV_RISC_CSR_RUN (0x4000)
1712#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1713
1714#define ADV_CTRL_REG_HOST_INTR 0x0100
1715#define ADV_CTRL_REG_SEL_INTR 0x0200
1716#define ADV_CTRL_REG_DPR_INTR 0x0400
1717#define ADV_CTRL_REG_RTA_INTR 0x0800
1718#define ADV_CTRL_REG_RMA_INTR 0x1000
1719#define ADV_CTRL_REG_RES_BIT14 0x2000
1720#define ADV_CTRL_REG_DPE_INTR 0x4000
1721#define ADV_CTRL_REG_POWER_DONE 0x8000
1722#define ADV_CTRL_REG_ANY_INTR 0xFF00
1723
1724#define ADV_CTRL_REG_CMD_RESET 0x00C6
1725#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1726#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1727#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1728#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1729
1730#define ADV_TICKLE_NOP 0x00
1731#define ADV_TICKLE_A 0x01
1732#define ADV_TICKLE_B 0x02
1733#define ADV_TICKLE_C 0x03
1734
1735#define ADV_SCSI_CTRL_RSTOUT 0x2000
1736
1737#define AdvIsIntPending(port) \
1738 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1739
1740/*
1741 * SCSI_CFG0 Register bit definitions
1742 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001743#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1744#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1745#define EVEN_PARITY 0x1000 /* Select Even Parity */
1746#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1747#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1748#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1749#define SCAM_EN 0x0080 /* Enable SCAM selection */
1750#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1751#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1752#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1753#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755/*
1756 * SCSI_CFG1 Register bit definitions
1757 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001758#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1759#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1760#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1761#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1762#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1763#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1764#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1765#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1766#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1767#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1768#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1769#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1770#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1771#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1772#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774/*
1775 * Addendum for ASC-38C0800 Chip
1776 *
1777 * The ASC-38C1600 Chip uses the same definitions except that the
1778 * bus mode override bits [12:10] have been moved to byte register
1779 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1780 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1781 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1782 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1783 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1784 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001785#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1786#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1787#define HVD 0x1000 /* HVD Device Detect */
1788#define LVD 0x0800 /* LVD Device Detect */
1789#define SE 0x0400 /* SE Device Detect */
1790#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1791#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1792#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1793#define TERM_SE 0x0030 /* SE Termination Bits */
1794#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1795#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1796#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1797#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1798#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1799#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1800#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1801#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803#define CABLE_ILLEGAL_A 0x7
1804 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1805
1806#define CABLE_ILLEGAL_B 0xB
1807 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1808
1809/*
1810 * MEM_CFG Register bit definitions
1811 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001812#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1813#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1814#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1815#define RAM_SZ_2KB 0x00 /* 2 KB */
1816#define RAM_SZ_4KB 0x04 /* 4 KB */
1817#define RAM_SZ_8KB 0x08 /* 8 KB */
1818#define RAM_SZ_16KB 0x0C /* 16 KB */
1819#define RAM_SZ_32KB 0x10 /* 32 KB */
1820#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
1822/*
1823 * DMA_CFG0 Register bit definitions
1824 *
1825 * This register is only accessible to the host.
1826 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001827#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1828#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1829#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1830#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1831#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1832#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1833#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1834#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1835#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1836#define START_CTL 0x0C /* DMA start conditions */
1837#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1838#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1839#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1840#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1841#define READ_CMD 0x03 /* Memory Read Method */
1842#define READ_CMD_MR 0x00 /* Memory Read */
1843#define READ_CMD_MRL 0x02 /* Memory Read Long */
1844#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846/*
1847 * ASC-38C0800 RAM BIST Register bit definitions
1848 */
1849#define RAM_TEST_MODE 0x80
1850#define PRE_TEST_MODE 0x40
1851#define NORMAL_MODE 0x00
1852#define RAM_TEST_DONE 0x10
1853#define RAM_TEST_STATUS 0x0F
1854#define RAM_TEST_HOST_ERROR 0x08
1855#define RAM_TEST_INTRAM_ERROR 0x04
1856#define RAM_TEST_RISC_ERROR 0x02
1857#define RAM_TEST_SCSI_ERROR 0x01
1858#define RAM_TEST_SUCCESS 0x00
1859#define PRE_TEST_VALUE 0x05
1860#define NORMAL_VALUE 0x00
1861
1862/*
1863 * ASC38C1600 Definitions
1864 *
1865 * IOPB_PCI_INT_CFG Bit Field Definitions
1866 */
1867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001868#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
1870/*
1871 * Bit 1 can be set to change the interrupt for the Function to operate in
1872 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1873 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1874 * mode, otherwise the operating mode is undefined.
1875 */
1876#define TOTEMPOLE 0x02
1877
1878/*
1879 * Bit 0 can be used to change the Int Pin for the Function. The value is
1880 * 0 by default for both Functions with Function 0 using INT A and Function
1881 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1882 * INT A is used.
1883 *
1884 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1885 * value specified in the PCI Configuration Space.
1886 */
1887#define INTAB 0x01
1888
1889/* a_advlib.h */
1890
1891/*
1892 * Adv Library Status Definitions
1893 */
1894#define ADV_TRUE 1
1895#define ADV_FALSE 0
1896#define ADV_NOERROR 1
1897#define ADV_SUCCESS 1
1898#define ADV_BUSY 0
1899#define ADV_ERROR (-1)
1900
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901/*
1902 * ADV_DVC_VAR 'warn_code' values
1903 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001904#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1905#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1906#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
1907#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
1908#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001910#define ADV_MAX_TID 15 /* max. target identifier */
1911#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913/*
1914 * Error code values are set in ADV_DVC_VAR 'err_code'.
1915 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001916#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
1917#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
1918#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
1919#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
1920#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
1921#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
1922#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
1923#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
1924#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
1925#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
1926#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
1927#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
1928#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
1929#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
1931/*
1932 * Fixed locations of microcode operating variables.
1933 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001934#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1935#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1936#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1937#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1938#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1939#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1940#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1941#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1942#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1943#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1944#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1945#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1946#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947#define ASC_MC_CHIP_TYPE 0x009A
1948#define ASC_MC_INTRB_CODE 0x009B
1949#define ASC_MC_WDTR_ABLE 0x009C
1950#define ASC_MC_SDTR_ABLE 0x009E
1951#define ASC_MC_TAGQNG_ABLE 0x00A0
1952#define ASC_MC_DISC_ENABLE 0x00A2
1953#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1954#define ASC_MC_IDLE_CMD 0x00A6
1955#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1956#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1957#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1958#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1959#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1960#define ASC_MC_SDTR_DONE 0x00B6
1961#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1962#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1963#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001964#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001966#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967#define ASC_MC_ICQ 0x0160
1968#define ASC_MC_IRQ 0x0164
1969#define ASC_MC_PPR_ABLE 0x017A
1970
1971/*
1972 * BIOS LRAM variable absolute offsets.
1973 */
1974#define BIOS_CODESEG 0x54
1975#define BIOS_CODELEN 0x56
1976#define BIOS_SIGNATURE 0x58
1977#define BIOS_VERSION 0x5A
1978
1979/*
1980 * Microcode Control Flags
1981 *
1982 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1983 * and handled by the microcode.
1984 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001985#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1986#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
1988/*
1989 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1990 */
1991#define HSHK_CFG_WIDE_XFR 0x8000
1992#define HSHK_CFG_RATE 0x0F00
1993#define HSHK_CFG_OFFSET 0x001F
1994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001995#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1996#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1997#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1998#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002000#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2001#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2002#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2003#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2004#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002006#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2007#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2008#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2009#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2010#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011/*
2012 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2013 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2014 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002015#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2016#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
2018/*
2019 * All fields here are accessed by the board microcode and need to be
2020 * little-endian.
2021 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002022typedef struct adv_carr_t {
2023 ADV_VADDR carr_va; /* Carrier Virtual Address */
2024 ADV_PADDR carr_pa; /* Carrier Physical Address */
2025 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2026 /*
2027 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2028 *
2029 * next_vpa [3:1] Reserved Bits
2030 * next_vpa [0] Done Flag set in Response Queue.
2031 */
2032 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033} ADV_CARR_T;
2034
2035/*
2036 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2037 */
2038#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2039
2040#define ASC_RQ_DONE 0x00000001
2041#define ASC_RQ_GOOD 0x00000002
2042#define ASC_CQ_STOPPER 0x00000000
2043
2044#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2045
2046#define ADV_CARRIER_NUM_PAGE_CROSSING \
2047 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2048 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2049
2050#define ADV_CARRIER_BUFSIZE \
2051 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2052
2053/*
2054 * ASC_SCSI_REQ_Q 'a_flag' definitions
2055 *
2056 * The Adv Library should limit use to the lower nibble (4 bits) of
2057 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2058 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002059#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2060#define ADV_SCSIQ_DONE 0x02 /* request done */
2061#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002063#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2064#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2065#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
2067/*
2068 * Adapter temporary configuration structure
2069 *
2070 * This structure can be discarded after initialization. Don't add
2071 * fields here needed after initialization.
2072 *
2073 * Field naming convention:
2074 *
2075 * *_enable indicates the field enables or disables a feature. The
2076 * value of the field is never reset.
2077 */
2078typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002079 ushort disc_enable; /* enable disconnection */
2080 uchar chip_version; /* chip version */
2081 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2082 ushort lib_version; /* Adv Library version number */
2083 ushort control_flag; /* Microcode Control Flag */
2084 ushort mcode_date; /* Microcode date */
2085 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002086 ushort serial1; /* EEPROM serial number word 1 */
2087 ushort serial2; /* EEPROM serial number word 2 */
2088 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089} ADV_DVC_CFG;
2090
2091struct adv_dvc_var;
2092struct adv_scsi_req_q;
2093
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094/*
2095 * Adapter operation variable structure.
2096 *
2097 * One structure is required per host adapter.
2098 *
2099 * Field naming convention:
2100 *
2101 * *_able indicates both whether a feature should be enabled or disabled
2102 * and whether a device isi capable of the feature. At initialization
2103 * this field may be set, but later if a device is found to be incapable
2104 * of the feature, the field is cleared.
2105 */
2106typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002107 AdvPortAddr iop_base; /* I/O port address */
2108 ushort err_code; /* fatal error code */
2109 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002110 ushort wdtr_able; /* try WDTR for a device */
2111 ushort sdtr_able; /* try SDTR for a device */
2112 ushort ultra_able; /* try SDTR Ultra speed for a device */
2113 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2114 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2115 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2116 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2117 ushort tagqng_able; /* try tagged queuing with a device */
2118 ushort ppr_able; /* PPR message capable per TID bitmask. */
2119 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2120 ushort start_motor; /* start motor command allowed */
2121 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2122 uchar chip_no; /* should be assigned by caller */
2123 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2124 uchar irq_no; /* IRQ number */
2125 ushort no_scam; /* scam_tolerant of EEPROM */
2126 struct asc_board *drv_ptr; /* driver pointer to private structure */
2127 uchar chip_scsi_id; /* chip SCSI target ID */
2128 uchar chip_type;
2129 uchar bist_err_code;
2130 ADV_CARR_T *carrier_buf;
2131 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2132 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2133 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2134 ushort carr_pending_cnt; /* Count of pending carriers. */
2135 /*
2136 * Note: The following fields will not be used after initialization. The
2137 * driver may discard the buffer after initialization is done.
2138 */
2139 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140} ADV_DVC_VAR;
2141
2142#define NO_OF_SG_PER_BLOCK 15
2143
2144typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002145 uchar reserved1;
2146 uchar reserved2;
2147 uchar reserved3;
2148 uchar sg_cnt; /* Valid entries in block. */
2149 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
2150 struct {
2151 ADV_PADDR sg_addr; /* SG element address. */
2152 ADV_DCNT sg_count; /* SG element count. */
2153 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154} ADV_SG_BLOCK;
2155
2156/*
2157 * ADV_SCSI_REQ_Q - microcode request structure
2158 *
2159 * All fields in this structure up to byte 60 are used by the microcode.
2160 * The microcode makes assumptions about the size and ordering of fields
2161 * in this structure. Do not change the structure definition here without
2162 * coordinating the change with the microcode.
2163 *
2164 * All fields accessed by microcode must be maintained in little_endian
2165 * order.
2166 */
2167typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002168 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2169 uchar target_cmd;
2170 uchar target_id; /* Device target identifier. */
2171 uchar target_lun; /* Device target logical unit number. */
2172 ADV_PADDR data_addr; /* Data buffer physical address. */
2173 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
2174 ADV_PADDR sense_addr;
2175 ADV_PADDR carr_pa;
2176 uchar mflag;
2177 uchar sense_len;
2178 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
2179 uchar scsi_cntl;
2180 uchar done_status; /* Completion status. */
2181 uchar scsi_status; /* SCSI status byte. */
2182 uchar host_status; /* Ucode host status. */
2183 uchar sg_working_ix;
2184 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
2185 ADV_PADDR sg_real_addr; /* SG list physical address. */
2186 ADV_PADDR scsiq_rptr;
2187 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
2188 ADV_VADDR scsiq_ptr;
2189 ADV_VADDR carr_va;
2190 /*
2191 * End of microcode structure - 60 bytes. The rest of the structure
2192 * is used by the Adv Library and ignored by the microcode.
2193 */
2194 ADV_VADDR srb_ptr;
2195 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2196 char *vdata_addr; /* Data buffer virtual address. */
2197 uchar a_flag;
2198 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199} ADV_SCSI_REQ_Q;
2200
2201/*
2202 * Microcode idle loop commands
2203 */
2204#define IDLE_CMD_COMPLETED 0
2205#define IDLE_CMD_STOP_CHIP 0x0001
2206#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2207#define IDLE_CMD_SEND_INT 0x0004
2208#define IDLE_CMD_ABORT 0x0008
2209#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002210#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
2211#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212#define IDLE_CMD_SCSIREQ 0x0080
2213
2214#define IDLE_CMD_STATUS_SUCCESS 0x0001
2215#define IDLE_CMD_STATUS_FAILURE 0x0002
2216
2217/*
2218 * AdvSendIdleCmd() flag definitions.
2219 */
2220#define ADV_NOWAIT 0x01
2221
2222/*
2223 * Wait loop time out values.
2224 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002225#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
2226#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2227#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
2228#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
2229#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002231#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2232#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2233#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2234#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002236#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
2238/*
2239 * Device drivers must define the following functions.
2240 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002241static inline ulong DvcEnterCritical(void);
2242static inline void DvcLeaveCritical(ulong);
2243static void DvcSleepMilliSecond(ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002244static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2245 uchar *, ASC_SDCNT *, int);
2246static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
2248/*
2249 * Adv Library functions available to drivers.
2250 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002251static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2252static int AdvISR(ADV_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002253static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2254static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
2255static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
2256static int AdvResetChipAndSB(ADV_DVC_VAR *);
2257static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259/*
2260 * Internal Adv Library functions.
2261 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002262static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002263static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
2264static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
2265static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
2266static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2267static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2268static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2269static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2270static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2271static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2272static void AdvWaitEEPCmd(AdvPortAddr);
2273static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275/* Read byte from a register. */
2276#define AdvReadByteRegister(iop_base, reg_off) \
2277 (ADV_MEM_READB((iop_base) + (reg_off)))
2278
2279/* Write byte to a register. */
2280#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2281 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2282
2283/* Read word (2 bytes) from a register. */
2284#define AdvReadWordRegister(iop_base, reg_off) \
2285 (ADV_MEM_READW((iop_base) + (reg_off)))
2286
2287/* Write word (2 bytes) to a register. */
2288#define AdvWriteWordRegister(iop_base, reg_off, word) \
2289 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2290
2291/* Write dword (4 bytes) to a register. */
2292#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2293 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2294
2295/* Read byte from LRAM. */
2296#define AdvReadByteLram(iop_base, addr, byte) \
2297do { \
2298 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2299 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2300} while (0)
2301
2302/* Write byte to LRAM. */
2303#define AdvWriteByteLram(iop_base, addr, byte) \
2304 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2305 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2306
2307/* Read word (2 bytes) from LRAM. */
2308#define AdvReadWordLram(iop_base, addr, word) \
2309do { \
2310 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2311 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2312} while (0)
2313
2314/* Write word (2 bytes) to LRAM. */
2315#define AdvWriteWordLram(iop_base, addr, word) \
2316 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2317 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2318
2319/* Write little-endian double word (4 bytes) to LRAM */
2320/* Because of unspecified C language ordering don't use auto-increment. */
2321#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2322 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2323 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2324 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2325 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2326 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2327 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2328
2329/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2330#define AdvReadWordAutoIncLram(iop_base) \
2331 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2332
2333/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2334#define AdvWriteWordAutoIncLram(iop_base, word) \
2335 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337/*
2338 * Define macro to check for Condor signature.
2339 *
2340 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2341 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2342 */
2343#define AdvFindSignature(iop_base) \
2344 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2345 ADV_CHIP_ID_BYTE) && \
2346 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2347 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2348
2349/*
2350 * Define macro to Return the version number of the chip at 'iop_base'.
2351 *
2352 * The second parameter 'bus_type' is currently unused.
2353 */
2354#define AdvGetChipVersion(iop_base, bus_type) \
2355 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2356
2357/*
2358 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2359 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2360 *
2361 * If the request has not yet been sent to the device it will simply be
2362 * aborted from RISC memory. If the request is disconnected it will be
2363 * aborted on reselection by sending an Abort Message to the target ID.
2364 *
2365 * Return value:
2366 * ADV_TRUE(1) - Queue was successfully aborted.
2367 * ADV_FALSE(0) - Queue was not found on the active queue list.
2368 */
2369#define AdvAbortQueue(asc_dvc, scsiq) \
2370 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2371 (ADV_DCNT) (scsiq))
2372
2373/*
2374 * Send a Bus Device Reset Message to the specified target ID.
2375 *
2376 * All outstanding commands will be purged if sending the
2377 * Bus Device Reset Message is successful.
2378 *
2379 * Return Value:
2380 * ADV_TRUE(1) - All requests on the target are purged.
2381 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2382 * are not purged.
2383 */
2384#define AdvResetDevice(asc_dvc, target_id) \
2385 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2386 (ADV_DCNT) (target_id))
2387
2388/*
2389 * SCSI Wide Type definition.
2390 */
2391#define ADV_SCSI_BIT_ID_TYPE ushort
2392
2393/*
2394 * AdvInitScsiTarget() 'cntl_flag' options.
2395 */
2396#define ADV_SCAN_LUN 0x01
2397#define ADV_CAPINFO_NOLUN 0x02
2398
2399/*
2400 * Convert target id to target id bit mask.
2401 */
2402#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2403
2404/*
2405 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2406 */
2407
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002408#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409#define QD_NO_ERROR 0x01
2410#define QD_ABORTED_BY_HOST 0x02
2411#define QD_WITH_ERROR 0x04
2412
2413#define QHSTA_NO_ERROR 0x00
2414#define QHSTA_M_SEL_TIMEOUT 0x11
2415#define QHSTA_M_DATA_OVER_RUN 0x12
2416#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2417#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002418#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2419#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2420#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2421#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2422#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2423#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2424#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002426#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2427#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2428#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2429#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2430#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2431#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2432#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2433#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434#define QHSTA_M_WTM_TIMEOUT 0x41
2435#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2436#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2437#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002438#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2439#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2440#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
2442/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 * DvcGetPhyAddr() flag arguments
2444 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002445#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2446#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2447#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2448#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2449#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2450#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
2452/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2453#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2454#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2455#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2456
2457/*
2458 * Total contiguous memory needed for driver SG blocks.
2459 *
2460 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2461 * number of scatter-gather elements the driver supports in a
2462 * single request.
2463 */
2464
2465#define ADV_SG_LIST_MAX_BYTE_SIZE \
2466 (sizeof(ADV_SG_BLOCK) * \
2467 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2468
2469/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 * --- Driver Constants and Macros
2471 */
2472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473/* Reference Scsi_Host hostdata */
2474#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
2475
2476/* asc_board_t flags */
2477#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002478#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479#define ASC_SELECT_QUEUE_DEPTHS 0x08
2480
2481#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
2482#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
2483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002484#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002486#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
2488#ifdef CONFIG_PROC_FS
2489/* /proc/scsi/advansys/[0...] related definitions */
2490#define ASC_PRTBUF_SIZE 2048
2491#define ASC_PRTLINE_SIZE 160
2492
2493#define ASC_PRT_NEXT() \
2494 if (cp) { \
2495 totlen += len; \
2496 leftlen -= len; \
2497 if (leftlen == 0) { \
2498 return totlen; \
2499 } \
2500 cp += len; \
2501 }
2502#endif /* CONFIG_PROC_FS */
2503
2504/* Asc Library return codes */
2505#define ASC_TRUE 1
2506#define ASC_FALSE 0
2507#define ASC_NOERROR 1
2508#define ASC_BUSY 0
2509#define ASC_ERROR (-1)
2510
2511/* struct scsi_cmnd function return codes */
2512#define STATUS_BYTE(byte) (byte)
2513#define MSG_BYTE(byte) ((byte) << 8)
2514#define HOST_BYTE(byte) ((byte) << 16)
2515#define DRIVER_BYTE(byte) ((byte) << 24)
2516
2517/*
2518 * The following definitions and macros are OS independent interfaces to
2519 * the queue functions:
2520 * REQ - SCSI request structure
2521 * REQP - pointer to SCSI request structure
2522 * REQPTID(reqp) - reqp's target id
2523 * REQPNEXT(reqp) - reqp's next pointer
2524 * REQPNEXTP(reqp) - pointer to reqp's next pointer
2525 * REQPTIME(reqp) - reqp's time stamp value
2526 * REQTIMESTAMP() - system time stamp value
2527 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002528typedef struct scsi_cmnd REQ, *REQP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529#define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
2530#define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
2531#define REQPTID(reqp) ((reqp)->device->id)
2532#define REQPTIME(reqp) ((reqp)->SCp.this_residual)
2533#define REQTIMESTAMP() (jiffies)
2534
2535#define REQTIMESTAT(function, ascq, reqp, tid) \
2536{ \
2537 /*
2538 * If the request time stamp is less than the system time stamp, then \
2539 * maybe the system time stamp wrapped. Set the request time to zero.\
2540 */ \
2541 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
2542 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
2543 } else { \
2544 /* Indicate an error occurred with the assertion. */ \
2545 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
2546 REQPTIME(reqp) = 0; \
2547 } \
2548 /* Handle first minimum time case without external initialization. */ \
2549 if (((ascq)->q_tot_cnt[tid] == 1) || \
2550 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
2551 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
2552 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
2553 (function), (tid), (ascq)->q_min_tim[tid]); \
2554 } \
2555 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
2556 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
2557 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
2558 (function), tid, (ascq)->q_max_tim[tid]); \
2559 } \
2560 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
2561 /* Reset the time stamp field. */ \
2562 REQPTIME(reqp) = 0; \
2563}
2564
2565/* asc_enqueue() flags */
2566#define ASC_FRONT 1
2567#define ASC_BACK 2
2568
2569/* asc_dequeue_list() argument */
2570#define ASC_TID_ALL (-1)
2571
2572/* Return non-zero, if the queue is empty. */
2573#define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
2574
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002576#define ASC_STATS(shost, counter)
2577#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002579#define ASC_STATS(shost, counter) \
2580 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002582#define ASC_STATS_ADD(shost, counter, count) \
2583 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584#endif /* ADVANSYS_STATS */
2585
2586#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2587
2588/* If the result wraps when calculating tenths, return 0. */
2589#define ASC_TENTHS(num, den) \
2590 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2591 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2592
2593/*
2594 * Display a message to the console.
2595 */
2596#define ASC_PRINT(s) \
2597 { \
2598 printk("advansys: "); \
2599 printk(s); \
2600 }
2601
2602#define ASC_PRINT1(s, a1) \
2603 { \
2604 printk("advansys: "); \
2605 printk((s), (a1)); \
2606 }
2607
2608#define ASC_PRINT2(s, a1, a2) \
2609 { \
2610 printk("advansys: "); \
2611 printk((s), (a1), (a2)); \
2612 }
2613
2614#define ASC_PRINT3(s, a1, a2, a3) \
2615 { \
2616 printk("advansys: "); \
2617 printk((s), (a1), (a2), (a3)); \
2618 }
2619
2620#define ASC_PRINT4(s, a1, a2, a3, a4) \
2621 { \
2622 printk("advansys: "); \
2623 printk((s), (a1), (a2), (a3), (a4)); \
2624 }
2625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626#ifndef ADVANSYS_DEBUG
2627
2628#define ASC_DBG(lvl, s)
2629#define ASC_DBG1(lvl, s, a1)
2630#define ASC_DBG2(lvl, s, a1, a2)
2631#define ASC_DBG3(lvl, s, a1, a2, a3)
2632#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2633#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2634#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
2635#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2636#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2637#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2638#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2639#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2640#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2641#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2642#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2643
2644#else /* ADVANSYS_DEBUG */
2645
2646/*
2647 * Debugging Message Levels:
2648 * 0: Errors Only
2649 * 1: High-Level Tracing
2650 * 2-N: Verbose Tracing
2651 */
2652
2653#define ASC_DBG(lvl, s) \
2654 { \
2655 if (asc_dbglvl >= (lvl)) { \
2656 printk(s); \
2657 } \
2658 }
2659
2660#define ASC_DBG1(lvl, s, a1) \
2661 { \
2662 if (asc_dbglvl >= (lvl)) { \
2663 printk((s), (a1)); \
2664 } \
2665 }
2666
2667#define ASC_DBG2(lvl, s, a1, a2) \
2668 { \
2669 if (asc_dbglvl >= (lvl)) { \
2670 printk((s), (a1), (a2)); \
2671 } \
2672 }
2673
2674#define ASC_DBG3(lvl, s, a1, a2, a3) \
2675 { \
2676 if (asc_dbglvl >= (lvl)) { \
2677 printk((s), (a1), (a2), (a3)); \
2678 } \
2679 }
2680
2681#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2682 { \
2683 if (asc_dbglvl >= (lvl)) { \
2684 printk((s), (a1), (a2), (a3), (a4)); \
2685 } \
2686 }
2687
2688#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2689 { \
2690 if (asc_dbglvl >= (lvl)) { \
2691 asc_prt_scsi_host(s); \
2692 } \
2693 }
2694
2695#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
2696 { \
2697 if (asc_dbglvl >= (lvl)) { \
2698 asc_prt_scsi_cmnd(s); \
2699 } \
2700 }
2701
2702#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2703 { \
2704 if (asc_dbglvl >= (lvl)) { \
2705 asc_prt_asc_scsi_q(scsiqp); \
2706 } \
2707 }
2708
2709#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2710 { \
2711 if (asc_dbglvl >= (lvl)) { \
2712 asc_prt_asc_qdone_info(qdone); \
2713 } \
2714 }
2715
2716#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2717 { \
2718 if (asc_dbglvl >= (lvl)) { \
2719 asc_prt_adv_scsi_req_q(scsiqp); \
2720 } \
2721 }
2722
2723#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2724 { \
2725 if (asc_dbglvl >= (lvl)) { \
2726 asc_prt_hex((name), (start), (length)); \
2727 } \
2728 }
2729
2730#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2731 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2732
2733#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2734 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2735
2736#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2737 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2738#endif /* ADVANSYS_DEBUG */
2739
2740#ifndef ADVANSYS_ASSERT
2741#define ASC_ASSERT(a)
2742#else /* ADVANSYS_ASSERT */
2743
2744#define ASC_ASSERT(a) \
2745 { \
2746 if (!(a)) { \
2747 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
2748 __FILE__, __LINE__); \
2749 } \
2750 }
2751
2752#endif /* ADVANSYS_ASSERT */
2753
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754/*
2755 * --- Driver Structures
2756 */
2757
2758#ifdef ADVANSYS_STATS
2759
2760/* Per board statistics structure */
2761struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002762 /* Driver Entrypoint Statistics */
2763 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2764 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2765 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2766 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2767 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2768 ADV_DCNT done; /* # calls to request's scsi_done function */
2769 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2770 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2771 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2772 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2773 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2774 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2775 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2776 ADV_DCNT exe_unknown; /* # unknown returns. */
2777 /* Data Transfer Statistics */
2778 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2779 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2780 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2781 ADV_DCNT sg_elem; /* # scatter-gather elements */
2782 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783};
2784#endif /* ADVANSYS_STATS */
2785
2786/*
2787 * Request queuing structure
2788 */
2789typedef struct asc_queue {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002790 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
2791 REQP q_first[ADV_MAX_TID + 1]; /* first queued request */
2792 REQP q_last[ADV_MAX_TID + 1]; /* last queued request */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002794 short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */
2795 short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */
2796 ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */
2797 ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */
2798 ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */
2799 ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */
2800#endif /* ADVANSYS_STATS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801} asc_queue_t;
2802
2803/*
2804 * Adv Library Request Structures
2805 *
2806 * The following two structures are used to process Wide Board requests.
2807 *
2808 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2809 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2810 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2811 * Mid-Level SCSI request structure.
2812 *
2813 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2814 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2815 * up to 255 scatter-gather elements may be used per request or
2816 * ADV_SCSI_REQ_Q.
2817 *
2818 * Both structures must be 32 byte aligned.
2819 */
2820typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002821 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2822 uchar align[32]; /* Sgblock structure padding. */
2823 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824} adv_sgblk_t;
2825
2826typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002827 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2828 uchar align[32]; /* Request structure padding. */
2829 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2830 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2831 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832} adv_req_t;
2833
2834/*
2835 * Structure allocated for each board.
2836 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002837 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 * of the 'Scsi_Host' structure starting at the 'hostdata'
2839 * field. It is guaranteed to be allocated from DMA-able memory.
2840 */
2841typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002842 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002843 int id; /* Board Id */
2844 uint flags; /* Board flags */
2845 union {
2846 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2847 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2848 } dvc_var;
2849 union {
2850 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2851 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2852 } dvc_cfg;
2853 ushort asc_n_io_port; /* Number I/O ports. */
2854 asc_queue_t active; /* Active command queue */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002855 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
2856 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
2857 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2858 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2859 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2860 union {
2861 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2862 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2863 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2864 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2865 } eep_config;
2866 ulong last_reset; /* Saved last reset time */
2867 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002868 /* /proc/scsi/advansys/[0...] */
2869 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002871 struct asc_stats asc_stats; /* Board statistics */
2872#endif /* ADVANSYS_STATS */
2873 /*
2874 * The following fields are used only for Narrow Boards.
2875 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002876 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2877 /*
2878 * The following fields are used only for Wide Boards.
2879 */
2880 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2881 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002882 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002883 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2884 adv_req_t *adv_reqp; /* Request structures. */
2885 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2886 ushort bios_signature; /* BIOS Signature. */
2887 ushort bios_version; /* BIOS Version. */
2888 ushort bios_codeseg; /* BIOS Code Segment. */
2889 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890} asc_board_t;
2891
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002892#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2893 dvc_var.adv_dvc_var)
2894#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2895
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002897static int asc_board_count;
2898
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002900static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901
2902/*
2903 * Global structures required to issue a command.
2904 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002905static ASC_SCSI_Q asc_scsi_q = { {0} };
2906static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002909static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910#endif /* ADVANSYS_DEBUG */
2911
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912/*
2913 * --- Driver Function Prototypes
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914 */
2915
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002916static int advansys_slave_configure(struct scsi_device *);
2917static void asc_scsi_done_list(struct scsi_cmnd *);
2918static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
2919static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
2920static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
2921static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002922static void asc_enqueue(asc_queue_t *, REQP, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002923static REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
2924static int asc_rmqueue(asc_queue_t *, REQP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002926static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
2927static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
2928static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
2929static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
2930static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
2931static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
2932static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
2933static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
2934static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
2935static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936#endif /* CONFIG_PROC_FS */
2937
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938/* Statistics function prototypes. */
2939#ifdef ADVANSYS_STATS
2940#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002941static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
2942static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943#endif /* CONFIG_PROC_FS */
2944#endif /* ADVANSYS_STATS */
2945
2946/* Debug function prototypes. */
2947#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002948static void asc_prt_scsi_host(struct Scsi_Host *);
2949static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
2950static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
2951static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
2952static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
2953static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
2954static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
2955static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
2956static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
2957static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
2958static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959#endif /* ADVANSYS_DEBUG */
2960
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961#ifdef CONFIG_PROC_FS
2962/*
Matthew Wilcoxc304ec92007-07-30 09:18:45 -06002963 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 *
2965 * *buffer: I/O buffer
2966 * **start: if inout == FALSE pointer into buffer where user read should start
2967 * offset: current offset into a /proc/scsi/advansys/[0...] file
2968 * length: length of buffer
2969 * hostno: Scsi_Host host_no
2970 * inout: TRUE - user is writing; FALSE - user is reading
2971 *
2972 * Return the number of bytes read from or written to a
2973 * /proc/scsi/advansys/[0...] file.
2974 *
2975 * Note: This function uses the per board buffer 'prtbuf' which is
2976 * allocated when the board is initialized in advansys_detect(). The
2977 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
2978 * used to write to the buffer. The way asc_proc_copy() is written
2979 * if 'prtbuf' is too small it will not be overwritten. Instead the
2980 * user just won't get all the available statistics.
2981 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07002982static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002984 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002986 asc_board_t *boardp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002987 char *cp;
2988 int cplen;
2989 int cnt;
2990 int totcnt;
2991 int leftlen;
2992 char *curbuf;
2993 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002995 int tgt_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996#endif /* ADVANSYS_STATS */
2997
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002998 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003000 /*
3001 * User write not supported.
3002 */
3003 if (inout == TRUE) {
3004 return (-ENOSYS);
3005 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003007 /*
3008 * User read of /proc/scsi/advansys/[0...] file.
3009 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Matthew Wilcox2a437952007-07-26 11:00:51 -04003011 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003013 /* Copy read data starting at the beginning of the buffer. */
3014 *start = buffer;
3015 curbuf = buffer;
3016 advoffset = 0;
3017 totcnt = 0;
3018 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003020 /*
3021 * Get board configuration information.
3022 *
3023 * advansys_info() returns the board string from its own static buffer.
3024 */
Matthew Wilcox2a437952007-07-26 11:00:51 -04003025 cp = (char *)advansys_info(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003026 strcat(cp, "\n");
3027 cplen = strlen(cp);
3028 /* Copy board information. */
3029 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3030 totcnt += cnt;
3031 leftlen -= cnt;
3032 if (leftlen == 0) {
3033 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3034 return totcnt;
3035 }
3036 advoffset += cplen;
3037 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003039 /*
3040 * Display Wide Board BIOS Information.
3041 */
3042 if (ASC_WIDE_BOARD(boardp)) {
3043 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003044 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003045 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003046 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003047 cplen);
3048 totcnt += cnt;
3049 leftlen -= cnt;
3050 if (leftlen == 0) {
3051 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3052 return totcnt;
3053 }
3054 advoffset += cplen;
3055 curbuf += cnt;
3056 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003058 /*
3059 * Display driver information for each device attached to the board.
3060 */
3061 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003062 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003063 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3064 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3065 totcnt += cnt;
3066 leftlen -= cnt;
3067 if (leftlen == 0) {
3068 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3069 return totcnt;
3070 }
3071 advoffset += cplen;
3072 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003074 /*
3075 * Display EEPROM configuration for the board.
3076 */
3077 cp = boardp->prtbuf;
3078 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003079 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003080 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003081 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003082 }
3083 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3084 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3085 totcnt += cnt;
3086 leftlen -= cnt;
3087 if (leftlen == 0) {
3088 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3089 return totcnt;
3090 }
3091 advoffset += cplen;
3092 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003094 /*
3095 * Display driver configuration and information for the board.
3096 */
3097 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003098 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003099 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3100 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3101 totcnt += cnt;
3102 leftlen -= cnt;
3103 if (leftlen == 0) {
3104 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3105 return totcnt;
3106 }
3107 advoffset += cplen;
3108 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109
3110#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003111 /*
3112 * Display driver statistics for the board.
3113 */
3114 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003115 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003116 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
3117 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3118 totcnt += cnt;
3119 leftlen -= cnt;
3120 if (leftlen == 0) {
3121 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3122 return totcnt;
3123 }
3124 advoffset += cplen;
3125 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003127 /*
3128 * Display driver statistics for each target.
3129 */
3130 for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
3131 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04003132 cplen = asc_prt_target_stats(shost, tgt_id, cp,
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003133 ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003134 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003135 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
3136 cplen);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003137 totcnt += cnt;
3138 leftlen -= cnt;
3139 if (leftlen == 0) {
3140 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3141 return totcnt;
3142 }
3143 advoffset += cplen;
3144 curbuf += cnt;
3145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146#endif /* ADVANSYS_STATS */
3147
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003148 /*
3149 * Display Asc Library dynamic configuration information
3150 * for the board.
3151 */
3152 cp = boardp->prtbuf;
3153 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003154 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003155 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003156 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003157 }
3158 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
3159 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3160 totcnt += cnt;
3161 leftlen -= cnt;
3162 if (leftlen == 0) {
3163 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3164 return totcnt;
3165 }
3166 advoffset += cplen;
3167 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003169 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003171 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172}
3173#endif /* CONFIG_PROC_FS */
3174
3175/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 * advansys_info()
3177 *
3178 * Return suitable for printing on the console with the argument
3179 * adapter's configuration information.
3180 *
3181 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
3182 * otherwise the static 'info' array will be overrun.
3183 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003184static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003186 static char info[ASC_INFO_SIZE];
3187 asc_board_t *boardp;
3188 ASC_DVC_VAR *asc_dvc_varp;
3189 ADV_DVC_VAR *adv_dvc_varp;
3190 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003191 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003193 boardp = ASC_BOARDP(shost);
3194 if (ASC_NARROW_BOARD(boardp)) {
3195 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3196 ASC_DBG(1, "advansys_info: begin\n");
3197 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3198 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
3199 ASC_IS_ISAPNP) {
3200 busname = "ISA PnP";
3201 } else {
3202 busname = "ISA";
3203 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003204 sprintf(info,
3205 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
3206 ASC_VERSION, busname,
3207 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003208 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3209 shost->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003210 } else {
3211 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
3212 busname = "VL";
3213 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
3214 busname = "EISA";
3215 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
3216 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
3217 == ASC_IS_PCI_ULTRA) {
3218 busname = "PCI Ultra";
3219 } else {
3220 busname = "PCI";
3221 }
3222 } else {
3223 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003224 ASC_PRINT2("advansys_info: board %d: unknown "
3225 "bus type %d\n", boardp->id,
3226 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003227 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003228 sprintf(info,
3229 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003230 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003231 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3232 shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003233 }
3234 } else {
3235 /*
3236 * Wide Adapter Information
3237 *
3238 * Memory-mapped I/O is used instead of I/O space to access
3239 * the adapter, but display the I/O Port range. The Memory
3240 * I/O address is displayed through the driver /proc file.
3241 */
3242 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3243 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003244 widename = "Ultra-Wide";
3245 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003246 widename = "Ultra2-Wide";
3247 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003248 widename = "Ultra3-Wide";
3249 }
3250 sprintf(info,
3251 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
3252 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003253 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003254 }
3255 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
3256 ASC_DBG(1, "advansys_info: end\n");
3257 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258}
3259
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003260static void asc_scsi_done(struct scsi_cmnd *scp)
3261{
3262 struct asc_board *boardp = ASC_BOARDP(scp->device->host);
3263
3264 if (scp->use_sg)
3265 dma_unmap_sg(boardp->dev,
3266 (struct scatterlist *)scp->request_buffer,
3267 scp->use_sg, scp->sc_data_direction);
3268 else if (scp->request_bufflen)
3269 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
3270 scp->request_bufflen, scp->sc_data_direction);
3271
3272 ASC_STATS(scp->device->host, done);
3273
3274 scp->scsi_done(scp);
3275}
3276
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277/*
3278 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
3279 *
3280 * This function always returns 0. Command return status is saved
3281 * in the 'scp' result field.
3282 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003283static int
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003284advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003286 struct Scsi_Host *shost;
3287 asc_board_t *boardp;
3288 ulong flags;
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003289 int asc_res, result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003291 shost = scp->device->host;
3292 boardp = ASC_BOARDP(shost);
3293 ASC_STATS(shost, queuecommand);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003295 /* host_lock taken by mid-level prior to call but need to protect */
3296 /* against own ISR */
3297 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003299 scp->scsi_done = done;
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003300 asc_res = asc_execute_scsi_cmnd(scp);
3301 switch (asc_res) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003302 case ASC_NOERROR:
3303 break;
3304 case ASC_BUSY:
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003305 result = SCSI_MLQUEUE_HOST_BUSY;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003306 break;
3307 case ASC_ERROR:
3308 default:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003309 /* Interrupts could be enabled here. */
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003310 asc_scsi_done(scp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003311 break;
3312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003315 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316}
3317
3318/*
3319 * advansys_reset()
3320 *
3321 * Reset the bus associated with the command 'scp'.
3322 *
3323 * This function runs its own thread. Interrupts must be blocked but
3324 * sleeping is allowed and no locking other than for host structures is
3325 * required. Returns SUCCESS or FAILED.
3326 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003327static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003329 struct Scsi_Host *shost;
3330 asc_board_t *boardp;
3331 ASC_DVC_VAR *asc_dvc_varp;
3332 ADV_DVC_VAR *adv_dvc_varp;
3333 ulong flags;
3334 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
3335 struct scsi_cmnd *tscp, *new_last_scp;
3336 int status;
3337 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003339 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340
3341#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003342 if (scp->device->host != NULL) {
3343 ASC_STATS(scp->device->host, reset);
3344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345#endif /* ADVANSYS_STATS */
3346
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003347 if ((shost = scp->device->host) == NULL) {
3348 scp->result = HOST_BYTE(DID_ERROR);
3349 return FAILED;
3350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003352 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003354 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
3355 boardp->id);
3356 /*
3357 * Check for re-entrancy.
3358 */
3359 spin_lock_irqsave(&boardp->lock, flags);
3360 if (boardp->flags & ASC_HOST_IN_RESET) {
3361 spin_unlock_irqrestore(&boardp->lock, flags);
3362 return FAILED;
3363 }
3364 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003367 if (ASC_NARROW_BOARD(boardp)) {
3368 /*
3369 * Narrow Board
3370 */
3371 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003373 /*
3374 * Reset the chip and SCSI bus.
3375 */
3376 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
3377 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003379 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
3380 if (asc_dvc_varp->err_code) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003381 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3382 "error: 0x%x\n", boardp->id,
3383 asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003384 ret = FAILED;
3385 } else if (status) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003386 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3387 "warning: 0x%x\n", boardp->id, status);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003388 } else {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003389 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3390 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003393 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
3394 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003396 } else {
3397 /*
3398 * Wide Board
3399 *
3400 * If the suggest reset bus flags are set, then reset the bus.
3401 * Otherwise only reset the device.
3402 */
3403 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003405 /*
3406 * Reset the target's SCSI bus.
3407 */
3408 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
3409 switch (AdvResetChipAndSB(adv_dvc_varp)) {
3410 case ASC_TRUE:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003411 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3412 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003413 break;
3414 case ASC_FALSE:
3415 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003416 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3417 "error.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003418 ret = FAILED;
3419 break;
3420 }
3421 spin_lock_irqsave(&boardp->lock, flags);
3422 (void)AdvISR(adv_dvc_varp);
3423 }
3424 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003426 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003427 * Dequeue all board 'active' requests for all devices and set
3428 * the request status to DID_RESET. A pointer to the last request
3429 * is returned in 'last_scp'.
3430 */
3431 if (done_scp == NULL) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003432 done_scp = asc_dequeue_list(&boardp->active, &last_scp,
3433 ASC_TID_ALL);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003434 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
3435 tscp->result = HOST_BYTE(DID_RESET);
3436 }
3437 } else {
3438 /* Append to 'done_scp' at the end with 'last_scp'. */
3439 ASC_ASSERT(last_scp != NULL);
3440 last_scp->host_scribble =
3441 (unsigned char *)asc_dequeue_list(&boardp->active,
3442 &new_last_scp,
3443 ASC_TID_ALL);
3444 if (new_last_scp != NULL) {
3445 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
3446 for (tscp = REQPNEXT(last_scp); tscp;
3447 tscp = REQPNEXT(tscp)) {
3448 tscp->result = HOST_BYTE(DID_RESET);
3449 }
3450 last_scp = new_last_scp;
3451 }
3452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003454 /* Save the time of the most recently completed reset. */
3455 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003457 /* Clear reset flag. */
3458 boardp->flags &= ~ASC_HOST_IN_RESET;
3459 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003461 /*
3462 * Complete all the 'done_scp' requests.
3463 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003464 if (done_scp)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003465 asc_scsi_done_list(done_scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003467 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003469 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470}
3471
3472/*
3473 * advansys_biosparam()
3474 *
3475 * Translate disk drive geometry if the "BIOS greater than 1 GB"
3476 * support is enabled for a drive.
3477 *
3478 * ip (information pointer) is an int array with the following definition:
3479 * ip[0]: heads
3480 * ip[1]: sectors
3481 * ip[2]: cylinders
3482 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003483static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003485 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003487 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003489 ASC_DBG(1, "advansys_biosparam: begin\n");
3490 ASC_STATS(sdev->host, biosparam);
3491 boardp = ASC_BOARDP(sdev->host);
3492 if (ASC_NARROW_BOARD(boardp)) {
3493 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
3494 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
3495 ip[0] = 255;
3496 ip[1] = 63;
3497 } else {
3498 ip[0] = 64;
3499 ip[1] = 32;
3500 }
3501 } else {
3502 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
3503 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
3504 ip[0] = 255;
3505 ip[1] = 63;
3506 } else {
3507 ip[0] = 64;
3508 ip[1] = 32;
3509 }
3510 }
3511 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
3512 ASC_DBG(1, "advansys_biosparam: end\n");
3513 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514}
3515
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003516static struct scsi_host_template advansys_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003517 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003519 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003521 .name = "advansys",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003522 .info = advansys_info,
3523 .queuecommand = advansys_queuecommand,
3524 .eh_bus_reset_handler = advansys_reset,
3525 .bios_param = advansys_biosparam,
3526 .slave_configure = advansys_slave_configure,
3527 /*
3528 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003529 * must be set. The flag will be cleared in advansys_board_found
3530 * for non-ISA adapters.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003531 */
3532 .unchecked_isa_dma = 1,
3533 /*
3534 * All adapters controlled by this driver are capable of large
3535 * scatter-gather lists. According to the mid-level SCSI documentation
3536 * this obviates any performance gain provided by setting
3537 * 'use_clustering'. But empirically while CPU utilization is increased
3538 * by enabling clustering, I/O throughput increases as well.
3539 */
3540 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543/*
3544 * --- Miscellaneous Driver Functions
3545 */
3546
3547/*
3548 * First-level interrupt handler.
3549 *
3550 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
3551 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
3552 * is not referenced. 'dev_id' could be used to identify an interrupt passed
3553 * to the AdvanSys driver which is for a device sharing an interrupt with
3554 * an AdvanSys adapter.
3555 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003556static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557{
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003558 unsigned long flags;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003559 struct Scsi_Host *shost = dev_id;
3560 asc_board_t *boardp = ASC_BOARDP(shost);
3561 irqreturn_t result = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003563 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
3564 spin_lock_irqsave(&boardp->lock, flags);
3565 if (ASC_NARROW_BOARD(boardp)) {
3566 /*
3567 * Narrow Board
3568 */
3569 if (AscIsIntPending(shost->io_port)) {
3570 result = IRQ_HANDLED;
3571 ASC_STATS(shost, interrupt);
3572 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
3573 AscISR(&boardp->dvc_var.asc_dvc_var);
3574 }
3575 } else {
3576 /*
3577 * Wide Board
3578 */
3579 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
3580 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
3581 result = IRQ_HANDLED;
3582 ASC_STATS(shost, interrupt);
3583 }
3584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003586 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003588 /*
3589 * If interrupts were enabled on entry, then they
3590 * are now enabled here.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003591 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003593 ASC_DBG(1, "advansys_interrupt: end\n");
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003594 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595}
3596
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003597static void
3598advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
3599{
3600 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
3601 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
3602
3603 if (sdev->lun == 0) {
3604 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
3605 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
3606 asc_dvc->init_sdtr |= tid_bit;
3607 } else {
3608 asc_dvc->init_sdtr &= ~tid_bit;
3609 }
3610
3611 if (orig_init_sdtr != asc_dvc->init_sdtr)
3612 AscAsyncFix(asc_dvc, sdev);
3613 }
3614
3615 if (sdev->tagged_supported) {
3616 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
3617 if (sdev->lun == 0) {
3618 asc_dvc->cfg->can_tagged_qng |= tid_bit;
3619 asc_dvc->use_tagged_qng |= tid_bit;
3620 }
3621 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3622 asc_dvc->max_dvc_qng[sdev->id]);
3623 }
3624 } else {
3625 if (sdev->lun == 0) {
3626 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
3627 asc_dvc->use_tagged_qng &= ~tid_bit;
3628 }
3629 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3630 }
3631
3632 if ((sdev->lun == 0) &&
3633 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
3634 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
3635 asc_dvc->cfg->disc_enable);
3636 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
3637 asc_dvc->use_tagged_qng);
3638 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
3639 asc_dvc->cfg->can_tagged_qng);
3640
3641 asc_dvc->max_dvc_qng[sdev->id] =
3642 asc_dvc->cfg->max_tag_qng[sdev->id];
3643 AscWriteLramByte(asc_dvc->iop_base,
3644 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
3645 asc_dvc->max_dvc_qng[sdev->id]);
3646 }
3647}
3648
3649/*
3650 * Wide Transfers
3651 *
3652 * If the EEPROM enabled WDTR for the device and the device supports wide
3653 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
3654 * write the new value to the microcode.
3655 */
3656static void
3657advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
3658{
3659 unsigned short cfg_word;
3660 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3661 if ((cfg_word & tidmask) != 0)
3662 return;
3663
3664 cfg_word |= tidmask;
3665 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3666
3667 /*
3668 * Clear the microcode SDTR and WDTR negotiation done indicators for
3669 * the target to cause it to negotiate with the new setting set above.
3670 * WDTR when accepted causes the target to enter asynchronous mode, so
3671 * SDTR must be negotiated.
3672 */
3673 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3674 cfg_word &= ~tidmask;
3675 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3676 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3677 cfg_word &= ~tidmask;
3678 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3679}
3680
3681/*
3682 * Synchronous Transfers
3683 *
3684 * If the EEPROM enabled SDTR for the device and the device
3685 * supports synchronous transfers, then turn on the device's
3686 * 'sdtr_able' bit. Write the new value to the microcode.
3687 */
3688static void
3689advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
3690{
3691 unsigned short cfg_word;
3692 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3693 if ((cfg_word & tidmask) != 0)
3694 return;
3695
3696 cfg_word |= tidmask;
3697 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3698
3699 /*
3700 * Clear the microcode "SDTR negotiation" done indicator for the
3701 * target to cause it to negotiate with the new setting set above.
3702 */
3703 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3704 cfg_word &= ~tidmask;
3705 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3706}
3707
3708/*
3709 * PPR (Parallel Protocol Request) Capable
3710 *
3711 * If the device supports DT mode, then it must be PPR capable.
3712 * The PPR message will be used in place of the SDTR and WDTR
3713 * messages to negotiate synchronous speed and offset, transfer
3714 * width, and protocol options.
3715 */
3716static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
3717 AdvPortAddr iop_base, unsigned short tidmask)
3718{
3719 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3720 adv_dvc->ppr_able |= tidmask;
3721 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3722}
3723
3724static void
3725advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
3726{
3727 AdvPortAddr iop_base = adv_dvc->iop_base;
3728 unsigned short tidmask = 1 << sdev->id;
3729
3730 if (sdev->lun == 0) {
3731 /*
3732 * Handle WDTR, SDTR, and Tag Queuing. If the feature
3733 * is enabled in the EEPROM and the device supports the
3734 * feature, then enable it in the microcode.
3735 */
3736
3737 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
3738 advansys_wide_enable_wdtr(iop_base, tidmask);
3739 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
3740 advansys_wide_enable_sdtr(iop_base, tidmask);
3741 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
3742 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
3743
3744 /*
3745 * Tag Queuing is disabled for the BIOS which runs in polled
3746 * mode and would see no benefit from Tag Queuing. Also by
3747 * disabling Tag Queuing in the BIOS devices with Tag Queuing
3748 * bugs will at least work with the BIOS.
3749 */
3750 if ((adv_dvc->tagqng_able & tidmask) &&
3751 sdev->tagged_supported) {
3752 unsigned short cfg_word;
3753 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
3754 cfg_word |= tidmask;
3755 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
3756 cfg_word);
3757 AdvWriteByteLram(iop_base,
3758 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
3759 adv_dvc->max_dvc_qng);
3760 }
3761 }
3762
3763 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
3764 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3765 adv_dvc->max_dvc_qng);
3766 } else {
3767 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3768 }
3769}
3770
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771/*
3772 * Set the number of commands to queue per device for the
3773 * specified host adapter.
3774 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003775static int advansys_slave_configure(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003777 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003778 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003779
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003780 /*
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003781 * Save a pointer to the sdev and set its initial/maximum
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003782 * queue depth. Only save the pointer for a lun0 dev though.
3783 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003784 if (sdev->lun == 0)
3785 boardp->device[sdev->id] = sdev;
3786
3787 if (ASC_NARROW_BOARD(boardp))
3788 advansys_narrow_slave_configure(sdev,
3789 &boardp->dvc_var.asc_dvc_var);
3790 else
3791 advansys_wide_slave_configure(sdev,
3792 &boardp->dvc_var.adv_dvc_var);
3793
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003794 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795}
3796
3797/*
3798 * Complete all requests on the singly linked list pointed
3799 * to by 'scp'.
3800 *
3801 * Interrupts can be enabled on entry.
3802 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003803static void asc_scsi_done_list(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003805 struct scsi_cmnd *tscp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003807 ASC_DBG(2, "asc_scsi_done_list: begin\n");
3808 while (scp != NULL) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003809 ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
3810 tscp = REQPNEXT(scp);
3811 scp->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003813 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003815 scp = tscp;
3816 }
3817 ASC_DBG(2, "asc_scsi_done_list: done\n");
3818 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819}
3820
3821/*
3822 * Execute a single 'Scsi_Cmnd'.
3823 *
3824 * The function 'done' is called when the request has been completed.
3825 *
3826 * Scsi_Cmnd:
3827 *
3828 * host - board controlling device
3829 * device - device to send command
3830 * target - target of device
3831 * lun - lun of device
3832 * cmd_len - length of SCSI CDB
3833 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
3834 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
3835 *
3836 * if (use_sg == 0) {
3837 * request_buffer - buffer address for request
3838 * request_bufflen - length of request buffer
3839 * } else {
3840 * request_buffer - pointer to scatterlist structure
3841 * }
3842 *
3843 * sense_buffer - sense command buffer
3844 *
3845 * result (4 bytes of an int):
3846 * Byte Meaning
3847 * 0 SCSI Status Byte Code
3848 * 1 SCSI One Byte Message Code
3849 * 2 Host Error Code
3850 * 3 Mid-Level Error Code
3851 *
3852 * host driver fields:
3853 * SCp - Scsi_Pointer used for command processing status
3854 * scsi_done - used to save caller's done function
3855 * host_scribble - used for pointer to another struct scsi_cmnd
3856 *
3857 * If this function returns ASC_NOERROR the request has been enqueued
3858 * on the board's 'active' queue and will be completed from the
3859 * interrupt handler.
3860 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003861 * If this function returns ASC_ERROR the host error code has been set,
3862 * and the called must call asc_scsi_done.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 *
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003864 * If ASC_BUSY is returned the request will be returned to the midlayer
3865 * and re-tried later.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003867static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003869 asc_board_t *boardp;
3870 ASC_DVC_VAR *asc_dvc_varp;
3871 ADV_DVC_VAR *adv_dvc_varp;
3872 ADV_SCSI_REQ_Q *adv_scsiqp;
3873 struct scsi_device *device;
3874 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003876 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
3877 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003879 boardp = ASC_BOARDP(scp->device->host);
3880 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003882 if (ASC_NARROW_BOARD(boardp)) {
3883 /*
3884 * Build and execute Narrow Board request.
3885 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003887 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003889 /*
3890 * Build Asc Library request structure using the
3891 * global structures 'asc_scsi_req' and 'asc_sg_head'.
3892 *
3893 * If an error is returned, then the request has been
3894 * queued on the board done queue. It will be completed
3895 * by the caller.
3896 *
3897 * asc_build_req() can not return ASC_BUSY.
3898 */
3899 if (asc_build_req(boardp, scp) == ASC_ERROR) {
3900 ASC_STATS(scp->device->host, build_error);
3901 return ASC_ERROR;
3902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003904 /*
3905 * Execute the command. If there is no error, add the command
3906 * to the active queue.
3907 */
3908 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
3909 case ASC_NOERROR:
3910 ASC_STATS(scp->device->host, exe_noerror);
3911 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003912 * Increment monotonically increasing per device
3913 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003914 */
3915 boardp->reqcnt[scp->device->id]++;
3916 asc_enqueue(&boardp->active, scp, ASC_BACK);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003917 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), "
3918 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003919 break;
3920 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003921 ASC_STATS(scp->device->host, exe_busy);
3922 break;
3923 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003924 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3925 "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3926 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003927 ASC_STATS(scp->device->host, exe_error);
3928 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003929 break;
3930 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003931 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3932 "AscExeScsiQueue() unknown, err_code 0x%x\n",
3933 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003934 ASC_STATS(scp->device->host, exe_unknown);
3935 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003936 break;
3937 }
3938 } else {
3939 /*
3940 * Build and execute Wide Board request.
3941 */
3942 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003944 /*
3945 * Build and get a pointer to an Adv Library request structure.
3946 *
3947 * If the request is successfully built then send it below,
3948 * otherwise return with an error.
3949 */
3950 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
3951 case ASC_NOERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003952 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
3953 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003954 break;
3955 case ASC_BUSY:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003956 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3957 "ASC_BUSY\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003958 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003959 * The asc_stats fields 'adv_build_noreq' and
3960 * 'adv_build_nosg' count wide board busy conditions.
3961 * They are updated in adv_build_req and
3962 * adv_get_sglist, respectively.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003963 */
3964 return ASC_BUSY;
3965 case ASC_ERROR:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003966 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003967 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3968 "ASC_ERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003969 ASC_STATS(scp->device->host, build_error);
3970 return ASC_ERROR;
3971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003973 /*
3974 * Execute the command. If there is no error, add the command
3975 * to the active queue.
3976 */
3977 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
3978 case ASC_NOERROR:
3979 ASC_STATS(scp->device->host, exe_noerror);
3980 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003981 * Increment monotonically increasing per device
3982 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003983 */
3984 boardp->reqcnt[scp->device->id]++;
3985 asc_enqueue(&boardp->active, scp, ASC_BACK);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003986 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), "
3987 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003988 break;
3989 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003990 ASC_STATS(scp->device->host, exe_busy);
3991 break;
3992 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003993 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3994 "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3995 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003996 ASC_STATS(scp->device->host, exe_error);
3997 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003998 break;
3999 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004000 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
4001 "AdvExeScsiQueue() unknown, err_code 0x%x\n",
4002 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004003 ASC_STATS(scp->device->host, exe_unknown);
4004 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004005 break;
4006 }
4007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004009 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
4010 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011}
4012
4013/*
4014 * Build a request structure for the Asc Library (Narrow Board).
4015 *
4016 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
4017 * used to build the request.
4018 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004019 * If an error occurs, then return ASC_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004021static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004023 /*
4024 * Mutually exclusive access is required to 'asc_scsi_q' and
4025 * 'asc_sg_head' until after the request is started.
4026 */
4027 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004029 /*
4030 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
4031 */
4032 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004034 /*
4035 * Build the ASC_SCSI_Q request.
4036 *
4037 * For narrow boards a CDB length maximum of 12 bytes
4038 * is supported.
4039 */
4040 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06004041 ASC_PRINT3("asc_build_req: board %d: cmd_len %d > "
4042 "ASC_MAX_CDB_LEN %d\n", boardp->id, scp->cmd_len,
4043 ASC_MAX_CDB_LEN);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004044 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004045 return ASC_ERROR;
4046 }
4047 asc_scsi_q.cdbptr = &scp->cmnd[0];
4048 asc_scsi_q.q2.cdb_len = scp->cmd_len;
4049 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
4050 asc_scsi_q.q1.target_lun = scp->device->lun;
4051 asc_scsi_q.q2.target_ix =
4052 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
4053 asc_scsi_q.q1.sense_addr =
4054 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4055 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004057 /*
4058 * If there are any outstanding requests for the current target,
4059 * then every 255th request send an ORDERED request. This heuristic
4060 * tries to retain the benefit of request sorting while preventing
4061 * request starvation. 255 is the max number of tags or pending commands
4062 * a device may have outstanding.
4063 *
4064 * The request count is incremented below for every successfully
4065 * started request.
4066 *
4067 */
4068 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
4069 (boardp->reqcnt[scp->device->id] % 255) == 0) {
4070 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
4071 } else {
4072 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
4073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004075 /*
4076 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
4077 * buffer command.
4078 */
4079 if (scp->use_sg == 0) {
4080 /*
4081 * CDB request of single contiguous buffer.
4082 */
4083 ASC_STATS(scp->device->host, cont_cnt);
4084 scp->SCp.dma_handle = scp->request_bufflen ?
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004085 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004086 scp->request_bufflen,
4087 scp->sc_data_direction) : 0;
4088 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
4089 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
4090 ASC_STATS_ADD(scp->device->host, cont_xfer,
4091 ASC_CEILING(scp->request_bufflen, 512));
4092 asc_scsi_q.q1.sg_queue_cnt = 0;
4093 asc_scsi_q.sg_head = NULL;
4094 } else {
4095 /*
4096 * CDB scatter-gather request list.
4097 */
4098 int sgcnt;
4099 int use_sg;
4100 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004102 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004103 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4104 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004106 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004107 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
4108 "sg_tablesize %d\n", boardp->id, use_sg,
4109 scp->device->host->sg_tablesize);
4110 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004111 scp->sc_data_direction);
4112 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004113 return ASC_ERROR;
4114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004116 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004118 /*
4119 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
4120 * structure to point to it.
4121 */
4122 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004124 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
4125 asc_scsi_q.sg_head = &asc_sg_head;
4126 asc_scsi_q.q1.data_cnt = 0;
4127 asc_scsi_q.q1.data_addr = 0;
4128 /* This is a byte value, otherwise it would need to be swapped. */
4129 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
4130 ASC_STATS_ADD(scp->device->host, sg_elem,
4131 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004133 /*
4134 * Convert scatter-gather list into ASC_SG_HEAD list.
4135 */
4136 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
4137 asc_sg_head.sg_list[sgcnt].addr =
4138 cpu_to_le32(sg_dma_address(slp));
4139 asc_sg_head.sg_list[sgcnt].bytes =
4140 cpu_to_le32(sg_dma_len(slp));
4141 ASC_STATS_ADD(scp->device->host, sg_xfer,
4142 ASC_CEILING(sg_dma_len(slp), 512));
4143 }
4144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004146 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
4147 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004149 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150}
4151
4152/*
4153 * Build a request structure for the Adv Library (Wide Board).
4154 *
4155 * If an adv_req_t can not be allocated to issue the request,
4156 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
4157 *
4158 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
4159 * microcode for DMA addresses or math operations are byte swapped
4160 * to little-endian order.
4161 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004162static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004164 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004166 adv_req_t *reqp;
4167 ADV_SCSI_REQ_Q *scsiqp;
4168 int i;
4169 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004171 /*
4172 * Allocate an adv_req_t structure from the board to execute
4173 * the command.
4174 */
4175 if (boardp->adv_reqp == NULL) {
4176 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
4177 ASC_STATS(scp->device->host, adv_build_noreq);
4178 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004180 reqp = boardp->adv_reqp;
4181 boardp->adv_reqp = reqp->next_reqp;
4182 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004185 /*
4186 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
4187 */
4188 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004190 /*
4191 * Initialize the structure.
4192 */
4193 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004195 /*
4196 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
4197 */
4198 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004200 /*
4201 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
4202 */
4203 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004205 /*
4206 * Build the ADV_SCSI_REQ_Q request.
4207 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004209 /*
4210 * Set CDB length and copy it to the request structure.
4211 * For wide boards a CDB length maximum of 16 bytes
4212 * is supported.
4213 */
4214 if (scp->cmd_len > ADV_MAX_CDB_LEN) {
4215 ASC_PRINT3
4216 ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n",
4217 boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
4218 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004219 return ASC_ERROR;
4220 }
4221 scsiqp->cdb_len = scp->cmd_len;
4222 /* Copy first 12 CDB bytes to cdb[]. */
4223 for (i = 0; i < scp->cmd_len && i < 12; i++) {
4224 scsiqp->cdb[i] = scp->cmnd[i];
4225 }
4226 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
4227 for (; i < scp->cmd_len; i++) {
4228 scsiqp->cdb16[i - 12] = scp->cmnd[i];
4229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004231 scsiqp->target_id = scp->device->id;
4232 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004234 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
4235 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004237 /*
4238 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
4239 * buffer command.
4240 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004242 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4243 scsiqp->vdata_addr = scp->request_buffer;
4244 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
4245
4246 if (scp->use_sg == 0) {
4247 /*
4248 * CDB request of single contiguous buffer.
4249 */
4250 reqp->sgblkp = NULL;
4251 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4252 if (scp->request_bufflen) {
4253 scsiqp->vdata_addr = scp->request_buffer;
4254 scp->SCp.dma_handle =
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004255 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004256 scp->request_bufflen,
4257 scp->sc_data_direction);
4258 } else {
4259 scsiqp->vdata_addr = NULL;
4260 scp->SCp.dma_handle = 0;
4261 }
4262 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
4263 scsiqp->sg_list_ptr = NULL;
4264 scsiqp->sg_real_addr = 0;
4265 ASC_STATS(scp->device->host, cont_cnt);
4266 ASC_STATS_ADD(scp->device->host, cont_xfer,
4267 ASC_CEILING(scp->request_bufflen, 512));
4268 } else {
4269 /*
4270 * CDB scatter-gather request list.
4271 */
4272 struct scatterlist *slp;
4273 int use_sg;
4274
4275 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004276 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4277 scp->sc_data_direction);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004278
4279 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004280 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
4281 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
4282 scp->device->host->sg_tablesize);
4283 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004284 scp->sc_data_direction);
4285 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004286
4287 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004288 * Free the 'adv_req_t' structure by adding it back
4289 * to the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004290 */
4291 reqp->next_reqp = boardp->adv_reqp;
4292 boardp->adv_reqp = reqp;
4293
4294 return ASC_ERROR;
4295 }
4296
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004297 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
4298 if (ret != ADV_SUCCESS) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004299 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004300 * Free the adv_req_t structure by adding it back to
4301 * the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004302 */
4303 reqp->next_reqp = boardp->adv_reqp;
4304 boardp->adv_reqp = reqp;
4305
4306 return ret;
4307 }
4308
4309 ASC_STATS(scp->device->host, sg_cnt);
4310 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
4311 }
4312
4313 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
4314 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
4315
4316 *adv_scsiqpp = scsiqp;
4317
4318 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319}
4320
4321/*
4322 * Build scatter-gather list for Adv Library (Wide Board).
4323 *
4324 * Additional ADV_SG_BLOCK structures will need to be allocated
4325 * if the total number of scatter-gather elements exceeds
4326 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
4327 * assumed to be physically contiguous.
4328 *
4329 * Return:
4330 * ADV_SUCCESS(1) - SG List successfully created
4331 * ADV_ERROR(-1) - SG List creation failed
4332 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004333static int
4334adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
4335 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004337 adv_sgblk_t *sgblkp;
4338 ADV_SCSI_REQ_Q *scsiqp;
4339 struct scatterlist *slp;
4340 int sg_elem_cnt;
4341 ADV_SG_BLOCK *sg_block, *prev_sg_block;
4342 ADV_PADDR sg_block_paddr;
4343 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004345 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
4346 slp = (struct scatterlist *)scp->request_buffer;
4347 sg_elem_cnt = use_sg;
4348 prev_sg_block = NULL;
4349 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004351 do {
4352 /*
4353 * Allocate a 'adv_sgblk_t' structure from the board free
4354 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
4355 * (15) scatter-gather elements.
4356 */
4357 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
4358 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
4359 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004361 /*
4362 * Allocation failed. Free 'adv_sgblk_t' structures already
4363 * allocated for the request.
4364 */
4365 while ((sgblkp = reqp->sgblkp) != NULL) {
4366 /* Remove 'sgblkp' from the request list. */
4367 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004369 /* Add 'sgblkp' to the board free list. */
4370 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4371 boardp->adv_sgblkp = sgblkp;
4372 }
4373 return ASC_BUSY;
4374 } else {
4375 /* Complete 'adv_sgblk_t' board allocation. */
4376 boardp->adv_sgblkp = sgblkp->next_sgblkp;
4377 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004379 /*
4380 * Get 8 byte aligned virtual and physical addresses for
4381 * the allocated ADV_SG_BLOCK structure.
4382 */
4383 sg_block =
4384 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
4385 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004387 /*
4388 * Check if this is the first 'adv_sgblk_t' for the request.
4389 */
4390 if (reqp->sgblkp == NULL) {
4391 /* Request's first scatter-gather block. */
4392 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004394 /*
4395 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
4396 * address pointers.
4397 */
4398 scsiqp->sg_list_ptr = sg_block;
4399 scsiqp->sg_real_addr =
4400 cpu_to_le32(sg_block_paddr);
4401 } else {
4402 /* Request's second or later scatter-gather block. */
4403 sgblkp->next_sgblkp = reqp->sgblkp;
4404 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004406 /*
4407 * Point the previous ADV_SG_BLOCK structure to
4408 * the newly allocated ADV_SG_BLOCK structure.
4409 */
4410 ASC_ASSERT(prev_sg_block != NULL);
4411 prev_sg_block->sg_ptr =
4412 cpu_to_le32(sg_block_paddr);
4413 }
4414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004416 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
4417 sg_block->sg_list[i].sg_addr =
4418 cpu_to_le32(sg_dma_address(slp));
4419 sg_block->sg_list[i].sg_count =
4420 cpu_to_le32(sg_dma_len(slp));
4421 ASC_STATS_ADD(scp->device->host, sg_xfer,
4422 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004424 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
4425 sg_block->sg_cnt = i + 1;
4426 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
4427 return ADV_SUCCESS;
4428 }
4429 slp++;
4430 }
4431 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
4432 prev_sg_block = sg_block;
4433 }
4434 while (1);
4435 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436}
4437
4438/*
4439 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
4440 *
4441 * Interrupt callback function for the Narrow SCSI Asc Library.
4442 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004443static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004445 asc_board_t *boardp;
4446 struct scsi_cmnd *scp;
4447 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004449 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
4450 (ulong)asc_dvc_varp, (ulong)qdonep);
4451 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004453 /*
4454 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4455 * command that has been completed.
4456 */
4457 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
4458 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004460 if (scp == NULL) {
4461 ASC_PRINT("asc_isr_callback: scp is NULL\n");
4462 return;
4463 }
4464 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004466 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004467 ASC_STATS(shost, callback);
4468 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004470 /*
4471 * If the request isn't found on the active queue, it may
4472 * have been removed to handle a reset request.
4473 * Display a message and return.
4474 */
4475 boardp = ASC_BOARDP(shost);
4476 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
4477 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
4478 ASC_PRINT2
4479 ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n",
4480 boardp->id, (ulong)scp);
4481 return;
4482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004484 /*
4485 * 'qdonep' contains the command's ending status.
4486 */
4487 switch (qdonep->d3.done_stat) {
4488 case QD_NO_ERROR:
4489 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
4490 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004492 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004493 * Check for an underrun condition.
4494 *
4495 * If there was no error and an underrun condition, then
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004496 * return the number of underrun bytes.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004497 */
4498 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
4499 qdonep->remain_bytes <= scp->request_bufflen) {
4500 ASC_DBG1(1,
4501 "asc_isr_callback: underrun condition %u bytes\n",
4502 (unsigned)qdonep->remain_bytes);
4503 scp->resid = qdonep->remain_bytes;
4504 }
4505 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004507 case QD_WITH_ERROR:
4508 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
4509 switch (qdonep->d3.host_stat) {
4510 case QHSTA_NO_ERROR:
4511 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
4512 ASC_DBG(2,
4513 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4514 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4515 sizeof(scp->sense_buffer));
4516 /*
4517 * Note: The 'status_byte()' macro used by target drivers
4518 * defined in scsi.h shifts the status byte returned by
4519 * host drivers right by 1 bit. This is why target drivers
4520 * also use right shifted status byte definitions. For
4521 * instance target drivers use CHECK_CONDITION, defined to
4522 * 0x1, instead of the SCSI defined check condition value
4523 * of 0x2. Host drivers are supposed to return the status
4524 * byte as it is defined by SCSI.
4525 */
4526 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4527 STATUS_BYTE(qdonep->d3.scsi_stat);
4528 } else {
4529 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
4530 }
4531 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004533 default:
4534 /* QHSTA error occurred */
4535 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
4536 qdonep->d3.host_stat);
4537 scp->result = HOST_BYTE(DID_BAD_TARGET);
4538 break;
4539 }
4540 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004542 case QD_ABORTED_BY_HOST:
4543 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
4544 scp->result =
4545 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
4546 scsi_msg) |
4547 STATUS_BYTE(qdonep->d3.scsi_stat);
4548 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004550 default:
4551 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
4552 qdonep->d3.done_stat);
4553 scp->result =
4554 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
4555 scsi_msg) |
4556 STATUS_BYTE(qdonep->d3.scsi_stat);
4557 break;
4558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004560 /*
4561 * If the 'init_tidmask' bit isn't already set for the target and the
4562 * current request finished normally, then set the bit for the target
4563 * to indicate that a device is present.
4564 */
4565 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4566 qdonep->d3.done_stat == QD_NO_ERROR &&
4567 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
4568 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004571 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004573 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574}
4575
4576/*
4577 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
4578 *
4579 * Callback function for the Wide SCSI Adv Library.
4580 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004581static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004583 asc_board_t *boardp;
4584 adv_req_t *reqp;
4585 adv_sgblk_t *sgblkp;
4586 struct scsi_cmnd *scp;
4587 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004588 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004590 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
4591 (ulong)adv_dvc_varp, (ulong)scsiqp);
4592 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004594 /*
4595 * Get the adv_req_t structure for the command that has been
4596 * completed. The adv_req_t structure actually contains the
4597 * completed ADV_SCSI_REQ_Q structure.
4598 */
4599 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
4600 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
4601 if (reqp == NULL) {
4602 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
4603 return;
4604 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004606 /*
4607 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4608 * command that has been completed.
4609 *
4610 * Note: The adv_req_t request structure and adv_sgblk_t structure,
4611 * if any, are dropped, because a board structure pointer can not be
4612 * determined.
4613 */
4614 scp = reqp->cmndp;
4615 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
4616 if (scp == NULL) {
4617 ASC_PRINT
4618 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
4619 return;
4620 }
4621 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004623 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004624 ASC_STATS(shost, callback);
4625 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004627 /*
4628 * If the request isn't found on the active queue, it may have been
4629 * removed to handle a reset request. Display a message and return.
4630 *
4631 * Note: Because the structure may still be in use don't attempt
4632 * to free the adv_req_t and adv_sgblk_t, if any, structures.
4633 */
4634 boardp = ASC_BOARDP(shost);
4635 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
4636 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
4637 ASC_PRINT2
4638 ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n",
4639 boardp->id, (ulong)scp);
4640 return;
4641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004643 /*
4644 * 'done_status' contains the command's ending status.
4645 */
4646 switch (scsiqp->done_status) {
4647 case QD_NO_ERROR:
4648 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
4649 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004651 /*
4652 * Check for an underrun condition.
4653 *
4654 * If there was no error and an underrun condition, then
4655 * then return the number of underrun bytes.
4656 */
4657 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
4658 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
4659 resid_cnt <= scp->request_bufflen) {
4660 ASC_DBG1(1,
4661 "adv_isr_callback: underrun condition %lu bytes\n",
4662 (ulong)resid_cnt);
4663 scp->resid = resid_cnt;
4664 }
4665 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004667 case QD_WITH_ERROR:
4668 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
4669 switch (scsiqp->host_status) {
4670 case QHSTA_NO_ERROR:
4671 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
4672 ASC_DBG(2,
4673 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4674 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4675 sizeof(scp->sense_buffer));
4676 /*
4677 * Note: The 'status_byte()' macro used by target drivers
4678 * defined in scsi.h shifts the status byte returned by
4679 * host drivers right by 1 bit. This is why target drivers
4680 * also use right shifted status byte definitions. For
4681 * instance target drivers use CHECK_CONDITION, defined to
4682 * 0x1, instead of the SCSI defined check condition value
4683 * of 0x2. Host drivers are supposed to return the status
4684 * byte as it is defined by SCSI.
4685 */
4686 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4687 STATUS_BYTE(scsiqp->scsi_status);
4688 } else {
4689 scp->result = STATUS_BYTE(scsiqp->scsi_status);
4690 }
4691 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004693 default:
4694 /* Some other QHSTA error occurred. */
4695 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
4696 scsiqp->host_status);
4697 scp->result = HOST_BYTE(DID_BAD_TARGET);
4698 break;
4699 }
4700 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004702 case QD_ABORTED_BY_HOST:
4703 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
4704 scp->result =
4705 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
4706 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004708 default:
4709 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
4710 scsiqp->done_status);
4711 scp->result =
4712 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
4713 break;
4714 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004716 /*
4717 * If the 'init_tidmask' bit isn't already set for the target and the
4718 * current request finished normally, then set the bit for the target
4719 * to indicate that a device is present.
4720 */
4721 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4722 scsiqp->done_status == QD_NO_ERROR &&
4723 scsiqp->host_status == QHSTA_NO_ERROR) {
4724 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004727 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004729 /*
4730 * Free all 'adv_sgblk_t' structures allocated for the request.
4731 */
4732 while ((sgblkp = reqp->sgblkp) != NULL) {
4733 /* Remove 'sgblkp' from the request list. */
4734 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004736 /* Add 'sgblkp' to the board free list. */
4737 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4738 boardp->adv_sgblkp = sgblkp;
4739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004741 /*
4742 * Free the adv_req_t structure used with the command by adding
4743 * it back to the board free list.
4744 */
4745 reqp->next_reqp = boardp->adv_reqp;
4746 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004748 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004750 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751}
4752
4753/*
4754 * adv_async_callback() - Adv Library asynchronous event callback function.
4755 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004756static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004758 switch (code) {
4759 case ADV_ASYNC_SCSI_BUS_RESET_DET:
4760 /*
4761 * The firmware detected a SCSI Bus reset.
4762 */
4763 ASC_DBG(0,
4764 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
4765 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004767 case ADV_ASYNC_RDMA_FAILURE:
4768 /*
4769 * Handle RDMA failure by resetting the SCSI Bus and
4770 * possibly the chip if it is unresponsive. Log the error
4771 * with a unique code.
4772 */
4773 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
4774 AdvResetChipAndSB(adv_dvc_varp);
4775 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004777 case ADV_HOST_SCSI_BUS_RESET:
4778 /*
4779 * Host generated SCSI bus reset occurred.
4780 */
4781 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
4782 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004784 default:
4785 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
4786 break;
4787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788}
4789
4790/*
4791 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
4792 * to indicate a command is queued for the device.
4793 *
4794 * 'flag' may be either ASC_FRONT or ASC_BACK.
4795 *
4796 * 'REQPNEXT(reqp)' returns reqp's next pointer.
4797 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004798static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004800 int tid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004802 ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n",
4803 (ulong)ascq, (ulong)reqp, flag);
4804 ASC_ASSERT(reqp != NULL);
4805 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
4806 tid = REQPTID(reqp);
4807 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
4808 if (flag == ASC_FRONT) {
4809 reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
4810 ascq->q_first[tid] = reqp;
4811 /* If the queue was empty, set the last pointer. */
4812 if (ascq->q_last[tid] == NULL) {
4813 ascq->q_last[tid] = reqp;
4814 }
4815 } else { /* ASC_BACK */
4816 if (ascq->q_last[tid] != NULL) {
4817 ascq->q_last[tid]->host_scribble =
4818 (unsigned char *)reqp;
4819 }
4820 ascq->q_last[tid] = reqp;
4821 reqp->host_scribble = NULL;
4822 /* If the queue was empty, set the first pointer. */
4823 if (ascq->q_first[tid] == NULL) {
4824 ascq->q_first[tid] = reqp;
4825 }
4826 }
4827 /* The queue has at least one entry, set its bit. */
4828 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004830 /* Maintain request queue statistics. */
4831 ascq->q_tot_cnt[tid]++;
4832 ascq->q_cur_cnt[tid]++;
4833 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
4834 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
4835 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
4836 tid, ascq->q_max_cnt[tid]);
4837 }
4838 REQPTIME(reqp) = REQTIMESTAMP();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004840 ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp);
4841 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004842}
4843
4844/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845 * Return a pointer to a singly linked list of all the requests queued
4846 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
4847 *
4848 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
4849 * the last request returned in the singly linked list.
4850 *
4851 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
4852 * then all queued requests are concatenated into one list and
4853 * returned.
4854 *
4855 * Note: If 'lastpp' is used to append a new list to the end of
4856 * an old list, only change the old list last pointer if '*lastpp'
4857 * (or the function return value) is not NULL, i.e. use a temporary
4858 * variable for 'lastpp' and check its value after the function return
4859 * before assigning it to the list last pointer.
4860 *
4861 * Unfortunately collecting queuing time statistics adds overhead to
4862 * the function that isn't inherent to the function's algorithm.
4863 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004864static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004865{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004866 REQP firstp, lastp;
4867 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004869 ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
4870 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004872 /*
4873 * If 'tid' is not ASC_TID_ALL, return requests only for
4874 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
4875 * requests for all tids.
4876 */
4877 if (tid != ASC_TID_ALL) {
4878 /* Return all requests for the specified 'tid'. */
4879 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
4880 /* List is empty; Set first and last return pointers to NULL. */
4881 firstp = lastp = NULL;
4882 } else {
4883 firstp = ascq->q_first[tid];
4884 lastp = ascq->q_last[tid];
4885 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
4886 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004887#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004888 {
4889 REQP reqp;
4890 ascq->q_cur_cnt[tid] = 0;
4891 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
4892 REQTIMESTAT("asc_dequeue_list", ascq,
4893 reqp, tid);
4894 }
4895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004897 }
4898 } else {
4899 /* Return all requests for all tids. */
4900 firstp = lastp = NULL;
4901 for (i = 0; i <= ADV_MAX_TID; i++) {
4902 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
4903 if (firstp == NULL) {
4904 firstp = ascq->q_first[i];
4905 lastp = ascq->q_last[i];
4906 } else {
4907 ASC_ASSERT(lastp != NULL);
4908 lastp->host_scribble =
4909 (unsigned char *)ascq->q_first[i];
4910 lastp = ascq->q_last[i];
4911 }
4912 ascq->q_first[i] = ascq->q_last[i] = NULL;
4913 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004915 ascq->q_cur_cnt[i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004917 }
4918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004920 {
4921 REQP reqp;
4922 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
4923 REQTIMESTAT("asc_dequeue_list", ascq, reqp,
4924 reqp->device->id);
4925 }
4926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004928 }
4929 if (lastpp) {
4930 *lastpp = lastp;
4931 }
4932 ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp);
4933 return firstp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934}
4935
4936/*
4937 * Remove the specified 'REQP' from the specified queue for
4938 * the specified target device. Clear the 'tidmask' bit for the
4939 * device if no more commands are left queued for it.
4940 *
4941 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
4942 *
4943 * Return ASC_TRUE if the command was found and removed,
4944 * otherwise return ASC_FALSE.
4945 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004946static int asc_rmqueue(asc_queue_t *ascq, REQP reqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004948 REQP currp, prevp;
4949 int tid;
4950 int ret = ASC_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004952 ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n",
4953 (ulong)ascq, (ulong)reqp);
4954 ASC_ASSERT(reqp != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004956 tid = REQPTID(reqp);
4957 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004959 /*
4960 * Handle the common case of 'reqp' being the first
4961 * entry on the queue.
4962 */
4963 if (reqp == ascq->q_first[tid]) {
4964 ret = ASC_TRUE;
4965 ascq->q_first[tid] = REQPNEXT(reqp);
4966 /* If the queue is now empty, clear its bit and the last pointer. */
4967 if (ascq->q_first[tid] == NULL) {
4968 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
4969 ASC_ASSERT(ascq->q_last[tid] == reqp);
4970 ascq->q_last[tid] = NULL;
4971 }
4972 } else if (ascq->q_first[tid] != NULL) {
4973 ASC_ASSERT(ascq->q_last[tid] != NULL);
4974 /*
4975 * Because the case of 'reqp' being the first entry has been
4976 * handled above and it is known the queue is not empty, if
4977 * 'reqp' is found on the queue it is guaranteed the queue will
4978 * not become empty and that 'q_first[tid]' will not be changed.
4979 *
4980 * Set 'prevp' to the first entry, 'currp' to the second entry,
4981 * and search for 'reqp'.
4982 */
4983 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
4984 currp; prevp = currp, currp = REQPNEXT(currp)) {
4985 if (currp == reqp) {
4986 ret = ASC_TRUE;
4987 prevp->host_scribble =
4988 (unsigned char *)REQPNEXT(currp);
4989 reqp->host_scribble = NULL;
4990 if (ascq->q_last[tid] == reqp) {
4991 ascq->q_last[tid] = prevp;
4992 }
4993 break;
4994 }
4995 }
4996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004998 /* Maintain request queue statistics. */
4999 if (ret == ASC_TRUE) {
5000 ascq->q_cur_cnt[tid]--;
5001 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
5002 }
5003 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004#endif /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005005 ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret);
5006 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007}
5008
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009#ifdef CONFIG_PROC_FS
5010/*
5011 * asc_prt_board_devices()
5012 *
5013 * Print driver information for devices attached to the board.
5014 *
5015 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5016 * cf. asc_prt_line().
5017 *
5018 * Return the number of characters copied into 'cp'. No more than
5019 * 'cplen' characters will be copied to 'cp'.
5020 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005021static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005023 asc_board_t *boardp;
5024 int leftlen;
5025 int totlen;
5026 int len;
5027 int chip_scsi_id;
5028 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005030 boardp = ASC_BOARDP(shost);
5031 leftlen = cplen;
5032 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005034 len = asc_prt_line(cp, leftlen,
5035 "\nDevice Information for AdvanSys SCSI Host %d:\n",
5036 shost->host_no);
5037 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005039 if (ASC_NARROW_BOARD(boardp)) {
5040 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
5041 } else {
5042 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
5043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005045 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
5046 ASC_PRT_NEXT();
5047 for (i = 0; i <= ADV_MAX_TID; i++) {
5048 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
5049 len = asc_prt_line(cp, leftlen, " %X,", i);
5050 ASC_PRT_NEXT();
5051 }
5052 }
5053 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
5054 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005056 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057}
5058
5059/*
5060 * Display Wide Board BIOS Information.
5061 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005062static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005064 asc_board_t *boardp;
5065 int leftlen;
5066 int totlen;
5067 int len;
5068 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005070 boardp = ASC_BOARDP(shost);
5071 leftlen = cplen;
5072 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005074 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
5075 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005077 /*
5078 * If the BIOS saved a valid signature, then fill in
5079 * the BIOS code segment base address.
5080 */
5081 if (boardp->bios_signature != 0x55AA) {
5082 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
5083 ASC_PRT_NEXT();
5084 len = asc_prt_line(cp, leftlen,
5085 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
5086 ASC_PRT_NEXT();
5087 len = asc_prt_line(cp, leftlen,
5088 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
5089 ASC_PRT_NEXT();
5090 } else {
5091 major = (boardp->bios_version >> 12) & 0xF;
5092 minor = (boardp->bios_version >> 8) & 0xF;
5093 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005095 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
5096 major, minor,
5097 letter >= 26 ? '?' : letter + 'A');
5098 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005100 /*
5101 * Current available ROM BIOS release is 3.1I for UW
5102 * and 3.2I for U2W. This code doesn't differentiate
5103 * UW and U2W boards.
5104 */
5105 if (major < 3 || (major <= 3 && minor < 1) ||
5106 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
5107 len = asc_prt_line(cp, leftlen,
5108 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
5109 ASC_PRT_NEXT();
5110 len = asc_prt_line(cp, leftlen,
5111 "ftp://ftp.connectcom.net/pub\n");
5112 ASC_PRT_NEXT();
5113 }
5114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005116 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117}
5118
5119/*
5120 * Add serial number to information bar if signature AAh
5121 * is found in at bit 15-9 (7 bits) of word 1.
5122 *
5123 * Serial Number consists fo 12 alpha-numeric digits.
5124 *
5125 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
5126 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
5127 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
5128 * 5 - Product revision (A-J) Word0: " "
5129 *
5130 * Signature Word1: 15-9 (7 bits)
5131 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
5132 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
5133 *
5134 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
5135 *
5136 * Note 1: Only production cards will have a serial number.
5137 *
5138 * Note 2: Signature is most significant 7 bits (0xFE).
5139 *
5140 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
5141 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005142static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005144 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005146 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
5147 return ASC_FALSE;
5148 } else {
5149 /*
5150 * First word - 6 digits.
5151 */
5152 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005154 /* Product type - 1st digit. */
5155 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
5156 /* Product type is P=Prototype */
5157 *cp += 0x8;
5158 }
5159 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005161 /* Manufacturing location - 2nd digit. */
5162 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005164 /* Product ID - 3rd, 4th digits. */
5165 num = w & 0x3FF;
5166 *cp++ = '0' + (num / 100);
5167 num %= 100;
5168 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005170 /* Product revision - 5th digit. */
5171 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005173 /*
5174 * Second word
5175 */
5176 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005178 /*
5179 * Year - 6th digit.
5180 *
5181 * If bit 15 of third word is set, then the
5182 * last digit of the year is greater than 7.
5183 */
5184 if (serialnum[2] & 0x8000) {
5185 *cp++ = '8' + ((w & 0x1C0) >> 6);
5186 } else {
5187 *cp++ = '0' + ((w & 0x1C0) >> 6);
5188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005190 /* Week of year - 7th, 8th digits. */
5191 num = w & 0x003F;
5192 *cp++ = '0' + num / 10;
5193 num %= 10;
5194 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005196 /*
5197 * Third word
5198 */
5199 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005201 /* Serial number - 9th digit. */
5202 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005204 /* 10th, 11th, 12th digits. */
5205 num = w % 1000;
5206 *cp++ = '0' + num / 100;
5207 num %= 100;
5208 *cp++ = '0' + num / 10;
5209 num %= 10;
5210 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005212 *cp = '\0'; /* Null Terminate the string. */
5213 return ASC_TRUE;
5214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215}
5216
5217/*
5218 * asc_prt_asc_board_eeprom()
5219 *
5220 * Print board EEPROM configuration.
5221 *
5222 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5223 * cf. asc_prt_line().
5224 *
5225 * Return the number of characters copied into 'cp'. No more than
5226 * 'cplen' characters will be copied to 'cp'.
5227 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005228static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005230 asc_board_t *boardp;
5231 ASC_DVC_VAR *asc_dvc_varp;
5232 int leftlen;
5233 int totlen;
5234 int len;
5235 ASCEEP_CONFIG *ep;
5236 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005238 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005240 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005242 boardp = ASC_BOARDP(shost);
5243 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5244 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005246 leftlen = cplen;
5247 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005249 len = asc_prt_line(cp, leftlen,
5250 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
5251 shost->host_no);
5252 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005254 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
5255 == ASC_TRUE) {
5256 len =
5257 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
5258 serialstr);
5259 ASC_PRT_NEXT();
5260 } else {
5261 if (ep->adapter_info[5] == 0xBB) {
5262 len = asc_prt_line(cp, leftlen,
5263 " Default Settings Used for EEPROM-less Adapter.\n");
5264 ASC_PRT_NEXT();
5265 } else {
5266 len = asc_prt_line(cp, leftlen,
5267 " Serial Number Signature Not Present.\n");
5268 ASC_PRT_NEXT();
5269 }
5270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005272 len = asc_prt_line(cp, leftlen,
5273 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5274 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
5275 ep->max_tag_qng);
5276 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005278 len = asc_prt_line(cp, leftlen,
5279 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
5280 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005282 len = asc_prt_line(cp, leftlen, " Target ID: ");
5283 ASC_PRT_NEXT();
5284 for (i = 0; i <= ASC_MAX_TID; i++) {
5285 len = asc_prt_line(cp, leftlen, " %d", i);
5286 ASC_PRT_NEXT();
5287 }
5288 len = asc_prt_line(cp, leftlen, "\n");
5289 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005291 len = asc_prt_line(cp, leftlen, " Disconnects: ");
5292 ASC_PRT_NEXT();
5293 for (i = 0; i <= ASC_MAX_TID; i++) {
5294 len = asc_prt_line(cp, leftlen, " %c",
5295 (ep->
5296 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5297 'N');
5298 ASC_PRT_NEXT();
5299 }
5300 len = asc_prt_line(cp, leftlen, "\n");
5301 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005303 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
5304 ASC_PRT_NEXT();
5305 for (i = 0; i <= ASC_MAX_TID; i++) {
5306 len = asc_prt_line(cp, leftlen, " %c",
5307 (ep->
5308 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5309 'N');
5310 ASC_PRT_NEXT();
5311 }
5312 len = asc_prt_line(cp, leftlen, "\n");
5313 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005315 len = asc_prt_line(cp, leftlen, " Start Motor: ");
5316 ASC_PRT_NEXT();
5317 for (i = 0; i <= ASC_MAX_TID; i++) {
5318 len = asc_prt_line(cp, leftlen, " %c",
5319 (ep->
5320 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5321 'N');
5322 ASC_PRT_NEXT();
5323 }
5324 len = asc_prt_line(cp, leftlen, "\n");
5325 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005327 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5328 ASC_PRT_NEXT();
5329 for (i = 0; i <= ASC_MAX_TID; i++) {
5330 len = asc_prt_line(cp, leftlen, " %c",
5331 (ep->
5332 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5333 'N');
5334 ASC_PRT_NEXT();
5335 }
5336 len = asc_prt_line(cp, leftlen, "\n");
5337 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338
5339#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005340 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
5341 len = asc_prt_line(cp, leftlen,
5342 " Host ISA DMA speed: %d MB/S\n",
5343 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
5344 ASC_PRT_NEXT();
5345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346#endif /* CONFIG_ISA */
5347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005348 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349}
5350
5351/*
5352 * asc_prt_adv_board_eeprom()
5353 *
5354 * Print board EEPROM configuration.
5355 *
5356 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5357 * cf. asc_prt_line().
5358 *
5359 * Return the number of characters copied into 'cp'. No more than
5360 * 'cplen' characters will be copied to 'cp'.
5361 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005362static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005364 asc_board_t *boardp;
5365 ADV_DVC_VAR *adv_dvc_varp;
5366 int leftlen;
5367 int totlen;
5368 int len;
5369 int i;
5370 char *termstr;
5371 uchar serialstr[13];
5372 ADVEEP_3550_CONFIG *ep_3550 = NULL;
5373 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
5374 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
5375 ushort word;
5376 ushort *wordp;
5377 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005379 boardp = ASC_BOARDP(shost);
5380 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5381 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5382 ep_3550 = &boardp->eep_config.adv_3550_eep;
5383 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5384 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
5385 } else {
5386 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
5387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005389 leftlen = cplen;
5390 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005392 len = asc_prt_line(cp, leftlen,
5393 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
5394 shost->host_no);
5395 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005397 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5398 wordp = &ep_3550->serial_number_word1;
5399 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5400 wordp = &ep_38C0800->serial_number_word1;
5401 } else {
5402 wordp = &ep_38C1600->serial_number_word1;
5403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005405 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
5406 len =
5407 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
5408 serialstr);
5409 ASC_PRT_NEXT();
5410 } else {
5411 len = asc_prt_line(cp, leftlen,
5412 " Serial Number Signature Not Present.\n");
5413 ASC_PRT_NEXT();
5414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005416 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5417 len = asc_prt_line(cp, leftlen,
5418 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5419 ep_3550->adapter_scsi_id,
5420 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
5421 ASC_PRT_NEXT();
5422 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5423 len = asc_prt_line(cp, leftlen,
5424 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5425 ep_38C0800->adapter_scsi_id,
5426 ep_38C0800->max_host_qng,
5427 ep_38C0800->max_dvc_qng);
5428 ASC_PRT_NEXT();
5429 } else {
5430 len = asc_prt_line(cp, leftlen,
5431 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
5432 ep_38C1600->adapter_scsi_id,
5433 ep_38C1600->max_host_qng,
5434 ep_38C1600->max_dvc_qng);
5435 ASC_PRT_NEXT();
5436 }
5437 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5438 word = ep_3550->termination;
5439 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5440 word = ep_38C0800->termination_lvd;
5441 } else {
5442 word = ep_38C1600->termination_lvd;
5443 }
5444 switch (word) {
5445 case 1:
5446 termstr = "Low Off/High Off";
5447 break;
5448 case 2:
5449 termstr = "Low Off/High On";
5450 break;
5451 case 3:
5452 termstr = "Low On/High On";
5453 break;
5454 default:
5455 case 0:
5456 termstr = "Automatic";
5457 break;
5458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005460 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5461 len = asc_prt_line(cp, leftlen,
5462 " termination: %u (%s), bios_ctrl: 0x%x\n",
5463 ep_3550->termination, termstr,
5464 ep_3550->bios_ctrl);
5465 ASC_PRT_NEXT();
5466 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5467 len = asc_prt_line(cp, leftlen,
5468 " termination: %u (%s), bios_ctrl: 0x%x\n",
5469 ep_38C0800->termination_lvd, termstr,
5470 ep_38C0800->bios_ctrl);
5471 ASC_PRT_NEXT();
5472 } else {
5473 len = asc_prt_line(cp, leftlen,
5474 " termination: %u (%s), bios_ctrl: 0x%x\n",
5475 ep_38C1600->termination_lvd, termstr,
5476 ep_38C1600->bios_ctrl);
5477 ASC_PRT_NEXT();
5478 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005480 len = asc_prt_line(cp, leftlen, " Target ID: ");
5481 ASC_PRT_NEXT();
5482 for (i = 0; i <= ADV_MAX_TID; i++) {
5483 len = asc_prt_line(cp, leftlen, " %X", i);
5484 ASC_PRT_NEXT();
5485 }
5486 len = asc_prt_line(cp, leftlen, "\n");
5487 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005489 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5490 word = ep_3550->disc_enable;
5491 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5492 word = ep_38C0800->disc_enable;
5493 } else {
5494 word = ep_38C1600->disc_enable;
5495 }
5496 len = asc_prt_line(cp, leftlen, " Disconnects: ");
5497 ASC_PRT_NEXT();
5498 for (i = 0; i <= ADV_MAX_TID; i++) {
5499 len = asc_prt_line(cp, leftlen, " %c",
5500 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5501 ASC_PRT_NEXT();
5502 }
5503 len = asc_prt_line(cp, leftlen, "\n");
5504 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005506 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5507 word = ep_3550->tagqng_able;
5508 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5509 word = ep_38C0800->tagqng_able;
5510 } else {
5511 word = ep_38C1600->tagqng_able;
5512 }
5513 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
5514 ASC_PRT_NEXT();
5515 for (i = 0; i <= ADV_MAX_TID; i++) {
5516 len = asc_prt_line(cp, leftlen, " %c",
5517 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5518 ASC_PRT_NEXT();
5519 }
5520 len = asc_prt_line(cp, leftlen, "\n");
5521 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005523 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5524 word = ep_3550->start_motor;
5525 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5526 word = ep_38C0800->start_motor;
5527 } else {
5528 word = ep_38C1600->start_motor;
5529 }
5530 len = asc_prt_line(cp, leftlen, " Start Motor: ");
5531 ASC_PRT_NEXT();
5532 for (i = 0; i <= ADV_MAX_TID; i++) {
5533 len = asc_prt_line(cp, leftlen, " %c",
5534 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5535 ASC_PRT_NEXT();
5536 }
5537 len = asc_prt_line(cp, leftlen, "\n");
5538 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005540 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5541 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5542 ASC_PRT_NEXT();
5543 for (i = 0; i <= ADV_MAX_TID; i++) {
5544 len = asc_prt_line(cp, leftlen, " %c",
5545 (ep_3550->
5546 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
5547 'Y' : 'N');
5548 ASC_PRT_NEXT();
5549 }
5550 len = asc_prt_line(cp, leftlen, "\n");
5551 ASC_PRT_NEXT();
5552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005554 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5555 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
5556 ASC_PRT_NEXT();
5557 for (i = 0; i <= ADV_MAX_TID; i++) {
5558 len = asc_prt_line(cp, leftlen, " %c",
5559 (ep_3550->
5560 ultra_able & ADV_TID_TO_TIDMASK(i))
5561 ? 'Y' : 'N');
5562 ASC_PRT_NEXT();
5563 }
5564 len = asc_prt_line(cp, leftlen, "\n");
5565 ASC_PRT_NEXT();
5566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005568 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5569 word = ep_3550->wdtr_able;
5570 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5571 word = ep_38C0800->wdtr_able;
5572 } else {
5573 word = ep_38C1600->wdtr_able;
5574 }
5575 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
5576 ASC_PRT_NEXT();
5577 for (i = 0; i <= ADV_MAX_TID; i++) {
5578 len = asc_prt_line(cp, leftlen, " %c",
5579 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5580 ASC_PRT_NEXT();
5581 }
5582 len = asc_prt_line(cp, leftlen, "\n");
5583 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005585 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
5586 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
5587 len = asc_prt_line(cp, leftlen,
5588 " Synchronous Transfer Speed (Mhz):\n ");
5589 ASC_PRT_NEXT();
5590 for (i = 0; i <= ADV_MAX_TID; i++) {
5591 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005593 if (i == 0) {
5594 sdtr_speed = adv_dvc_varp->sdtr_speed1;
5595 } else if (i == 4) {
5596 sdtr_speed = adv_dvc_varp->sdtr_speed2;
5597 } else if (i == 8) {
5598 sdtr_speed = adv_dvc_varp->sdtr_speed3;
5599 } else if (i == 12) {
5600 sdtr_speed = adv_dvc_varp->sdtr_speed4;
5601 }
5602 switch (sdtr_speed & ADV_MAX_TID) {
5603 case 0:
5604 speed_str = "Off";
5605 break;
5606 case 1:
5607 speed_str = " 5";
5608 break;
5609 case 2:
5610 speed_str = " 10";
5611 break;
5612 case 3:
5613 speed_str = " 20";
5614 break;
5615 case 4:
5616 speed_str = " 40";
5617 break;
5618 case 5:
5619 speed_str = " 80";
5620 break;
5621 default:
5622 speed_str = "Unk";
5623 break;
5624 }
5625 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
5626 ASC_PRT_NEXT();
5627 if (i == 7) {
5628 len = asc_prt_line(cp, leftlen, "\n ");
5629 ASC_PRT_NEXT();
5630 }
5631 sdtr_speed >>= 4;
5632 }
5633 len = asc_prt_line(cp, leftlen, "\n");
5634 ASC_PRT_NEXT();
5635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005637 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638}
5639
5640/*
5641 * asc_prt_driver_conf()
5642 *
5643 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5644 * cf. asc_prt_line().
5645 *
5646 * Return the number of characters copied into 'cp'. No more than
5647 * 'cplen' characters will be copied to 'cp'.
5648 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005649static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005651 asc_board_t *boardp;
5652 int leftlen;
5653 int totlen;
5654 int len;
5655 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005657 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005659 leftlen = cplen;
5660 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005662 len = asc_prt_line(cp, leftlen,
5663 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
5664 shost->host_no);
5665 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005667 len = asc_prt_line(cp, leftlen,
5668 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
5669 shost->host_busy, shost->last_reset, shost->max_id,
5670 shost->max_lun, shost->max_channel);
5671 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005673 len = asc_prt_line(cp, leftlen,
5674 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
5675 shost->unique_id, shost->can_queue, shost->this_id,
5676 shost->sg_tablesize, shost->cmd_per_lun);
5677 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005679 len = asc_prt_line(cp, leftlen,
5680 " unchecked_isa_dma %d, use_clustering %d\n",
5681 shost->unchecked_isa_dma, shost->use_clustering);
5682 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005684 len = asc_prt_line(cp, leftlen,
5685 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
5686 boardp->flags, boardp->last_reset, jiffies,
5687 boardp->asc_n_io_port);
5688 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04005690 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005691 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005693 if (ASC_NARROW_BOARD(boardp)) {
5694 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
5695 } else {
5696 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
5697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005699 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700}
5701
5702/*
5703 * asc_prt_asc_board_info()
5704 *
5705 * Print dynamic board configuration information.
5706 *
5707 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5708 * cf. asc_prt_line().
5709 *
5710 * Return the number of characters copied into 'cp'. No more than
5711 * 'cplen' characters will be copied to 'cp'.
5712 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005713static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005715 asc_board_t *boardp;
5716 int chip_scsi_id;
5717 int leftlen;
5718 int totlen;
5719 int len;
5720 ASC_DVC_VAR *v;
5721 ASC_DVC_CFG *c;
5722 int i;
5723 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005724
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005725 boardp = ASC_BOARDP(shost);
5726 v = &boardp->dvc_var.asc_dvc_var;
5727 c = &boardp->dvc_cfg.asc_dvc_cfg;
5728 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005730 leftlen = cplen;
5731 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005733 len = asc_prt_line(cp, leftlen,
5734 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5735 shost->host_no);
5736 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005737
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005738 len = asc_prt_line(cp, leftlen,
5739 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
5740 c->chip_version, c->lib_version, c->lib_serial_no,
5741 c->mcode_date);
5742 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005744 len = asc_prt_line(cp, leftlen,
5745 " mcode_version 0x%x, err_code %u\n",
5746 c->mcode_version, v->err_code);
5747 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005749 /* Current number of commands waiting for the host. */
5750 len = asc_prt_line(cp, leftlen,
5751 " Total Command Pending: %d\n", v->cur_total_qng);
5752 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005753
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005754 len = asc_prt_line(cp, leftlen, " Command Queuing:");
5755 ASC_PRT_NEXT();
5756 for (i = 0; i <= ASC_MAX_TID; i++) {
5757 if ((chip_scsi_id == i) ||
5758 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5759 continue;
5760 }
5761 len = asc_prt_line(cp, leftlen, " %X:%c",
5762 i,
5763 (v->
5764 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
5765 'Y' : 'N');
5766 ASC_PRT_NEXT();
5767 }
5768 len = asc_prt_line(cp, leftlen, "\n");
5769 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005771 /* Current number of commands waiting for a device. */
5772 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
5773 ASC_PRT_NEXT();
5774 for (i = 0; i <= ASC_MAX_TID; i++) {
5775 if ((chip_scsi_id == i) ||
5776 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5777 continue;
5778 }
5779 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
5780 ASC_PRT_NEXT();
5781 }
5782 len = asc_prt_line(cp, leftlen, "\n");
5783 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005785 /* Current limit on number of commands that can be sent to a device. */
5786 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
5787 ASC_PRT_NEXT();
5788 for (i = 0; i <= ASC_MAX_TID; i++) {
5789 if ((chip_scsi_id == i) ||
5790 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5791 continue;
5792 }
5793 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
5794 ASC_PRT_NEXT();
5795 }
5796 len = asc_prt_line(cp, leftlen, "\n");
5797 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005799 /* Indicate whether the device has returned queue full status. */
5800 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
5801 ASC_PRT_NEXT();
5802 for (i = 0; i <= ASC_MAX_TID; i++) {
5803 if ((chip_scsi_id == i) ||
5804 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5805 continue;
5806 }
5807 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
5808 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
5809 i, boardp->queue_full_cnt[i]);
5810 } else {
5811 len = asc_prt_line(cp, leftlen, " %X:N", i);
5812 }
5813 ASC_PRT_NEXT();
5814 }
5815 len = asc_prt_line(cp, leftlen, "\n");
5816 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005818 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5819 ASC_PRT_NEXT();
5820 for (i = 0; i <= ASC_MAX_TID; i++) {
5821 if ((chip_scsi_id == i) ||
5822 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5823 continue;
5824 }
5825 len = asc_prt_line(cp, leftlen, " %X:%c",
5826 i,
5827 (v->
5828 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5829 'N');
5830 ASC_PRT_NEXT();
5831 }
5832 len = asc_prt_line(cp, leftlen, "\n");
5833 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005835 for (i = 0; i <= ASC_MAX_TID; i++) {
5836 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005838 if ((chip_scsi_id == i) ||
5839 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5840 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
5841 continue;
5842 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005844 len = asc_prt_line(cp, leftlen, " %X:", i);
5845 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005847 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
5848 len = asc_prt_line(cp, leftlen, " Asynchronous");
5849 ASC_PRT_NEXT();
5850 } else {
5851 syn_period_ix =
5852 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
5853 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005855 len = asc_prt_line(cp, leftlen,
5856 " Transfer Period Factor: %d (%d.%d Mhz),",
5857 v->sdtr_period_tbl[syn_period_ix],
5858 250 /
5859 v->sdtr_period_tbl[syn_period_ix],
5860 ASC_TENTHS(250,
5861 v->
5862 sdtr_period_tbl
5863 [syn_period_ix]));
5864 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005866 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5867 boardp->
5868 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
5869 ASC_PRT_NEXT();
5870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005872 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5873 len = asc_prt_line(cp, leftlen, "*\n");
5874 renegotiate = 1;
5875 } else {
5876 len = asc_prt_line(cp, leftlen, "\n");
5877 }
5878 ASC_PRT_NEXT();
5879 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005881 if (renegotiate) {
5882 len = asc_prt_line(cp, leftlen,
5883 " * = Re-negotiation pending before next command.\n");
5884 ASC_PRT_NEXT();
5885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005887 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888}
5889
5890/*
5891 * asc_prt_adv_board_info()
5892 *
5893 * Print dynamic board configuration information.
5894 *
5895 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5896 * cf. asc_prt_line().
5897 *
5898 * Return the number of characters copied into 'cp'. No more than
5899 * 'cplen' characters will be copied to 'cp'.
5900 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005901static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005903 asc_board_t *boardp;
5904 int leftlen;
5905 int totlen;
5906 int len;
5907 int i;
5908 ADV_DVC_VAR *v;
5909 ADV_DVC_CFG *c;
5910 AdvPortAddr iop_base;
5911 ushort chip_scsi_id;
5912 ushort lramword;
5913 uchar lrambyte;
5914 ushort tagqng_able;
5915 ushort sdtr_able, wdtr_able;
5916 ushort wdtr_done, sdtr_done;
5917 ushort period = 0;
5918 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005920 boardp = ASC_BOARDP(shost);
5921 v = &boardp->dvc_var.adv_dvc_var;
5922 c = &boardp->dvc_cfg.adv_dvc_cfg;
5923 iop_base = v->iop_base;
5924 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005926 leftlen = cplen;
5927 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005929 len = asc_prt_line(cp, leftlen,
5930 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5931 shost->host_no);
5932 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005934 len = asc_prt_line(cp, leftlen,
5935 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
5936 v->iop_base,
5937 AdvReadWordRegister(iop_base,
5938 IOPW_SCSI_CFG1) & CABLE_DETECT,
5939 v->err_code);
5940 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005942 len = asc_prt_line(cp, leftlen,
5943 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
5944 c->chip_version, c->lib_version, c->mcode_date,
5945 c->mcode_version);
5946 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005948 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
5949 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
5950 ASC_PRT_NEXT();
5951 for (i = 0; i <= ADV_MAX_TID; i++) {
5952 if ((chip_scsi_id == i) ||
5953 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5954 continue;
5955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005957 len = asc_prt_line(cp, leftlen, " %X:%c",
5958 i,
5959 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5960 'N');
5961 ASC_PRT_NEXT();
5962 }
5963 len = asc_prt_line(cp, leftlen, "\n");
5964 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005966 len = asc_prt_line(cp, leftlen, " Queue Limit:");
5967 ASC_PRT_NEXT();
5968 for (i = 0; i <= ADV_MAX_TID; i++) {
5969 if ((chip_scsi_id == i) ||
5970 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5971 continue;
5972 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005974 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
5975 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005977 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5978 ASC_PRT_NEXT();
5979 }
5980 len = asc_prt_line(cp, leftlen, "\n");
5981 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005983 len = asc_prt_line(cp, leftlen, " Command Pending:");
5984 ASC_PRT_NEXT();
5985 for (i = 0; i <= ADV_MAX_TID; i++) {
5986 if ((chip_scsi_id == i) ||
5987 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5988 continue;
5989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005990
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005991 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
5992 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005994 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5995 ASC_PRT_NEXT();
5996 }
5997 len = asc_prt_line(cp, leftlen, "\n");
5998 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005999
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006000 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
6001 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
6002 ASC_PRT_NEXT();
6003 for (i = 0; i <= ADV_MAX_TID; i++) {
6004 if ((chip_scsi_id == i) ||
6005 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6006 continue;
6007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006009 len = asc_prt_line(cp, leftlen, " %X:%c",
6010 i,
6011 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6012 'N');
6013 ASC_PRT_NEXT();
6014 }
6015 len = asc_prt_line(cp, leftlen, "\n");
6016 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006018 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
6019 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
6020 ASC_PRT_NEXT();
6021 for (i = 0; i <= ADV_MAX_TID; i++) {
6022 if ((chip_scsi_id == i) ||
6023 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6024 continue;
6025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006027 AdvReadWordLram(iop_base,
6028 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
6029 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006031 len = asc_prt_line(cp, leftlen, " %X:%d",
6032 i, (lramword & 0x8000) ? 16 : 8);
6033 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006035 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
6036 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
6037 len = asc_prt_line(cp, leftlen, "*");
6038 ASC_PRT_NEXT();
6039 renegotiate = 1;
6040 }
6041 }
6042 len = asc_prt_line(cp, leftlen, "\n");
6043 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006045 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
6046 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
6047 ASC_PRT_NEXT();
6048 for (i = 0; i <= ADV_MAX_TID; i++) {
6049 if ((chip_scsi_id == i) ||
6050 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
6051 continue;
6052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006054 len = asc_prt_line(cp, leftlen, " %X:%c",
6055 i,
6056 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
6057 'N');
6058 ASC_PRT_NEXT();
6059 }
6060 len = asc_prt_line(cp, leftlen, "\n");
6061 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006062
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006063 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
6064 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006066 AdvReadWordLram(iop_base,
6067 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
6068 lramword);
6069 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006071 if ((chip_scsi_id == i) ||
6072 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
6073 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
6074 continue;
6075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006077 len = asc_prt_line(cp, leftlen, " %X:", i);
6078 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006080 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
6081 len = asc_prt_line(cp, leftlen, " Asynchronous");
6082 ASC_PRT_NEXT();
6083 } else {
6084 len =
6085 asc_prt_line(cp, leftlen,
6086 " Transfer Period Factor: ");
6087 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006089 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
6090 len =
6091 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
6092 ASC_PRT_NEXT();
6093 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
6094 len =
6095 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
6096 ASC_PRT_NEXT();
6097 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006099 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006101 if (period == 0) { /* Should never happen. */
6102 len =
6103 asc_prt_line(cp, leftlen,
6104 "%d (? Mhz), ");
6105 ASC_PRT_NEXT();
6106 } else {
6107 len = asc_prt_line(cp, leftlen,
6108 "%d (%d.%d Mhz),",
6109 period, 250 / period,
6110 ASC_TENTHS(250,
6111 period));
6112 ASC_PRT_NEXT();
6113 }
6114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006116 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
6117 lramword & 0x1F);
6118 ASC_PRT_NEXT();
6119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006121 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
6122 len = asc_prt_line(cp, leftlen, "*\n");
6123 renegotiate = 1;
6124 } else {
6125 len = asc_prt_line(cp, leftlen, "\n");
6126 }
6127 ASC_PRT_NEXT();
6128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006130 if (renegotiate) {
6131 len = asc_prt_line(cp, leftlen,
6132 " * = Re-negotiation pending before next command.\n");
6133 ASC_PRT_NEXT();
6134 }
6135
6136 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137}
6138
6139/*
6140 * asc_proc_copy()
6141 *
6142 * Copy proc information to a read buffer taking into account the current
6143 * read offset in the file and the remaining space in the read buffer.
6144 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006145static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006147 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006149 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006151 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
6152 (unsigned)offset, (unsigned)advoffset, cplen);
6153 if (offset <= advoffset) {
6154 /* Read offset below current offset, copy everything. */
6155 cnt = min(cplen, leftlen);
6156 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
6157 (ulong)curbuf, (ulong)cp, cnt);
6158 memcpy(curbuf, cp, cnt);
6159 } else if (offset < advoffset + cplen) {
6160 /* Read offset within current range, partial copy. */
6161 cnt = (advoffset + cplen) - offset;
6162 cp = (cp + cplen) - cnt;
6163 cnt = min(cnt, leftlen);
6164 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
6165 (ulong)curbuf, (ulong)cp, cnt);
6166 memcpy(curbuf, cp, cnt);
6167 }
6168 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169}
6170
6171/*
6172 * asc_prt_line()
6173 *
6174 * If 'cp' is NULL print to the console, otherwise print to a buffer.
6175 *
6176 * Return 0 if printing to the console, otherwise return the number of
6177 * bytes written to the buffer.
6178 *
6179 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
6180 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
6181 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006182static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006184 va_list args;
6185 int ret;
6186 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006188 va_start(args, fmt);
6189 ret = vsprintf(s, fmt, args);
6190 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
6191 if (buf == NULL) {
6192 (void)printk(s);
6193 ret = 0;
6194 } else {
6195 ret = min(buflen, ret);
6196 memcpy(buf, s, ret);
6197 }
6198 va_end(args);
6199 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200}
6201#endif /* CONFIG_PROC_FS */
6202
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203/*
6204 * --- Functions Required by the Asc Library
6205 */
6206
6207/*
6208 * Delay for 'n' milliseconds. Don't use the 'jiffies'
6209 * global variable which is incremented once every 5 ms
6210 * from a timer interrupt, because this function may be
6211 * called when interrupts are disabled.
6212 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006213static void DvcSleepMilliSecond(ADV_DCNT n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006215 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
6216 mdelay(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217}
6218
6219/*
6220 * Currently and inline noop but leave as a placeholder.
6221 * Leave DvcEnterCritical() as a noop placeholder.
6222 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006223static inline ulong DvcEnterCritical(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006225 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226}
6227
6228/*
6229 * Critical sections are all protected by the board spinlock.
6230 * Leave DvcLeaveCritical() as a noop placeholder.
6231 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006232static inline void DvcLeaveCritical(ulong flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006234 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006235}
6236
6237/*
6238 * void
6239 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
6240 *
6241 * Calling/Exit State:
6242 * none
6243 *
6244 * Description:
6245 * Output an ASC_SCSI_Q structure to the chip
6246 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006247static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
6249{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006250 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006251
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006252 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
6253 AscSetChipLramAddr(iop_base, s_addr);
6254 for (i = 0; i < 2 * words; i += 2) {
6255 if (i == 4 || i == 20) {
6256 continue;
6257 }
6258 outpw(iop_base + IOP_RAM_DATA,
6259 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
6260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261}
6262
6263/*
6264 * void
6265 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
6266 *
6267 * Calling/Exit State:
6268 * none
6269 *
6270 * Description:
6271 * Input an ASC_QDONE_INFO structure from the chip
6272 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006273static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
6275{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006276 int i;
6277 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006279 AscSetChipLramAddr(iop_base, s_addr);
6280 for (i = 0; i < 2 * words; i += 2) {
6281 if (i == 10) {
6282 continue;
6283 }
6284 word = inpw(iop_base + IOP_RAM_DATA);
6285 inbuf[i] = word & 0xff;
6286 inbuf[i + 1] = (word >> 8) & 0xff;
6287 }
6288 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006289}
6290
6291/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292 * Return the BIOS address of the adapter at the specified
6293 * I/O port and with the specified bus type.
6294 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006295static unsigned short __devinit
6296AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006297{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006298 unsigned short cfg_lsw;
6299 unsigned short bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006300
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006301 /*
6302 * The PCI BIOS is re-located by the motherboard BIOS. Because
6303 * of this the driver can not determine where a PCI BIOS is
6304 * loaded and executes.
6305 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006306 if (bus_type & ASC_IS_PCI)
6307 return 0;
6308
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006310 if ((bus_type & ASC_IS_EISA) != 0) {
6311 cfg_lsw = AscGetEisaChipCfg(iop_base);
6312 cfg_lsw &= 0x000F;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006313 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
6314 return bios_addr;
6315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316#endif /* CONFIG_ISA */
6317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006318 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320 /*
6321 * ISA PnP uses the top bit as the 32K BIOS flag
6322 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006323 if (bus_type == ASC_IS_ISAPNP)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006324 cfg_lsw &= 0x7FFF;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006325 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
6326 return bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006327}
6328
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329/*
6330 * --- Functions Required by the Adv Library
6331 */
6332
6333/*
6334 * DvcGetPhyAddr()
6335 *
6336 * Return the physical address of 'vaddr' and set '*lenp' to the
6337 * number of physically contiguous bytes that follow 'vaddr'.
6338 * 'flag' indicates the type of structure whose physical address
6339 * is being translated.
6340 *
6341 * Note: Because Linux currently doesn't page the kernel and all
6342 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
6343 */
6344ADV_PADDR
6345DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006346 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006348 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006349
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006350 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006351
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006352 ASC_DBG4(4,
6353 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
6354 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
6355 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006356
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006357 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006358}
6359
6360/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361 * --- Tracing and Debugging Functions
6362 */
6363
6364#ifdef ADVANSYS_STATS
6365#ifdef CONFIG_PROC_FS
6366/*
6367 * asc_prt_board_stats()
6368 *
6369 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6370 * cf. asc_prt_line().
6371 *
6372 * Return the number of characters copied into 'cp'. No more than
6373 * 'cplen' characters will be copied to 'cp'.
6374 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006375static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006377 int leftlen;
6378 int totlen;
6379 int len;
6380 struct asc_stats *s;
6381 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006382
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006383 leftlen = cplen;
6384 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006385
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006386 boardp = ASC_BOARDP(shost);
6387 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006388
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006389 len = asc_prt_line(cp, leftlen,
6390 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
6391 shost->host_no);
6392 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006394 len = asc_prt_line(cp, leftlen,
6395 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
6396 s->queuecommand, s->reset, s->biosparam,
6397 s->interrupt);
6398 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006399
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006400 len = asc_prt_line(cp, leftlen,
6401 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
6402 s->callback, s->done, s->build_error,
6403 s->adv_build_noreq, s->adv_build_nosg);
6404 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006406 len = asc_prt_line(cp, leftlen,
6407 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
6408 s->exe_noerror, s->exe_busy, s->exe_error,
6409 s->exe_unknown);
6410 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006411
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006412 /*
6413 * Display data transfer statistics.
6414 */
6415 if (s->cont_cnt > 0) {
6416 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
6417 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006418
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006419 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
6420 s->cont_xfer / 2,
6421 ASC_TENTHS(s->cont_xfer, 2));
6422 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006424 /* Contiguous transfer average size */
6425 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
6426 (s->cont_xfer / 2) / s->cont_cnt,
6427 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
6428 ASC_PRT_NEXT();
6429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006430
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006431 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006433 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
6434 s->sg_cnt, s->sg_elem);
6435 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006437 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
6438 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
6439 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006440
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006441 /* Scatter gather transfer statistics */
6442 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
6443 s->sg_elem / s->sg_cnt,
6444 ASC_TENTHS(s->sg_elem, s->sg_cnt));
6445 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006446
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006447 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
6448 (s->sg_xfer / 2) / s->sg_elem,
6449 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
6450 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006452 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
6453 (s->sg_xfer / 2) / s->sg_cnt,
6454 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
6455 ASC_PRT_NEXT();
6456 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006458 /*
6459 * Display request queuing statistics.
6460 */
6461 len = asc_prt_line(cp, leftlen,
6462 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
6463 HZ);
6464 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006466 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006467}
6468
6469/*
6470 * asc_prt_target_stats()
6471 *
6472 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6473 * cf. asc_prt_line().
6474 *
6475 * This is separated from asc_prt_board_stats because a full set
6476 * of targets will overflow ASC_PRTBUF_SIZE.
6477 *
6478 * Return the number of characters copied into 'cp'. No more than
6479 * 'cplen' characters will be copied to 'cp'.
6480 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006481static int
6482asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006483{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006484 int leftlen;
6485 int totlen;
6486 int len;
6487 struct asc_stats *s;
6488 ushort chip_scsi_id;
6489 asc_board_t *boardp;
6490 asc_queue_t *active;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006492 leftlen = cplen;
6493 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006494
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006495 boardp = ASC_BOARDP(shost);
6496 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006497
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006498 active = &ASC_BOARDP(shost)->active;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006499
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006500 if (ASC_NARROW_BOARD(boardp)) {
6501 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6502 } else {
6503 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006505
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006506 if ((chip_scsi_id == tgt_id) ||
6507 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) {
6508 return 0;
6509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006510
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006511 do {
Matthew Wilcoxb6622922007-09-09 08:56:31 -06006512 if (active->q_tot_cnt[tgt_id] > 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006513 len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id);
6514 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006515
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006516 len = asc_prt_line(cp, leftlen,
6517 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
6518 active->q_cur_cnt[tgt_id],
6519 active->q_max_cnt[tgt_id],
6520 active->q_tot_cnt[tgt_id],
6521 active->q_min_tim[tgt_id],
6522 active->q_max_tim[tgt_id],
6523 (active->q_tot_cnt[tgt_id] ==
6524 0) ? 0 : (active->
6525 q_tot_tim[tgt_id] /
6526 active->
6527 q_tot_cnt[tgt_id]),
6528 (active->q_tot_cnt[tgt_id] ==
6529 0) ? 0 : ASC_TENTHS(active->
6530 q_tot_tim
6531 [tgt_id],
6532 active->
6533 q_tot_cnt
6534 [tgt_id]));
6535 ASC_PRT_NEXT();
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006536 }
6537 } while (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006539 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006540}
6541#endif /* CONFIG_PROC_FS */
6542#endif /* ADVANSYS_STATS */
6543
6544#ifdef ADVANSYS_DEBUG
6545/*
6546 * asc_prt_scsi_host()
6547 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006548static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006549{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006550 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006552 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006553
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006554 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
6555 printk(" host_busy %u, host_no %d, last_reset %d,\n",
6556 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006557
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04006558 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
6559 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006560
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006561 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
6562 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006563
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006564 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
6565 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006566
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006567 if (ASC_NARROW_BOARD(boardp)) {
6568 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
6569 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
6570 } else {
6571 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
6572 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
6573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006574}
6575
6576/*
6577 * asc_prt_scsi_cmnd()
6578 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006579static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006580{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006581 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006582
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006583 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
6584 (ulong)s->device->host, (ulong)s->device, s->device->id,
6585 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006587 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006588
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006589 printk("sc_data_direction %u, resid %d\n",
6590 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006591
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006592 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006593
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006594 printk(" serial_number 0x%x, retries %d, allowed %d\n",
6595 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006596
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006597 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006598
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006599 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
6600 s->scsi_done, s->done, s->host_scribble, s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006602 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006603}
6604
6605/*
6606 * asc_prt_asc_dvc_var()
6607 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006608static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006609{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006610 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006611
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006612 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
6613 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006614
Matthew Wilcox895d6b42007-07-26 11:57:06 -04006615 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
6616 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006617
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006618 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
6619 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
6620 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
6621 (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006622
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006623 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
6624 "%u,\n", (unsigned)h->queue_full_or_busy,
6625 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006626
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006627 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
6628 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
6629 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
6630 (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006631
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006632 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
6633 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
6634 (unsigned)h->init_state, (unsigned)h->no_scam,
6635 (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006636
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006637 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006638}
6639
6640/*
6641 * asc_prt_asc_dvc_cfg()
6642 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006643static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006644{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006645 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006646
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006647 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
6648 h->can_tagged_qng, h->cmd_qng_enabled);
6649 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
6650 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006651
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006652 printk
6653 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
6654 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
6655 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006656
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006657 printk
6658 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
6659 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
6660 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006661
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006662 printk(" mcode_version %d, overrun_buf 0x%lx\n",
6663 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006664}
6665
6666/*
6667 * asc_prt_asc_scsi_q()
6668 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006669static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006670{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006671 ASC_SG_HEAD *sgp;
6672 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006673
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006674 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006675
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006676 printk
6677 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
6678 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
6679 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006680
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006681 printk
6682 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6683 (ulong)le32_to_cpu(q->q1.data_addr),
6684 (ulong)le32_to_cpu(q->q1.data_cnt),
6685 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006686
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006687 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
6688 (ulong)q->cdbptr, q->q2.cdb_len,
6689 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006690
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006691 if (q->sg_head) {
6692 sgp = q->sg_head;
6693 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
6694 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
6695 sgp->queue_cnt);
6696 for (i = 0; i < sgp->entry_cnt; i++) {
6697 printk(" [%u]: addr 0x%lx, bytes %lu\n",
6698 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
6699 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
6700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006701
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006703}
6704
6705/*
6706 * asc_prt_asc_qdone_info()
6707 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006708static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006709{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006710 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
6711 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
6712 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
6713 q->d2.tag_code);
6714 printk
6715 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
6716 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006717}
6718
6719/*
6720 * asc_prt_adv_dvc_var()
6721 *
6722 * Display an ADV_DVC_VAR structure.
6723 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006724static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006725{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006726 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006727
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006728 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
6729 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006730
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006731 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
6732 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
6733 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006735 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
6736 (unsigned)h->start_motor,
6737 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006738
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006739 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
6740 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
6741 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006742
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006743 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
6744 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006745
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006746 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
6747 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006749 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
6750 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006751}
6752
6753/*
6754 * asc_prt_adv_dvc_cfg()
6755 *
6756 * Display an ADV_DVC_CFG structure.
6757 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006758static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006759{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006760 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006761
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006762 printk(" disc_enable 0x%x, termination 0x%x\n",
6763 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006764
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006765 printk(" chip_version 0x%x, mcode_date 0x%x\n",
6766 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006768 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
6769 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006770
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06006771 printk(" control_flag 0x%x\n", h->control_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006772}
6773
6774/*
6775 * asc_prt_adv_scsi_req_q()
6776 *
6777 * Display an ADV_SCSI_REQ_Q structure.
6778 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006779static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006781 int sg_blk_cnt;
6782 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006783
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006784 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006786 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
6787 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006788
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006789 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
6790 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006792 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6793 (ulong)le32_to_cpu(q->data_cnt),
6794 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006796 printk
6797 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
6798 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006799
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006800 printk(" sg_working_ix 0x%x, target_cmd %u\n",
6801 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006802
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006803 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
6804 (ulong)le32_to_cpu(q->scsiq_rptr),
6805 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006807 /* Display the request's ADV_SG_BLOCK structures. */
6808 if (q->sg_list_ptr != NULL) {
6809 sg_blk_cnt = 0;
6810 while (1) {
6811 /*
6812 * 'sg_ptr' is a physical address. Convert it to a virtual
6813 * address by indexing 'sg_blk_cnt' into the virtual address
6814 * array 'sg_list_ptr'.
6815 *
6816 * XXX - Assumes all SG physical blocks are virtually contiguous.
6817 */
6818 sg_ptr =
6819 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
6820 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
6821 if (sg_ptr->sg_ptr == 0) {
6822 break;
6823 }
6824 sg_blk_cnt++;
6825 }
6826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006827}
6828
6829/*
6830 * asc_prt_adv_sgblock()
6831 *
6832 * Display an ADV_SG_BLOCK structure.
6833 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006834static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006835{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006836 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006838 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
6839 (ulong)b, sgblockno);
6840 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
6841 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
6842 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
6843 if (b->sg_ptr != 0) {
6844 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
6845 }
6846 for (i = 0; i < b->sg_cnt; i++) {
6847 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
6848 i, (ulong)b->sg_list[i].sg_addr,
6849 (ulong)b->sg_list[i].sg_count);
6850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006851}
6852
6853/*
6854 * asc_prt_hex()
6855 *
6856 * Print hexadecimal output in 4 byte groupings 32 bytes
6857 * or 8 double-words per line.
6858 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006859static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006860{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006861 int i;
6862 int j;
6863 int k;
6864 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006866 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006867
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006868 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006869
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006870 /* Display a maximum of 8 double-words per line. */
6871 if ((k = (l - i) / 4) >= 8) {
6872 k = 8;
6873 m = 0;
6874 } else {
6875 m = (l - i) % 4;
6876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006877
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006878 for (j = 0; j < k; j++) {
6879 printk(" %2.2X%2.2X%2.2X%2.2X",
6880 (unsigned)s[i + (j * 4)],
6881 (unsigned)s[i + (j * 4) + 1],
6882 (unsigned)s[i + (j * 4) + 2],
6883 (unsigned)s[i + (j * 4) + 3]);
6884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006885
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006886 switch (m) {
6887 case 0:
6888 default:
6889 break;
6890 case 1:
6891 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
6892 break;
6893 case 2:
6894 printk(" %2.2X%2.2X",
6895 (unsigned)s[i + (j * 4)],
6896 (unsigned)s[i + (j * 4) + 1]);
6897 break;
6898 case 3:
6899 printk(" %2.2X%2.2X%2.2X",
6900 (unsigned)s[i + (j * 4) + 1],
6901 (unsigned)s[i + (j * 4) + 2],
6902 (unsigned)s[i + (j * 4) + 3]);
6903 break;
6904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006906 printk("\n");
6907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006908}
6909#endif /* ADVANSYS_DEBUG */
6910
6911/*
6912 * --- Asc Library Functions
6913 */
6914
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006915static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006916{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006917 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006918
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006919 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6920 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
6921 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006922}
6923
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006924static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006925{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006926 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006927
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006928 if (AscGetChipScsiID(iop_base) == new_host_id) {
6929 return (new_host_id);
6930 }
6931 cfg_lsw = AscGetChipCfgLsw(iop_base);
6932 cfg_lsw &= 0xF8FF;
6933 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
6934 AscSetChipCfgLsw(iop_base, cfg_lsw);
6935 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006936}
6937
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006938static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006939{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006940 unsigned char sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006942 AscSetBank(iop_base, 1);
6943 sc = inp(iop_base + IOP_REG_SC);
6944 AscSetBank(iop_base, 0);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006945 return sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006946}
6947
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006948static unsigned char __devinit
6949AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006950{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006951 if (bus_type & ASC_IS_EISA) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006952 PortAddr eisa_iop;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006953 unsigned char revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006954 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6955 (PortAddr) ASC_EISA_REV_IOP_MASK;
6956 revision = inp(eisa_iop);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006957 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006958 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006959 return AscGetChipVerNo(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006960}
6961
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006962static ASC_DCNT
6963AscLoadMicroCode(PortAddr iop_base,
6964 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006965{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006966 ASC_DCNT chksum;
6967 ushort mcode_word_size;
6968 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006970 /* Write the microcode buffer starting at LRAM address 0. */
6971 mcode_word_size = (ushort)(mcode_size >> 1);
6972 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
6973 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006974
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006975 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
6976 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
6977 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
6978 (ushort)ASC_CODE_SEC_BEG,
6979 (ushort)((mcode_size -
6980 s_addr - (ushort)
6981 ASC_CODE_SEC_BEG) /
6982 2));
6983 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
6984 (ulong)mcode_chksum);
6985 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
6986 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
6987 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006988}
6989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006990static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006991{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006992 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006993
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006994 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
6995 iop_base, AscGetChipSignatureByte(iop_base));
6996 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
6997 ASC_DBG2(1,
6998 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
6999 iop_base, AscGetChipSignatureWord(iop_base));
7000 sig_word = AscGetChipSignatureWord(iop_base);
7001 if ((sig_word == (ushort)ASC_1000_ID0W) ||
7002 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
7003 return (1);
7004 }
7005 }
7006 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007007}
7008
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007009static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007010{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007011 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
7012 AscSetChipStatus(iop_base, 0);
7013 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014}
7015
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007016static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007017{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007018 ushort cfg_lsw;
7019 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007020
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007021 if ((bus_type & ASC_IS_EISA) != 0) {
7022 cfg_lsw = AscGetEisaChipCfg(iop_base);
7023 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
7024 if ((chip_irq == 13) || (chip_irq > 15)) {
7025 return (0);
7026 }
7027 return (chip_irq);
7028 }
7029 if ((bus_type & ASC_IS_VL) != 0) {
7030 cfg_lsw = AscGetChipCfgLsw(iop_base);
7031 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
7032 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
7033 return (0);
7034 }
7035 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
7036 }
7037 cfg_lsw = AscGetChipCfgLsw(iop_base);
7038 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
7039 if (chip_irq == 3)
7040 chip_irq += (uchar)2;
7041 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007042}
7043
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007044static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007045AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007047 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007048
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007049 if ((bus_type & ASC_IS_VL) != 0) {
7050 if (irq_no != 0) {
7051 if ((irq_no < ASC_MIN_IRQ_NO)
7052 || (irq_no > ASC_MAX_IRQ_NO)) {
7053 irq_no = 0;
7054 } else {
7055 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
7056 }
7057 }
7058 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
7059 cfg_lsw |= (ushort)0x0010;
7060 AscSetChipCfgLsw(iop_base, cfg_lsw);
7061 AscToggleIRQAct(iop_base);
7062 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
7063 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
7064 AscSetChipCfgLsw(iop_base, cfg_lsw);
7065 AscToggleIRQAct(iop_base);
7066 return (AscGetChipIRQ(iop_base, bus_type));
7067 }
7068 if ((bus_type & (ASC_IS_ISA)) != 0) {
7069 if (irq_no == 15)
7070 irq_no -= (uchar)2;
7071 irq_no -= (uchar)ASC_MIN_IRQ_NO;
7072 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
7073 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
7074 AscSetChipCfgLsw(iop_base, cfg_lsw);
7075 return (AscGetChipIRQ(iop_base, bus_type));
7076 }
7077 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007078}
7079
7080#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06007081static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007083 if (dma_channel < 4) {
7084 outp(0x000B, (ushort)(0xC0 | dma_channel));
7085 outp(0x000A, dma_channel);
7086 } else if (dma_channel < 8) {
7087 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
7088 outp(0x00D4, (ushort)(dma_channel - 4));
7089 }
7090 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091}
7092#endif /* CONFIG_ISA */
7093
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007094static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007095{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007096 EXT_MSG ext_msg;
7097 EXT_MSG out_msg;
7098 ushort halt_q_addr;
7099 int sdtr_accept;
7100 ushort int_halt_code;
7101 ASC_SCSI_BIT_ID_TYPE scsi_busy;
7102 ASC_SCSI_BIT_ID_TYPE target_id;
7103 PortAddr iop_base;
7104 uchar tag_code;
7105 uchar q_status;
7106 uchar halt_qp;
7107 uchar sdtr_data;
7108 uchar target_ix;
7109 uchar q_cntl, tid_no;
7110 uchar cur_dvc_qng;
7111 uchar asyn_sdtr;
7112 uchar scsi_status;
7113 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007115 ASC_ASSERT(asc_dvc->drv_ptr != NULL);
7116 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007117
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007118 iop_base = asc_dvc->iop_base;
7119 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007120
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007121 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
7122 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
7123 target_ix = AscReadLramByte(iop_base,
7124 (ushort)(halt_q_addr +
7125 (ushort)ASC_SCSIQ_B_TARGET_IX));
7126 q_cntl =
7127 AscReadLramByte(iop_base,
7128 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
7129 tid_no = ASC_TIX_TO_TID(target_ix);
7130 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
7131 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
7132 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
7133 } else {
7134 asyn_sdtr = 0;
7135 }
7136 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
7137 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
7138 AscSetChipSDTR(iop_base, 0, tid_no);
7139 boardp->sdtr_data[tid_no] = 0;
7140 }
7141 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7142 return (0);
7143 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
7144 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
7145 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
7146 boardp->sdtr_data[tid_no] = asyn_sdtr;
7147 }
7148 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7149 return (0);
7150 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007151
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007152 AscMemWordCopyPtrFromLram(iop_base,
7153 ASCV_MSGIN_BEG,
7154 (uchar *)&ext_msg,
7155 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007156
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007157 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
7158 ext_msg.msg_req == EXTENDED_SDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007159 ext_msg.msg_len == MS_SDTR_LEN) {
7160 sdtr_accept = TRUE;
7161 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007162
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007163 sdtr_accept = FALSE;
7164 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
7165 }
7166 if ((ext_msg.xfer_period <
7167 asc_dvc->sdtr_period_tbl[asc_dvc->
7168 host_init_sdtr_index])
7169 || (ext_msg.xfer_period >
7170 asc_dvc->sdtr_period_tbl[asc_dvc->
7171 max_sdtr_index])) {
7172 sdtr_accept = FALSE;
7173 ext_msg.xfer_period =
7174 asc_dvc->sdtr_period_tbl[asc_dvc->
7175 host_init_sdtr_index];
7176 }
7177 if (sdtr_accept) {
7178 sdtr_data =
7179 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
7180 ext_msg.req_ack_offset);
7181 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007182
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007183 q_cntl |= QC_MSG_OUT;
7184 asc_dvc->init_sdtr &= ~target_id;
7185 asc_dvc->sdtr_done &= ~target_id;
7186 AscSetChipSDTR(iop_base, asyn_sdtr,
7187 tid_no);
7188 boardp->sdtr_data[tid_no] = asyn_sdtr;
7189 }
7190 }
7191 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007193 q_cntl &= ~QC_MSG_OUT;
7194 asc_dvc->init_sdtr &= ~target_id;
7195 asc_dvc->sdtr_done &= ~target_id;
7196 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
7197 } else {
7198 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007200 q_cntl &= ~QC_MSG_OUT;
7201 asc_dvc->sdtr_done |= target_id;
7202 asc_dvc->init_sdtr |= target_id;
7203 asc_dvc->pci_fix_asyn_xfer &=
7204 ~target_id;
7205 sdtr_data =
7206 AscCalSDTRData(asc_dvc,
7207 ext_msg.xfer_period,
7208 ext_msg.
7209 req_ack_offset);
7210 AscSetChipSDTR(iop_base, sdtr_data,
7211 tid_no);
7212 boardp->sdtr_data[tid_no] = sdtr_data;
7213 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007215 q_cntl |= QC_MSG_OUT;
7216 AscMsgOutSDTR(asc_dvc,
7217 ext_msg.xfer_period,
7218 ext_msg.req_ack_offset);
7219 asc_dvc->pci_fix_asyn_xfer &=
7220 ~target_id;
7221 sdtr_data =
7222 AscCalSDTRData(asc_dvc,
7223 ext_msg.xfer_period,
7224 ext_msg.
7225 req_ack_offset);
7226 AscSetChipSDTR(iop_base, sdtr_data,
7227 tid_no);
7228 boardp->sdtr_data[tid_no] = sdtr_data;
7229 asc_dvc->sdtr_done |= target_id;
7230 asc_dvc->init_sdtr |= target_id;
7231 }
7232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007234 AscWriteLramByte(iop_base,
7235 (ushort)(halt_q_addr +
7236 (ushort)ASC_SCSIQ_B_CNTL),
7237 q_cntl);
7238 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7239 return (0);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007240 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
7241 ext_msg.msg_req == EXTENDED_WDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007242 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007243
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007244 ext_msg.wdtr_width = 0;
7245 AscMemWordCopyPtrToLram(iop_base,
7246 ASCV_MSGOUT_BEG,
7247 (uchar *)&ext_msg,
7248 sizeof(EXT_MSG) >> 1);
7249 q_cntl |= QC_MSG_OUT;
7250 AscWriteLramByte(iop_base,
7251 (ushort)(halt_q_addr +
7252 (ushort)ASC_SCSIQ_B_CNTL),
7253 q_cntl);
7254 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7255 return (0);
7256 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007258 ext_msg.msg_type = MESSAGE_REJECT;
7259 AscMemWordCopyPtrToLram(iop_base,
7260 ASCV_MSGOUT_BEG,
7261 (uchar *)&ext_msg,
7262 sizeof(EXT_MSG) >> 1);
7263 q_cntl |= QC_MSG_OUT;
7264 AscWriteLramByte(iop_base,
7265 (ushort)(halt_q_addr +
7266 (ushort)ASC_SCSIQ_B_CNTL),
7267 q_cntl);
7268 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7269 return (0);
7270 }
7271 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007273 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007275 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007277 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007278
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007279 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7280 q_cntl |= QC_MSG_OUT;
7281 AscMsgOutSDTR(asc_dvc,
7282 asc_dvc->
7283 sdtr_period_tbl[(sdtr_data >> 4) &
7284 (uchar)(asc_dvc->
7285 max_sdtr_index -
7286 1)],
7287 (uchar)(sdtr_data & (uchar)
7288 ASC_SYN_MAX_OFFSET));
7289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007291 AscWriteLramByte(iop_base,
7292 (ushort)(halt_q_addr +
7293 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007294
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007295 tag_code = AscReadLramByte(iop_base,
7296 (ushort)(halt_q_addr + (ushort)
7297 ASC_SCSIQ_B_TAG_CODE));
7298 tag_code &= 0xDC;
7299 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
7300 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
7301 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007303 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
7304 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007305
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007306 }
7307 AscWriteLramByte(iop_base,
7308 (ushort)(halt_q_addr +
7309 (ushort)ASC_SCSIQ_B_TAG_CODE),
7310 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007311
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007312 q_status = AscReadLramByte(iop_base,
7313 (ushort)(halt_q_addr + (ushort)
7314 ASC_SCSIQ_B_STATUS));
7315 q_status |= (QS_READY | QS_BUSY);
7316 AscWriteLramByte(iop_base,
7317 (ushort)(halt_q_addr +
7318 (ushort)ASC_SCSIQ_B_STATUS),
7319 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007320
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007321 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
7322 scsi_busy &= ~target_id;
7323 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007324
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007325 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7326 return (0);
7327 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007328
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007329 AscMemWordCopyPtrFromLram(iop_base,
7330 ASCV_MSGOUT_BEG,
7331 (uchar *)&out_msg,
7332 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007333
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007334 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007335 (out_msg.msg_len == MS_SDTR_LEN) &&
Matthew Wilcox47d853c2007-07-26 11:41:33 -04007336 (out_msg.msg_req == EXTENDED_SDTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007337
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007338 asc_dvc->init_sdtr &= ~target_id;
7339 asc_dvc->sdtr_done &= ~target_id;
7340 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
7341 boardp->sdtr_data[tid_no] = asyn_sdtr;
7342 }
7343 q_cntl &= ~QC_MSG_OUT;
7344 AscWriteLramByte(iop_base,
7345 (ushort)(halt_q_addr +
7346 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
7347 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7348 return (0);
7349 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007350
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007351 scsi_status = AscReadLramByte(iop_base,
7352 (ushort)((ushort)halt_q_addr +
7353 (ushort)
7354 ASC_SCSIQ_SCSI_STATUS));
7355 cur_dvc_qng =
7356 AscReadLramByte(iop_base,
7357 (ushort)((ushort)ASC_QADR_BEG +
7358 (ushort)target_ix));
7359 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007360
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007361 scsi_busy = AscReadLramByte(iop_base,
7362 (ushort)ASCV_SCSIBUSY_B);
7363 scsi_busy |= target_id;
7364 AscWriteLramByte(iop_base,
7365 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
7366 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007367
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007368 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
7369 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
7370 cur_dvc_qng -= 1;
7371 asc_dvc->max_dvc_qng[tid_no] =
7372 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007374 AscWriteLramByte(iop_base,
7375 (ushort)((ushort)
7376 ASCV_MAX_DVC_QNG_BEG
7377 + (ushort)
7378 tid_no),
7379 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007380
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007381 /*
7382 * Set the device queue depth to the number of
7383 * active requests when the QUEUE FULL condition
7384 * was encountered.
7385 */
7386 boardp->queue_full |= target_id;
7387 boardp->queue_full_cnt[tid_no] =
7388 cur_dvc_qng;
7389 }
7390 }
7391 }
7392 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7393 return (0);
7394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007395#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007396 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
7397 uchar q_no;
7398 ushort q_addr;
7399 uchar sg_wk_q_no;
7400 uchar first_sg_wk_q_no;
7401 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
7402 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
7403 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
7404 ushort sg_list_dwords;
7405 ushort sg_entry_cnt;
7406 uchar next_qp;
7407 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007409 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
7410 if (q_no == ASC_QLINK_END) {
7411 return (0);
7412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007414 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007415
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007416 /*
7417 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
7418 * structure pointer using a macro provided by the driver.
7419 * The ASC_SCSI_REQ pointer provides a pointer to the
7420 * host ASC_SG_HEAD structure.
7421 */
7422 /* Read request's SRB pointer. */
7423 scsiq = (ASC_SCSI_Q *)
7424 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
7425 (ushort)
7426 (q_addr +
7427 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007428
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007429 /*
7430 * Get request's first and working SG queue.
7431 */
7432 sg_wk_q_no = AscReadLramByte(iop_base,
7433 (ushort)(q_addr +
7434 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007435
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007436 first_sg_wk_q_no = AscReadLramByte(iop_base,
7437 (ushort)(q_addr +
7438 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007439
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007440 /*
7441 * Reset request's working SG queue back to the
7442 * first SG queue.
7443 */
7444 AscWriteLramByte(iop_base,
7445 (ushort)(q_addr +
7446 (ushort)ASC_SCSIQ_B_SG_WK_QP),
7447 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007449 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007450
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007451 /*
7452 * Set sg_entry_cnt to the number of SG elements
7453 * that will be completed on this interrupt.
7454 *
7455 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
7456 * SG elements. The data_cnt and data_addr fields which
7457 * add 1 to the SG element capacity are not used when
7458 * restarting SG handling after a halt.
7459 */
7460 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
7461 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007463 /*
7464 * Keep track of remaining number of SG elements that will
7465 * need to be handled on the next interrupt.
7466 */
7467 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
7468 } else {
7469 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
7470 scsiq->remain_sg_entry_cnt = 0;
7471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007472
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007473 /*
7474 * Copy SG elements into the list of allocated SG queues.
7475 *
7476 * Last index completed is saved in scsiq->next_sg_index.
7477 */
7478 next_qp = first_sg_wk_q_no;
7479 q_addr = ASC_QNO_TO_QADDR(next_qp);
7480 scsi_sg_q.sg_head_qp = q_no;
7481 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
7482 for (i = 0; i < sg_head->queue_cnt; i++) {
7483 scsi_sg_q.seq_no = i + 1;
7484 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
7485 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
7486 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
7487 /*
7488 * After very first SG queue RISC FW uses next
7489 * SG queue first element then checks sg_list_cnt
7490 * against zero and then decrements, so set
7491 * sg_list_cnt 1 less than number of SG elements
7492 * in each SG queue.
7493 */
7494 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
7495 scsi_sg_q.sg_cur_list_cnt =
7496 ASC_SG_LIST_PER_Q - 1;
7497 } else {
7498 /*
7499 * This is the last SG queue in the list of
7500 * allocated SG queues. If there are more
7501 * SG elements than will fit in the allocated
7502 * queues, then set the QCSG_SG_XFER_MORE flag.
7503 */
7504 if (scsiq->remain_sg_entry_cnt != 0) {
7505 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
7506 } else {
7507 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
7508 }
7509 /* equals sg_entry_cnt * 2 */
7510 sg_list_dwords = sg_entry_cnt << 1;
7511 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
7512 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
7513 sg_entry_cnt = 0;
7514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007515
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007516 scsi_sg_q.q_no = next_qp;
7517 AscMemWordCopyPtrToLram(iop_base,
7518 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
7519 (uchar *)&scsi_sg_q,
7520 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007521
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007522 AscMemDWordCopyPtrToLram(iop_base,
7523 q_addr + ASC_SGQ_LIST_BEG,
7524 (uchar *)&sg_head->
7525 sg_list[scsiq->next_sg_index],
7526 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007528 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007529
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007530 /*
7531 * If the just completed SG queue contained the
7532 * last SG element, then no more SG queues need
7533 * to be written.
7534 */
7535 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
7536 break;
7537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007538
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007539 next_qp = AscReadLramByte(iop_base,
7540 (ushort)(q_addr +
7541 ASC_SCSIQ_B_FWD));
7542 q_addr = ASC_QNO_TO_QADDR(next_qp);
7543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007545 /*
7546 * Clear the halt condition so the RISC will be restarted
7547 * after the return.
7548 */
7549 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
7550 return (0);
7551 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007552#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007553 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007554}
7555
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007556static uchar
7557_AscCopyLramScsiDoneQ(PortAddr iop_base,
7558 ushort q_addr,
7559 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007560{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007561 ushort _val;
7562 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007563
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007564 DvcGetQinfo(iop_base,
7565 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
7566 (uchar *)scsiq,
7567 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007568
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007569 _val = AscReadLramWord(iop_base,
7570 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
7571 scsiq->q_status = (uchar)_val;
7572 scsiq->q_no = (uchar)(_val >> 8);
7573 _val = AscReadLramWord(iop_base,
7574 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
7575 scsiq->cntl = (uchar)_val;
7576 sg_queue_cnt = (uchar)(_val >> 8);
7577 _val = AscReadLramWord(iop_base,
7578 (ushort)(q_addr +
7579 (ushort)ASC_SCSIQ_B_SENSE_LEN));
7580 scsiq->sense_len = (uchar)_val;
7581 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007582
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007583 /*
7584 * Read high word of remain bytes from alternate location.
7585 */
7586 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
7587 (ushort)(q_addr +
7588 (ushort)
7589 ASC_SCSIQ_W_ALT_DC1)))
7590 << 16);
7591 /*
7592 * Read low word of remain bytes from original location.
7593 */
7594 scsiq->remain_bytes += AscReadLramWord(iop_base,
7595 (ushort)(q_addr + (ushort)
7596 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007598 scsiq->remain_bytes &= max_dma_count;
7599 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007600}
7601
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007602static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007603{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007604 uchar next_qp;
7605 uchar n_q_used;
7606 uchar sg_list_qp;
7607 uchar sg_queue_cnt;
7608 uchar q_cnt;
7609 uchar done_q_tail;
7610 uchar tid_no;
7611 ASC_SCSI_BIT_ID_TYPE scsi_busy;
7612 ASC_SCSI_BIT_ID_TYPE target_id;
7613 PortAddr iop_base;
7614 ushort q_addr;
7615 ushort sg_q_addr;
7616 uchar cur_target_qng;
7617 ASC_QDONE_INFO scsiq_buf;
7618 ASC_QDONE_INFO *scsiq;
7619 int false_overrun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007620
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007621 iop_base = asc_dvc->iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007622 n_q_used = 1;
7623 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
7624 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
7625 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
7626 next_qp = AscReadLramByte(iop_base,
7627 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
7628 if (next_qp != ASC_QLINK_END) {
7629 AscPutVarDoneQTail(iop_base, next_qp);
7630 q_addr = ASC_QNO_TO_QADDR(next_qp);
7631 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
7632 asc_dvc->max_dma_count);
7633 AscWriteLramByte(iop_base,
7634 (ushort)(q_addr +
7635 (ushort)ASC_SCSIQ_B_STATUS),
7636 (uchar)(scsiq->
7637 q_status & (uchar)~(QS_READY |
7638 QS_ABORTED)));
7639 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
7640 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
7641 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
7642 sg_q_addr = q_addr;
7643 sg_list_qp = next_qp;
7644 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
7645 sg_list_qp = AscReadLramByte(iop_base,
7646 (ushort)(sg_q_addr
7647 + (ushort)
7648 ASC_SCSIQ_B_FWD));
7649 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
7650 if (sg_list_qp == ASC_QLINK_END) {
7651 AscSetLibErrorCode(asc_dvc,
7652 ASCQ_ERR_SG_Q_LINKS);
7653 scsiq->d3.done_stat = QD_WITH_ERROR;
7654 scsiq->d3.host_stat =
7655 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
7656 goto FATAL_ERR_QDONE;
7657 }
7658 AscWriteLramByte(iop_base,
7659 (ushort)(sg_q_addr + (ushort)
7660 ASC_SCSIQ_B_STATUS),
7661 QS_FREE);
7662 }
7663 n_q_used = sg_queue_cnt + 1;
7664 AscPutVarDoneQTail(iop_base, sg_list_qp);
7665 }
7666 if (asc_dvc->queue_full_or_busy & target_id) {
7667 cur_target_qng = AscReadLramByte(iop_base,
7668 (ushort)((ushort)
7669 ASC_QADR_BEG
7670 + (ushort)
7671 scsiq->d2.
7672 target_ix));
7673 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
7674 scsi_busy = AscReadLramByte(iop_base, (ushort)
7675 ASCV_SCSIBUSY_B);
7676 scsi_busy &= ~target_id;
7677 AscWriteLramByte(iop_base,
7678 (ushort)ASCV_SCSIBUSY_B,
7679 scsi_busy);
7680 asc_dvc->queue_full_or_busy &= ~target_id;
7681 }
7682 }
7683 if (asc_dvc->cur_total_qng >= n_q_used) {
7684 asc_dvc->cur_total_qng -= n_q_used;
7685 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
7686 asc_dvc->cur_dvc_qng[tid_no]--;
7687 }
7688 } else {
7689 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
7690 scsiq->d3.done_stat = QD_WITH_ERROR;
7691 goto FATAL_ERR_QDONE;
7692 }
7693 if ((scsiq->d2.srb_ptr == 0UL) ||
7694 ((scsiq->q_status & QS_ABORTED) != 0)) {
7695 return (0x11);
7696 } else if (scsiq->q_status == QS_DONE) {
7697 false_overrun = FALSE;
7698 if (scsiq->extra_bytes != 0) {
7699 scsiq->remain_bytes +=
7700 (ADV_DCNT)scsiq->extra_bytes;
7701 }
7702 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
7703 if (scsiq->d3.host_stat ==
7704 QHSTA_M_DATA_OVER_RUN) {
7705 if ((scsiq->
7706 cntl & (QC_DATA_IN | QC_DATA_OUT))
7707 == 0) {
7708 scsiq->d3.done_stat =
7709 QD_NO_ERROR;
7710 scsiq->d3.host_stat =
7711 QHSTA_NO_ERROR;
7712 } else if (false_overrun) {
7713 scsiq->d3.done_stat =
7714 QD_NO_ERROR;
7715 scsiq->d3.host_stat =
7716 QHSTA_NO_ERROR;
7717 }
7718 } else if (scsiq->d3.host_stat ==
7719 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
7720 AscStopChip(iop_base);
7721 AscSetChipControl(iop_base,
7722 (uchar)(CC_SCSI_RESET
7723 | CC_HALT));
7724 DvcDelayNanoSecond(asc_dvc, 60000);
7725 AscSetChipControl(iop_base, CC_HALT);
7726 AscSetChipStatus(iop_base,
7727 CIW_CLR_SCSI_RESET_INT);
7728 AscSetChipStatus(iop_base, 0);
7729 AscSetChipControl(iop_base, 0);
7730 }
7731 }
7732 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007733 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007734 } else {
7735 if ((AscReadLramByte(iop_base,
7736 (ushort)(q_addr + (ushort)
7737 ASC_SCSIQ_CDB_BEG))
7738 == START_STOP)) {
7739 asc_dvc->unit_not_ready &= ~target_id;
7740 if (scsiq->d3.done_stat != QD_NO_ERROR) {
7741 asc_dvc->start_motor &=
7742 ~target_id;
7743 }
7744 }
7745 }
7746 return (1);
7747 } else {
7748 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
7749 FATAL_ERR_QDONE:
7750 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007751 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007752 }
7753 return (0x80);
7754 }
7755 }
7756 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007757}
7758
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007759static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007760{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007761 ASC_CS_TYPE chipstat;
7762 PortAddr iop_base;
7763 ushort saved_ram_addr;
7764 uchar ctrl_reg;
7765 uchar saved_ctrl_reg;
7766 int int_pending;
7767 int status;
7768 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007769
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007770 iop_base = asc_dvc->iop_base;
7771 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007772
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007773 if (AscIsIntPending(iop_base) == 0) {
7774 return int_pending;
7775 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007776
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007777 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007778 return (ERR);
7779 }
7780 if (asc_dvc->in_critical_cnt != 0) {
7781 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
7782 return (ERR);
7783 }
7784 if (asc_dvc->is_in_int) {
7785 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
7786 return (ERR);
7787 }
7788 asc_dvc->is_in_int = TRUE;
7789 ctrl_reg = AscGetChipControl(iop_base);
7790 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
7791 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
7792 chipstat = AscGetChipStatus(iop_base);
7793 if (chipstat & CSW_SCSI_RESET_LATCH) {
7794 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
7795 int i = 10;
7796 int_pending = TRUE;
7797 asc_dvc->sdtr_done = 0;
7798 saved_ctrl_reg &= (uchar)(~CC_HALT);
7799 while ((AscGetChipStatus(iop_base) &
7800 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
7801 DvcSleepMilliSecond(100);
7802 }
7803 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
7804 AscSetChipControl(iop_base, CC_HALT);
7805 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
7806 AscSetChipStatus(iop_base, 0);
7807 chipstat = AscGetChipStatus(iop_base);
7808 }
7809 }
7810 saved_ram_addr = AscGetChipLramAddr(iop_base);
7811 host_flag = AscReadLramByte(iop_base,
7812 ASCV_HOST_FLAG_B) &
7813 (uchar)(~ASC_HOST_FLAG_IN_ISR);
7814 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7815 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
7816 if ((chipstat & CSW_INT_PENDING)
7817 || (int_pending)
7818 ) {
7819 AscAckInterrupt(iop_base);
7820 int_pending = TRUE;
7821 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
7822 if (AscIsrChipHalted(asc_dvc) == ERR) {
7823 goto ISR_REPORT_QDONE_FATAL_ERROR;
7824 } else {
7825 saved_ctrl_reg &= (uchar)(~CC_HALT);
7826 }
7827 } else {
7828 ISR_REPORT_QDONE_FATAL_ERROR:
7829 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
7830 while (((status =
7831 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
7832 }
7833 } else {
7834 do {
7835 if ((status =
7836 AscIsrQDone(asc_dvc)) == 1) {
7837 break;
7838 }
7839 } while (status == 0x11);
7840 }
7841 if ((status & 0x80) != 0)
7842 int_pending = ERR;
7843 }
7844 }
7845 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7846 AscSetChipLramAddr(iop_base, saved_ram_addr);
7847 AscSetChipControl(iop_base, saved_ctrl_reg);
7848 asc_dvc->is_in_int = FALSE;
7849 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007850}
7851
7852/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007853static uchar _asc_mcode_buf[] = {
7854 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007855 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
7860 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7861 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007862 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007863 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
7864 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
7865 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007866 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007867 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
7868 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
7869 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007870 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007871 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
7872 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
7873 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007874 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007875 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
7876 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
7877 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007878 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007879 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
7880 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
7881 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007882 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007883 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
7884 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
7885 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007886 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007887 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
7888 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
7889 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007890 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007891 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
7892 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
7893 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007894 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007895 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
7896 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
7897 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007898 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007899 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
7900 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
7901 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007902 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007903 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
7904 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
7905 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007906 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007907 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
7908 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
7909 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007910 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007911 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
7912 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
7913 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007914 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007915 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
7916 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
7917 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007918 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007919 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
7920 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
7921 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007922 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007923 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
7924 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
7925 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007926 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007927 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
7928 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
7929 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007930 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007931 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
7932 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
7933 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007934 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007935 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
7936 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
7937 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007938 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007939 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
7940 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
7941 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007942 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007943 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
7944 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
7945 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007946 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007947 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
7948 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
7949 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007950 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007951 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
7952 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
7953 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007954 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007955 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
7956 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
7957 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007958 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007959 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
7960 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
7961 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007962 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007963 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
7964 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
7965 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007966 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007967 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
7968 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
7969 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007970 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007971 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
7972 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
7973 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007974 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007975 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
7976 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
7977 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007978 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007979 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
7980 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
7981 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007982 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007983 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
7984 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
7985 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007986 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007987 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
7988 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
7989 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007990 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007991 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
7992 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
7993 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007994 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007995 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
7996 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
7997 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007998 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007999 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
8000 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
8001 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008002 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008003 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
8004 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
8005 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008006 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008007 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
8008 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
8009 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008010 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008011 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
8012 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
8013 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008014 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008015 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
8016 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
8017 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008018 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008019 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
8020 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
8021 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008022 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008023 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
8024 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
8025 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008026 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008027 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
8028 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
8029 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008030 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008031 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
8032 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
8033 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008034 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008035 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
8036 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
8037 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008038 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008039 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
8040 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
8041 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008042 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06008043 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
8044 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
8045 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07008046};
8047
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008048static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
8049static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008050
8051#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008052static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
8053 INQUIRY,
8054 REQUEST_SENSE,
8055 READ_CAPACITY,
8056 READ_TOC,
8057 MODE_SELECT,
8058 MODE_SENSE,
8059 MODE_SELECT_10,
8060 MODE_SENSE_10,
8061 0xFF,
8062 0xFF,
8063 0xFF,
8064 0xFF,
8065 0xFF,
8066 0xFF,
8067 0xFF,
8068 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07008069};
8070
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008071static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008072{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008073 PortAddr iop_base;
8074 ulong last_int_level;
8075 int sta;
8076 int n_q_required;
8077 int disable_syn_offset_one_fix;
8078 int i;
8079 ASC_PADDR addr;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008080 ushort sg_entry_cnt = 0;
8081 ushort sg_entry_cnt_minus_one = 0;
8082 uchar target_ix;
8083 uchar tid_no;
8084 uchar sdtr_data;
8085 uchar extra_bytes;
8086 uchar scsi_cmd;
8087 uchar disable_cmd;
8088 ASC_SG_HEAD *sg_head;
8089 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008091 iop_base = asc_dvc->iop_base;
8092 sg_head = scsiq->sg_head;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008093 if (asc_dvc->err_code != 0)
8094 return (ERR);
8095 if (scsiq == (ASC_SCSI_Q *)0L) {
8096 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
8097 return (ERR);
8098 }
8099 scsiq->q1.q_no = 0;
8100 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
8101 scsiq->q1.extra_bytes = 0;
8102 }
8103 sta = 0;
8104 target_ix = scsiq->q2.target_ix;
8105 tid_no = ASC_TIX_TO_TID(target_ix);
8106 n_q_required = 1;
8107 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
8108 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
8109 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
8110 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8111 AscMsgOutSDTR(asc_dvc,
8112 asc_dvc->
8113 sdtr_period_tbl[(sdtr_data >> 4) &
8114 (uchar)(asc_dvc->
8115 max_sdtr_index -
8116 1)],
8117 (uchar)(sdtr_data & (uchar)
8118 ASC_SYN_MAX_OFFSET));
8119 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
8120 }
8121 }
8122 last_int_level = DvcEnterCritical();
8123 if (asc_dvc->in_critical_cnt != 0) {
8124 DvcLeaveCritical(last_int_level);
8125 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
8126 return (ERR);
8127 }
8128 asc_dvc->in_critical_cnt++;
8129 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
8130 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
8131 asc_dvc->in_critical_cnt--;
8132 DvcLeaveCritical(last_int_level);
8133 return (ERR);
8134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008135#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008136 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
8137 asc_dvc->in_critical_cnt--;
8138 DvcLeaveCritical(last_int_level);
8139 return (ERR);
8140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008141#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008142 if (sg_entry_cnt == 1) {
8143 scsiq->q1.data_addr =
8144 (ADV_PADDR)sg_head->sg_list[0].addr;
8145 scsiq->q1.data_cnt =
8146 (ADV_DCNT)sg_head->sg_list[0].bytes;
8147 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
8148 }
8149 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
8150 }
8151 scsi_cmd = scsiq->cdbptr[0];
8152 disable_syn_offset_one_fix = FALSE;
8153 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
8154 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
8155 if (scsiq->q1.cntl & QC_SG_HEAD) {
8156 data_cnt = 0;
8157 for (i = 0; i < sg_entry_cnt; i++) {
8158 data_cnt +=
8159 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
8160 bytes);
8161 }
8162 } else {
8163 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
8164 }
8165 if (data_cnt != 0UL) {
8166 if (data_cnt < 512UL) {
8167 disable_syn_offset_one_fix = TRUE;
8168 } else {
8169 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
8170 i++) {
8171 disable_cmd =
8172 _syn_offset_one_disable_cmd[i];
8173 if (disable_cmd == 0xFF) {
8174 break;
8175 }
8176 if (scsi_cmd == disable_cmd) {
8177 disable_syn_offset_one_fix =
8178 TRUE;
8179 break;
8180 }
8181 }
8182 }
8183 }
8184 }
8185 if (disable_syn_offset_one_fix) {
8186 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
8187 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
8188 ASC_TAG_FLAG_DISABLE_DISCONNECT);
8189 } else {
8190 scsiq->q2.tag_code &= 0x27;
8191 }
8192 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
8193 if (asc_dvc->bug_fix_cntl) {
8194 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
8195 if ((scsi_cmd == READ_6) ||
8196 (scsi_cmd == READ_10)) {
8197 addr =
8198 (ADV_PADDR)le32_to_cpu(sg_head->
8199 sg_list
8200 [sg_entry_cnt_minus_one].
8201 addr) +
8202 (ADV_DCNT)le32_to_cpu(sg_head->
8203 sg_list
8204 [sg_entry_cnt_minus_one].
8205 bytes);
8206 extra_bytes =
8207 (uchar)((ushort)addr & 0x0003);
8208 if ((extra_bytes != 0)
8209 &&
8210 ((scsiq->q2.
8211 tag_code &
8212 ASC_TAG_FLAG_EXTRA_BYTES)
8213 == 0)) {
8214 scsiq->q2.tag_code |=
8215 ASC_TAG_FLAG_EXTRA_BYTES;
8216 scsiq->q1.extra_bytes =
8217 extra_bytes;
8218 data_cnt =
8219 le32_to_cpu(sg_head->
8220 sg_list
8221 [sg_entry_cnt_minus_one].
8222 bytes);
8223 data_cnt -=
8224 (ASC_DCNT) extra_bytes;
8225 sg_head->
8226 sg_list
8227 [sg_entry_cnt_minus_one].
8228 bytes =
8229 cpu_to_le32(data_cnt);
8230 }
8231 }
8232 }
8233 }
8234 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008235#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008236 /*
8237 * Set the sg_entry_cnt to the maximum possible. The rest of
8238 * the SG elements will be copied when the RISC completes the
8239 * SG elements that fit and halts.
8240 */
8241 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
8242 sg_entry_cnt = ASC_MAX_SG_LIST;
8243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008244#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008245 n_q_required = AscSgListToQueue(sg_entry_cnt);
8246 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
8247 (uint) n_q_required)
8248 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
8249 if ((sta =
8250 AscSendScsiQueue(asc_dvc, scsiq,
8251 n_q_required)) == 1) {
8252 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008253 DvcLeaveCritical(last_int_level);
8254 return (sta);
8255 }
8256 }
8257 } else {
8258 if (asc_dvc->bug_fix_cntl) {
8259 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
8260 if ((scsi_cmd == READ_6) ||
8261 (scsi_cmd == READ_10)) {
8262 addr =
8263 le32_to_cpu(scsiq->q1.data_addr) +
8264 le32_to_cpu(scsiq->q1.data_cnt);
8265 extra_bytes =
8266 (uchar)((ushort)addr & 0x0003);
8267 if ((extra_bytes != 0)
8268 &&
8269 ((scsiq->q2.
8270 tag_code &
8271 ASC_TAG_FLAG_EXTRA_BYTES)
8272 == 0)) {
8273 data_cnt =
8274 le32_to_cpu(scsiq->q1.
8275 data_cnt);
8276 if (((ushort)data_cnt & 0x01FF)
8277 == 0) {
8278 scsiq->q2.tag_code |=
8279 ASC_TAG_FLAG_EXTRA_BYTES;
8280 data_cnt -= (ASC_DCNT)
8281 extra_bytes;
8282 scsiq->q1.data_cnt =
8283 cpu_to_le32
8284 (data_cnt);
8285 scsiq->q1.extra_bytes =
8286 extra_bytes;
8287 }
8288 }
8289 }
8290 }
8291 }
8292 n_q_required = 1;
8293 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
8294 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
8295 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
8296 n_q_required)) == 1) {
8297 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008298 DvcLeaveCritical(last_int_level);
8299 return (sta);
8300 }
8301 }
8302 }
8303 asc_dvc->in_critical_cnt--;
8304 DvcLeaveCritical(last_int_level);
8305 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008306}
8307
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008308static int
8309AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008310{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008311 PortAddr iop_base;
8312 uchar free_q_head;
8313 uchar next_qp;
8314 uchar tid_no;
8315 uchar target_ix;
8316 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008317
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008318 iop_base = asc_dvc->iop_base;
8319 target_ix = scsiq->q2.target_ix;
8320 tid_no = ASC_TIX_TO_TID(target_ix);
8321 sta = 0;
8322 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
8323 if (n_q_required > 1) {
8324 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
8325 free_q_head, (uchar)
8326 (n_q_required)))
8327 != (uchar)ASC_QLINK_END) {
8328 asc_dvc->last_q_shortage = 0;
8329 scsiq->sg_head->queue_cnt = n_q_required - 1;
8330 scsiq->q1.q_no = free_q_head;
8331 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
8332 free_q_head)) == 1) {
8333 AscPutVarFreeQHead(iop_base, next_qp);
8334 asc_dvc->cur_total_qng += (uchar)(n_q_required);
8335 asc_dvc->cur_dvc_qng[tid_no]++;
8336 }
8337 return (sta);
8338 }
8339 } else if (n_q_required == 1) {
8340 if ((next_qp = AscAllocFreeQueue(iop_base,
8341 free_q_head)) !=
8342 ASC_QLINK_END) {
8343 scsiq->q1.q_no = free_q_head;
8344 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
8345 free_q_head)) == 1) {
8346 AscPutVarFreeQHead(iop_base, next_qp);
8347 asc_dvc->cur_total_qng++;
8348 asc_dvc->cur_dvc_qng[tid_no]++;
8349 }
8350 return (sta);
8351 }
8352 }
8353 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008354}
8355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008356static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008357{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008358 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008359
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008360 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
8361 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
8362 n_sg_list_qs++;
8363 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008364}
8365
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008366static uint
8367AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008368{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008369 uint cur_used_qs;
8370 uint cur_free_qs;
8371 ASC_SCSI_BIT_ID_TYPE target_id;
8372 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008373
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008374 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
8375 tid_no = ASC_TIX_TO_TID(target_ix);
8376 if ((asc_dvc->unit_not_ready & target_id) ||
8377 (asc_dvc->queue_full_or_busy & target_id)) {
8378 return (0);
8379 }
8380 if (n_qs == 1) {
8381 cur_used_qs = (uint) asc_dvc->cur_total_qng +
8382 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
8383 } else {
8384 cur_used_qs = (uint) asc_dvc->cur_total_qng +
8385 (uint) ASC_MIN_FREE_Q;
8386 }
8387 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
8388 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
8389 if (asc_dvc->cur_dvc_qng[tid_no] >=
8390 asc_dvc->max_dvc_qng[tid_no]) {
8391 return (0);
8392 }
8393 return (cur_free_qs);
8394 }
8395 if (n_qs > 1) {
8396 if ((n_qs > asc_dvc->last_q_shortage)
8397 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
8398 asc_dvc->last_q_shortage = n_qs;
8399 }
8400 }
8401 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008402}
8403
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008404static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008405{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008406 ushort q_addr;
8407 uchar tid_no;
8408 uchar sdtr_data;
8409 uchar syn_period_ix;
8410 uchar syn_offset;
8411 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008413 iop_base = asc_dvc->iop_base;
8414 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
8415 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
8416 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
8417 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
8418 syn_period_ix =
8419 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
8420 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
8421 AscMsgOutSDTR(asc_dvc,
8422 asc_dvc->sdtr_period_tbl[syn_period_ix],
8423 syn_offset);
8424 scsiq->q1.cntl |= QC_MSG_OUT;
8425 }
8426 q_addr = ASC_QNO_TO_QADDR(q_no);
8427 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
8428 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
8429 }
8430 scsiq->q1.status = QS_FREE;
8431 AscMemWordCopyPtrToLram(iop_base,
8432 q_addr + ASC_SCSIQ_CDB_BEG,
8433 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008434
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008435 DvcPutScsiQ(iop_base,
8436 q_addr + ASC_SCSIQ_CPY_BEG,
8437 (uchar *)&scsiq->q1.cntl,
8438 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
8439 AscWriteLramWord(iop_base,
8440 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
8441 (ushort)(((ushort)scsiq->q1.
8442 q_no << 8) | (ushort)QS_READY));
8443 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008444}
8445
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008446static int
8447AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008448{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008449 int sta;
8450 int i;
8451 ASC_SG_HEAD *sg_head;
8452 ASC_SG_LIST_Q scsi_sg_q;
8453 ASC_DCNT saved_data_addr;
8454 ASC_DCNT saved_data_cnt;
8455 PortAddr iop_base;
8456 ushort sg_list_dwords;
8457 ushort sg_index;
8458 ushort sg_entry_cnt;
8459 ushort q_addr;
8460 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008462 iop_base = asc_dvc->iop_base;
8463 sg_head = scsiq->sg_head;
8464 saved_data_addr = scsiq->q1.data_addr;
8465 saved_data_cnt = scsiq->q1.data_cnt;
8466 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
8467 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008468#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008469 /*
8470 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
8471 * then not all SG elements will fit in the allocated queues.
8472 * The rest of the SG elements will be copied when the RISC
8473 * completes the SG elements that fit and halts.
8474 */
8475 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
8476 /*
8477 * Set sg_entry_cnt to be the number of SG elements that
8478 * will fit in the allocated SG queues. It is minus 1, because
8479 * the first SG element is handled above. ASC_MAX_SG_LIST is
8480 * already inflated by 1 to account for this. For example it
8481 * may be 50 which is 1 + 7 queues * 7 SG elements.
8482 */
8483 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008485 /*
8486 * Keep track of remaining number of SG elements that will
8487 * need to be handled from a_isr.c.
8488 */
8489 scsiq->remain_sg_entry_cnt =
8490 sg_head->entry_cnt - ASC_MAX_SG_LIST;
8491 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008492#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008493 /*
8494 * Set sg_entry_cnt to be the number of SG elements that
8495 * will fit in the allocated SG queues. It is minus 1, because
8496 * the first SG element is handled above.
8497 */
8498 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008499#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008501#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008502 if (sg_entry_cnt != 0) {
8503 scsiq->q1.cntl |= QC_SG_HEAD;
8504 q_addr = ASC_QNO_TO_QADDR(q_no);
8505 sg_index = 1;
8506 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
8507 scsi_sg_q.sg_head_qp = q_no;
8508 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
8509 for (i = 0; i < sg_head->queue_cnt; i++) {
8510 scsi_sg_q.seq_no = i + 1;
8511 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
8512 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
8513 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
8514 if (i == 0) {
8515 scsi_sg_q.sg_list_cnt =
8516 ASC_SG_LIST_PER_Q;
8517 scsi_sg_q.sg_cur_list_cnt =
8518 ASC_SG_LIST_PER_Q;
8519 } else {
8520 scsi_sg_q.sg_list_cnt =
8521 ASC_SG_LIST_PER_Q - 1;
8522 scsi_sg_q.sg_cur_list_cnt =
8523 ASC_SG_LIST_PER_Q - 1;
8524 }
8525 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008526#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008527 /*
8528 * This is the last SG queue in the list of
8529 * allocated SG queues. If there are more
8530 * SG elements than will fit in the allocated
8531 * queues, then set the QCSG_SG_XFER_MORE flag.
8532 */
8533 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
8534 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
8535 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008536#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008537 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008538#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008540#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008541 sg_list_dwords = sg_entry_cnt << 1;
8542 if (i == 0) {
8543 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
8544 scsi_sg_q.sg_cur_list_cnt =
8545 sg_entry_cnt;
8546 } else {
8547 scsi_sg_q.sg_list_cnt =
8548 sg_entry_cnt - 1;
8549 scsi_sg_q.sg_cur_list_cnt =
8550 sg_entry_cnt - 1;
8551 }
8552 sg_entry_cnt = 0;
8553 }
8554 next_qp = AscReadLramByte(iop_base,
8555 (ushort)(q_addr +
8556 ASC_SCSIQ_B_FWD));
8557 scsi_sg_q.q_no = next_qp;
8558 q_addr = ASC_QNO_TO_QADDR(next_qp);
8559 AscMemWordCopyPtrToLram(iop_base,
8560 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
8561 (uchar *)&scsi_sg_q,
8562 sizeof(ASC_SG_LIST_Q) >> 1);
8563 AscMemDWordCopyPtrToLram(iop_base,
8564 q_addr + ASC_SGQ_LIST_BEG,
8565 (uchar *)&sg_head->
8566 sg_list[sg_index],
8567 sg_list_dwords);
8568 sg_index += ASC_SG_LIST_PER_Q;
8569 scsiq->next_sg_index = sg_index;
8570 }
8571 } else {
8572 scsiq->q1.cntl &= ~QC_SG_HEAD;
8573 }
8574 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
8575 scsiq->q1.data_addr = saved_data_addr;
8576 scsiq->q1.data_cnt = saved_data_cnt;
8577 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008578}
8579
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008580static int
8581AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008582{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008583 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008584
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008585 if (AscHostReqRiscHalt(iop_base)) {
8586 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8587 AscStartChip(iop_base);
8588 return (sta);
8589 }
8590 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008591}
8592
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008593static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008594{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008595 ASC_SCSI_BIT_ID_TYPE org_id;
8596 int i;
8597 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008598
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008599 AscSetBank(iop_base, 1);
8600 org_id = AscReadChipDvcID(iop_base);
8601 for (i = 0; i <= ASC_MAX_TID; i++) {
8602 if (org_id == (0x01 << i))
8603 break;
8604 }
8605 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8606 AscWriteChipDvcID(iop_base, id);
8607 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8608 AscSetBank(iop_base, 0);
8609 AscSetChipSyn(iop_base, sdtr_data);
8610 if (AscGetChipSyn(iop_base) != sdtr_data) {
8611 sta = FALSE;
8612 }
8613 } else {
8614 sta = FALSE;
8615 }
8616 AscSetBank(iop_base, 1);
8617 AscWriteChipDvcID(iop_base, org_id);
8618 AscSetBank(iop_base, 0);
8619 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008620}
8621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008622static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008623{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008624 uchar i;
8625 ushort s_addr;
8626 PortAddr iop_base;
8627 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008629 iop_base = asc_dvc->iop_base;
8630 warn_code = 0;
8631 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
8632 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
8633 64) >> 1)
8634 );
8635 i = ASC_MIN_ACTIVE_QNO;
8636 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
8637 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8638 (uchar)(i + 1));
8639 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8640 (uchar)(asc_dvc->max_total_qng));
8641 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8642 (uchar)i);
8643 i++;
8644 s_addr += ASC_QBLK_SIZE;
8645 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
8646 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8647 (uchar)(i + 1));
8648 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8649 (uchar)(i - 1));
8650 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8651 (uchar)i);
8652 }
8653 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8654 (uchar)ASC_QLINK_END);
8655 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8656 (uchar)(asc_dvc->max_total_qng - 1));
8657 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8658 (uchar)asc_dvc->max_total_qng);
8659 i++;
8660 s_addr += ASC_QBLK_SIZE;
8661 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
8662 i++, s_addr += ASC_QBLK_SIZE) {
8663 AscWriteLramByte(iop_base,
8664 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
8665 AscWriteLramByte(iop_base,
8666 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
8667 AscWriteLramByte(iop_base,
8668 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
8669 }
8670 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008671}
8672
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008673static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008674{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008675 PortAddr iop_base;
8676 int i;
8677 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008679 iop_base = asc_dvc->iop_base;
8680 AscPutRiscVarFreeQHead(iop_base, 1);
8681 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8682 AscPutVarFreeQHead(iop_base, 1);
8683 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8684 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
8685 (uchar)((int)asc_dvc->max_total_qng + 1));
8686 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
8687 (uchar)((int)asc_dvc->max_total_qng + 2));
8688 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
8689 asc_dvc->max_total_qng);
8690 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
8691 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8692 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
8693 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
8694 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
8695 AscPutQDoneInProgress(iop_base, 0);
8696 lram_addr = ASC_QADR_BEG;
8697 for (i = 0; i < 32; i++, lram_addr += 2) {
8698 AscWriteLramWord(iop_base, lram_addr, 0);
8699 }
8700 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008701}
8702
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008703static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008704{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008705 if (asc_dvc->err_code == 0) {
8706 asc_dvc->err_code = err_code;
8707 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8708 err_code);
8709 }
8710 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008711}
8712
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008713static uchar
8714AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008715{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008716 EXT_MSG sdtr_buf;
8717 uchar sdtr_period_index;
8718 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008720 iop_base = asc_dvc->iop_base;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008721 sdtr_buf.msg_type = EXTENDED_MESSAGE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008722 sdtr_buf.msg_len = MS_SDTR_LEN;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008723 sdtr_buf.msg_req = EXTENDED_SDTR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008724 sdtr_buf.xfer_period = sdtr_period;
8725 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8726 sdtr_buf.req_ack_offset = sdtr_offset;
8727 if ((sdtr_period_index =
8728 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
8729 asc_dvc->max_sdtr_index) {
8730 AscMemWordCopyPtrToLram(iop_base,
8731 ASCV_MSGOUT_BEG,
8732 (uchar *)&sdtr_buf,
8733 sizeof(EXT_MSG) >> 1);
8734 return ((sdtr_period_index << 4) | sdtr_offset);
8735 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008736
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008737 sdtr_buf.req_ack_offset = 0;
8738 AscMemWordCopyPtrToLram(iop_base,
8739 ASCV_MSGOUT_BEG,
8740 (uchar *)&sdtr_buf,
8741 sizeof(EXT_MSG) >> 1);
8742 return (0);
8743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008744}
8745
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008746static uchar
8747AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008748{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008749 uchar byte;
8750 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008751
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008752 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8753 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
8754 ) {
8755 return (0xFF);
8756 }
8757 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8758 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008759}
8760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008761static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008762{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008763 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8764 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8765 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008766}
8767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008768static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008769{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008770 uchar *period_table;
8771 int max_index;
8772 int min_index;
8773 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008774
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008775 period_table = asc_dvc->sdtr_period_tbl;
8776 max_index = (int)asc_dvc->max_sdtr_index;
8777 min_index = (int)asc_dvc->host_init_sdtr_index;
8778 if ((syn_time <= period_table[max_index])) {
8779 for (i = min_index; i < (max_index - 1); i++) {
8780 if (syn_time <= period_table[i]) {
8781 return ((uchar)i);
8782 }
8783 }
8784 return ((uchar)max_index);
8785 } else {
8786 return ((uchar)(max_index + 1));
8787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008788}
8789
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008790static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008791{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008792 ushort q_addr;
8793 uchar next_qp;
8794 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008796 q_addr = ASC_QNO_TO_QADDR(free_q_head);
8797 q_status = (uchar)AscReadLramByte(iop_base,
8798 (ushort)(q_addr +
8799 ASC_SCSIQ_B_STATUS));
8800 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
8801 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
8802 return (next_qp);
8803 }
8804 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008805}
8806
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008807static uchar
8808AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008809{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008810 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008811
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008812 for (i = 0; i < n_free_q; i++) {
8813 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
8814 == ASC_QLINK_END) {
8815 return (ASC_QLINK_END);
8816 }
8817 }
8818 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008819}
8820
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008821static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008822{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008823 int count = 0;
8824 int sta = 0;
8825 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008826
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008827 if (AscIsChipHalted(iop_base))
8828 return (1);
8829 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
8830 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8831 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
8832 do {
8833 if (AscIsChipHalted(iop_base)) {
8834 sta = 1;
8835 break;
8836 }
8837 DvcSleepMilliSecond(100);
8838 } while (count++ < 20);
8839 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
8840 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008841}
8842
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008843static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008844{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008845 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008846
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008847 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
8848 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8849 ASC_STOP_REQ_RISC_STOP);
8850 do {
8851 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
8852 ASC_STOP_ACK_RISC_STOP) {
8853 return (1);
8854 }
8855 DvcSleepMilliSecond(100);
8856 } while (count++ < 20);
8857 }
8858 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008859}
8860
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008861static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008862{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008863 udelay(micro_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008864}
8865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008866static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008867{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008868 udelay((nano_sec + 999) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008869}
8870
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008871static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008872{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008873 AscSetChipControl(iop_base, 0);
8874 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8875 return (0);
8876 }
8877 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008878}
8879
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008880static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008881{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008882 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008883
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008884 cc_val =
8885 AscGetChipControl(iop_base) &
8886 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
8887 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
8888 AscSetChipIH(iop_base, INS_HALT);
8889 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8890 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
8891 return (0);
8892 }
8893 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008894}
8895
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008896static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008897{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008898 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8899 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
8900 return (1);
8901 }
8902 }
8903 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008904}
8905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008906static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008907{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008908 AscSetBank(iop_base, 1);
8909 AscWriteChipIH(iop_base, ins_code);
8910 AscSetBank(iop_base, 0);
8911 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008912}
8913
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008914static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008915{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008916 uchar host_flag;
8917 uchar risc_flag;
8918 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008919
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008920 loop = 0;
8921 do {
8922 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8923 if (loop++ > 0x7FFF) {
8924 break;
8925 }
8926 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8927 host_flag =
8928 AscReadLramByte(iop_base,
8929 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8930 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8931 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8932 AscSetChipStatus(iop_base, CIW_INT_ACK);
8933 loop = 0;
8934 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8935 AscSetChipStatus(iop_base, CIW_INT_ACK);
8936 if (loop++ > 3) {
8937 break;
8938 }
8939 }
8940 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8941 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008942}
8943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008944static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008945{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008946 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008948 cfg = AscGetChipCfgLsw(iop_base);
8949 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
8950 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008951}
8952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008953static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008954{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008955 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008956
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008957 cfg = AscGetChipCfgLsw(iop_base);
8958 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
8959 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008960}
8961
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008962static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008963{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008964 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008965
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008966 val = AscGetChipControl(iop_base) &
8967 (~
8968 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
8969 CC_CHIP_RESET));
8970 if (bank == 1) {
8971 val |= CC_BANK_ONE;
8972 } else if (bank == 2) {
8973 val |= CC_DIAG | CC_BANK_ONE;
8974 } else {
8975 val &= ~CC_BANK_ONE;
8976 }
8977 AscSetChipControl(iop_base, val);
8978 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008979}
8980
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008981static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008982{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008983 PortAddr iop_base;
8984 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008985
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008986 iop_base = asc_dvc->iop_base;
8987 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
8988 && (i-- > 0)) {
8989 DvcSleepMilliSecond(100);
8990 }
8991 AscStopChip(iop_base);
8992 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
8993 DvcDelayNanoSecond(asc_dvc, 60000);
8994 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8995 AscSetChipIH(iop_base, INS_HALT);
8996 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
8997 AscSetChipControl(iop_base, CC_HALT);
8998 DvcSleepMilliSecond(200);
8999 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
9000 AscSetChipStatus(iop_base, 0);
9001 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009002}
9003
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009004static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009005{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009006 if (bus_type & ASC_IS_ISA)
9007 return (ASC_MAX_ISA_DMA_COUNT);
9008 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
9009 return (ASC_MAX_VL_DMA_COUNT);
9010 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009011}
9012
9013#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009014static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009015{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009016 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009017
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009018 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
9019 if (channel == 0x03)
9020 return (0);
9021 else if (channel == 0x00)
9022 return (7);
9023 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009024}
9025
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009026static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009027{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009028 ushort cfg_lsw;
9029 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009031 if ((dma_channel >= 5) && (dma_channel <= 7)) {
9032 if (dma_channel == 7)
9033 value = 0x00;
9034 else
9035 value = dma_channel - 4;
9036 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
9037 cfg_lsw |= value;
9038 AscSetChipCfgLsw(iop_base, cfg_lsw);
9039 return (AscGetIsaDmaChannel(iop_base));
9040 }
9041 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009042}
9043
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009044static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009045{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009046 speed_value &= 0x07;
9047 AscSetBank(iop_base, 1);
9048 AscWriteChipDmaSpeed(iop_base, speed_value);
9049 AscSetBank(iop_base, 0);
9050 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009051}
9052
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009053static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009054{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009055 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009056
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009057 AscSetBank(iop_base, 1);
9058 speed_value = AscReadChipDmaSpeed(iop_base);
9059 speed_value &= 0x07;
9060 AscSetBank(iop_base, 0);
9061 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009062}
9063#endif /* CONFIG_ISA */
9064
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009065static int __devinit AscInitGetConfig(asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009066{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009067 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -06009068 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009069
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009070 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
Matthew Wilcox9649af32007-07-26 21:51:47 -06009071 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009072 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009073
Matthew Wilcox9649af32007-07-26 21:51:47 -06009074 if (AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009075 warn_code |= AscInitAscDvcVar(asc_dvc);
9076 warn_code |= AscInitFromEEP(asc_dvc);
9077 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06009078 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009079 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009080 } else {
9081 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
9082 }
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009083
9084 switch (warn_code) {
9085 case 0: /* No error */
9086 break;
9087 case ASC_WARN_IO_PORT_ROTATE:
9088 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
9089 "modified\n", boardp->id);
9090 break;
9091 case ASC_WARN_AUTO_CONFIG:
9092 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
9093 "switch enabled\n", boardp->id);
9094 break;
9095 case ASC_WARN_EEPROM_CHKSUM:
9096 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
9097 "error\n", boardp->id);
9098 break;
9099 case ASC_WARN_IRQ_MODIFIED:
9100 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
9101 boardp->id);
9102 break;
9103 case ASC_WARN_CMD_QNG_CONFLICT:
9104 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
9105 "w/o disconnects\n", boardp->id);
9106 break;
9107 default:
9108 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
9109 "0x%x\n", boardp->id, warn_code);
9110 break;
9111 }
9112
9113 if (asc_dvc->err_code != 0) {
9114 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
9115 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
9116 asc_dvc->err_code);
9117 }
9118
9119 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009120}
9121
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009122static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009123{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009124 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04009125 PortAddr iop_base = asc_dvc->iop_base;
9126 unsigned short cfg_msw;
9127 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009128
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009129 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
9130 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009131 return asc_dvc->err_code;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04009132 if (!AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009133 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009134 return asc_dvc->err_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009136
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009137 cfg_msw = AscGetChipCfgMsw(iop_base);
9138 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009139 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009140 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
9141 AscSetChipCfgMsw(iop_base, cfg_msw);
9142 }
9143 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
9144 asc_dvc->cfg->cmd_qng_enabled) {
9145 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
9146 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
9147 }
9148 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
9149 warn_code |= ASC_WARN_AUTO_CONFIG;
9150 }
9151 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
9152 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
9153 != asc_dvc->irq_no) {
9154 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
9155 }
9156 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06009157#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009158 if (asc_dvc->bus_type & ASC_IS_PCI) {
9159 cfg_msw &= 0xFFC0;
9160 AscSetChipCfgMsw(iop_base, cfg_msw);
9161 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
9162 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -06009163 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
9164 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009165 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
9166 asc_dvc->bug_fix_cntl |=
9167 ASC_BUG_FIX_ASYN_USE_SYN;
9168 }
9169 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06009170 } else
9171#endif /* CONFIG_PCI */
9172 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009173 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
9174 == ASC_CHIP_VER_ASYN_BUG) {
9175 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
9176 }
9177 }
9178 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
9179 asc_dvc->cfg->chip_scsi_id) {
9180 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
9181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009182#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009183 if (asc_dvc->bus_type & ASC_IS_ISA) {
9184 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
9185 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
9186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009187#endif /* CONFIG_ISA */
Matthew Wilcox394dbf32007-07-26 11:56:40 -04009188
9189 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009190
9191 switch (warn_code) {
9192 case 0: /* No error. */
9193 break;
9194 case ASC_WARN_IO_PORT_ROTATE:
9195 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
9196 "modified\n", boardp->id);
9197 break;
9198 case ASC_WARN_AUTO_CONFIG:
9199 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
9200 "switch enabled\n", boardp->id);
9201 break;
9202 case ASC_WARN_EEPROM_CHKSUM:
9203 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
9204 "error\n", boardp->id);
9205 break;
9206 case ASC_WARN_IRQ_MODIFIED:
9207 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
9208 boardp->id);
9209 break;
9210 case ASC_WARN_CMD_QNG_CONFLICT:
9211 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
9212 "disconnects\n",
9213 boardp->id);
9214 break;
9215 default:
9216 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
9217 "0x%x\n", boardp->id, warn_code);
9218 break;
9219 }
9220
9221 if (asc_dvc->err_code != 0) {
9222 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
9223 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
9224 asc_dvc->err_code);
9225 }
9226
9227 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009228}
9229
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009230static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009231{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009232 ushort warn_code;
9233 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009234
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009235 iop_base = asc_dvc->iop_base;
9236 warn_code = 0;
9237 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
9238 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
9239 AscResetChipAndScsiBus(asc_dvc);
9240 DvcSleepMilliSecond((ASC_DCNT)
9241 ((ushort)asc_dvc->scsi_reset_wait * 1000));
9242 }
9243 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
9244 if (asc_dvc->err_code != 0)
9245 return (UW_ERR);
9246 if (!AscFindSignature(asc_dvc->iop_base)) {
9247 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
9248 return (warn_code);
9249 }
9250 AscDisableInterrupt(iop_base);
9251 warn_code |= AscInitLram(asc_dvc);
9252 if (asc_dvc->err_code != 0)
9253 return (UW_ERR);
9254 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
9255 (ulong)_asc_mcode_chksum);
9256 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
9257 _asc_mcode_size) != _asc_mcode_chksum) {
9258 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
9259 return (warn_code);
9260 }
9261 warn_code |= AscInitMicroCodeVar(asc_dvc);
9262 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
9263 AscEnableInterrupt(iop_base);
9264 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009265}
9266
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009267static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009268{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009269 int i;
9270 PortAddr iop_base;
9271 ushort warn_code;
9272 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009273
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009274 iop_base = asc_dvc->iop_base;
9275 warn_code = 0;
9276 asc_dvc->err_code = 0;
9277 if ((asc_dvc->bus_type &
9278 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
9279 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
9280 }
9281 AscSetChipControl(iop_base, CC_HALT);
9282 AscSetChipStatus(iop_base, 0);
9283 asc_dvc->bug_fix_cntl = 0;
9284 asc_dvc->pci_fix_asyn_xfer = 0;
9285 asc_dvc->pci_fix_asyn_xfer_always = 0;
9286 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
9287 asc_dvc->sdtr_done = 0;
9288 asc_dvc->cur_total_qng = 0;
9289 asc_dvc->is_in_int = 0;
9290 asc_dvc->in_critical_cnt = 0;
9291 asc_dvc->last_q_shortage = 0;
9292 asc_dvc->use_tagged_qng = 0;
9293 asc_dvc->no_scam = 0;
9294 asc_dvc->unit_not_ready = 0;
9295 asc_dvc->queue_full_or_busy = 0;
9296 asc_dvc->redo_scam = 0;
9297 asc_dvc->res2 = 0;
9298 asc_dvc->host_init_sdtr_index = 0;
9299 asc_dvc->cfg->can_tagged_qng = 0;
9300 asc_dvc->cfg->cmd_qng_enabled = 0;
9301 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
9302 asc_dvc->init_sdtr = 0;
9303 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
9304 asc_dvc->scsi_reset_wait = 3;
9305 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
9306 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
9307 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
9308 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
9309 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
9310 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
9311 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
9312 ASC_LIB_VERSION_MINOR;
9313 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
9314 asc_dvc->cfg->chip_version = chip_version;
9315 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
9316 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
9317 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
9318 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
9319 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
9320 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
9321 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
9322 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
9323 asc_dvc->max_sdtr_index = 7;
9324 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
9325 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
9326 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
9327 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
9328 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
9329 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
9330 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
9331 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
9332 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
9333 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
9334 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
9335 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
9336 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
9337 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
9338 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
9339 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
9340 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
9341 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
9342 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
9343 asc_dvc->max_sdtr_index = 15;
9344 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
9345 AscSetExtraControl(iop_base,
9346 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
9347 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
9348 AscSetExtraControl(iop_base,
9349 (SEC_ACTIVE_NEGATE |
9350 SEC_ENABLE_FILTER));
9351 }
9352 }
9353 if (asc_dvc->bus_type == ASC_IS_PCI) {
9354 AscSetExtraControl(iop_base,
9355 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
9356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009358 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009359#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009360 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
Matthew Wilcox59fcf842007-07-26 11:54:15 -04009361 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
9362 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
9363 asc_dvc->bus_type = ASC_IS_ISAPNP;
9364 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009365 asc_dvc->cfg->isa_dma_channel =
9366 (uchar)AscGetIsaDmaChannel(iop_base);
9367 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009368#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009369 for (i = 0; i <= ASC_MAX_TID; i++) {
9370 asc_dvc->cur_dvc_qng[i] = 0;
9371 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
9372 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
9373 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
9374 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
9375 }
9376 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009377}
9378
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009379static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009380{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009381 ASCEEP_CONFIG eep_config_buf;
9382 ASCEEP_CONFIG *eep_config;
9383 PortAddr iop_base;
9384 ushort chksum;
9385 ushort warn_code;
9386 ushort cfg_msw, cfg_lsw;
9387 int i;
9388 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009389
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009390 iop_base = asc_dvc->iop_base;
9391 warn_code = 0;
9392 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
9393 AscStopQueueExe(iop_base);
9394 if ((AscStopChip(iop_base) == FALSE) ||
9395 (AscGetChipScsiCtrl(iop_base) != 0)) {
9396 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
9397 AscResetChipAndScsiBus(asc_dvc);
9398 DvcSleepMilliSecond((ASC_DCNT)
9399 ((ushort)asc_dvc->scsi_reset_wait * 1000));
9400 }
9401 if (AscIsChipHalted(iop_base) == FALSE) {
9402 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
9403 return (warn_code);
9404 }
9405 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
9406 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
9407 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
9408 return (warn_code);
9409 }
9410 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
9411 cfg_msw = AscGetChipCfgMsw(iop_base);
9412 cfg_lsw = AscGetChipCfgLsw(iop_base);
9413 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06009414 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009415 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
9416 AscSetChipCfgMsw(iop_base, cfg_msw);
9417 }
9418 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
9419 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
9420 if (chksum == 0) {
9421 chksum = 0xaa55;
9422 }
9423 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
9424 warn_code |= ASC_WARN_AUTO_CONFIG;
9425 if (asc_dvc->cfg->chip_version == 3) {
9426 if (eep_config->cfg_lsw != cfg_lsw) {
9427 warn_code |= ASC_WARN_EEPROM_RECOVER;
9428 eep_config->cfg_lsw =
9429 AscGetChipCfgLsw(iop_base);
9430 }
9431 if (eep_config->cfg_msw != cfg_msw) {
9432 warn_code |= ASC_WARN_EEPROM_RECOVER;
9433 eep_config->cfg_msw =
9434 AscGetChipCfgMsw(iop_base);
9435 }
9436 }
9437 }
9438 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
9439 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
9440 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
9441 eep_config->chksum);
9442 if (chksum != eep_config->chksum) {
9443 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
9444 ASC_CHIP_VER_PCI_ULTRA_3050) {
9445 ASC_DBG(1,
9446 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
9447 eep_config->init_sdtr = 0xFF;
9448 eep_config->disc_enable = 0xFF;
9449 eep_config->start_motor = 0xFF;
9450 eep_config->use_cmd_qng = 0;
9451 eep_config->max_total_qng = 0xF0;
9452 eep_config->max_tag_qng = 0x20;
9453 eep_config->cntl = 0xBFFF;
9454 ASC_EEP_SET_CHIP_ID(eep_config, 7);
9455 eep_config->no_scam = 0;
9456 eep_config->adapter_info[0] = 0;
9457 eep_config->adapter_info[1] = 0;
9458 eep_config->adapter_info[2] = 0;
9459 eep_config->adapter_info[3] = 0;
9460 eep_config->adapter_info[4] = 0;
9461 /* Indicate EEPROM-less board. */
9462 eep_config->adapter_info[5] = 0xBB;
9463 } else {
9464 ASC_PRINT
9465 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
9466 write_eep = 1;
9467 warn_code |= ASC_WARN_EEPROM_CHKSUM;
9468 }
9469 }
9470 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
9471 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
9472 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
9473 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
9474 asc_dvc->start_motor = eep_config->start_motor;
9475 asc_dvc->dvc_cntl = eep_config->cntl;
9476 asc_dvc->no_scam = eep_config->no_scam;
9477 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
9478 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
9479 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
9480 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
9481 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
9482 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
9483 if (!AscTestExternalLram(asc_dvc)) {
9484 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
9485 ASC_IS_PCI_ULTRA)) {
9486 eep_config->max_total_qng =
9487 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
9488 eep_config->max_tag_qng =
9489 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
9490 } else {
9491 eep_config->cfg_msw |= 0x0800;
9492 cfg_msw |= 0x0800;
9493 AscSetChipCfgMsw(iop_base, cfg_msw);
9494 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
9495 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
9496 }
9497 } else {
9498 }
9499 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
9500 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
9501 }
9502 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
9503 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
9504 }
9505 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
9506 eep_config->max_tag_qng = eep_config->max_total_qng;
9507 }
9508 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
9509 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
9510 }
9511 asc_dvc->max_total_qng = eep_config->max_total_qng;
9512 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
9513 eep_config->use_cmd_qng) {
9514 eep_config->disc_enable = eep_config->use_cmd_qng;
9515 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
9516 }
9517 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
9518 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
9519 }
9520 ASC_EEP_SET_CHIP_ID(eep_config,
9521 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
9522 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
9523 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
9524 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
9525 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
9526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009527
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009528 for (i = 0; i <= ASC_MAX_TID; i++) {
9529 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
9530 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
9531 asc_dvc->cfg->sdtr_period_offset[i] =
9532 (uchar)(ASC_DEF_SDTR_OFFSET |
9533 (asc_dvc->host_init_sdtr_index << 4));
9534 }
9535 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
9536 if (write_eep) {
9537 if ((i =
9538 AscSetEEPConfig(iop_base, eep_config,
9539 asc_dvc->bus_type)) != 0) {
9540 ASC_PRINT1
9541 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
9542 i);
9543 } else {
9544 ASC_PRINT
9545 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
9546 }
9547 }
9548 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009549}
9550
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009551static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009552{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009553 int i;
9554 ushort warn_code;
9555 PortAddr iop_base;
9556 ASC_PADDR phy_addr;
9557 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009558
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009559 iop_base = asc_dvc->iop_base;
9560 warn_code = 0;
9561 for (i = 0; i <= ASC_MAX_TID; i++) {
9562 AscPutMCodeInitSDTRAtID(iop_base, i,
9563 asc_dvc->cfg->sdtr_period_offset[i]
9564 );
9565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009566
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009567 AscInitQLinkVar(asc_dvc);
9568 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
9569 asc_dvc->cfg->disc_enable);
9570 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
9571 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009572
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009573 /* Align overrun buffer on an 8 byte boundary. */
9574 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
9575 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
9576 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
9577 (uchar *)&phy_addr, 1);
9578 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
9579 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
9580 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009581
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009582 asc_dvc->cfg->mcode_date =
9583 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
9584 asc_dvc->cfg->mcode_version =
9585 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009586
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009587 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
9588 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
9589 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
9590 return (warn_code);
9591 }
9592 if (AscStartChip(iop_base) != 1) {
9593 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
9594 return (warn_code);
9595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009596
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009597 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009598}
9599
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009600static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009601{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009602 PortAddr iop_base;
9603 ushort q_addr;
9604 ushort saved_word;
9605 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009607 iop_base = asc_dvc->iop_base;
9608 sta = 0;
9609 q_addr = ASC_QNO_TO_QADDR(241);
9610 saved_word = AscReadLramWord(iop_base, q_addr);
9611 AscSetChipLramAddr(iop_base, q_addr);
9612 AscSetChipLramData(iop_base, 0x55AA);
9613 DvcSleepMilliSecond(10);
9614 AscSetChipLramAddr(iop_base, q_addr);
9615 if (AscGetChipLramData(iop_base) == 0x55AA) {
9616 sta = 1;
9617 AscWriteLramWord(iop_base, q_addr, saved_word);
9618 }
9619 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009620}
9621
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009622static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009623{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009624 uchar read_back;
9625 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009626
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009627 retry = 0;
9628 while (TRUE) {
9629 AscSetChipEEPCmd(iop_base, cmd_reg);
9630 DvcSleepMilliSecond(1);
9631 read_back = AscGetChipEEPCmd(iop_base);
9632 if (read_back == cmd_reg) {
9633 return (1);
9634 }
9635 if (retry++ > ASC_EEP_MAX_RETRY) {
9636 return (0);
9637 }
9638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009639}
9640
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009641static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009642{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009643 ushort read_back;
9644 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009645
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009646 retry = 0;
9647 while (TRUE) {
9648 AscSetChipEEPData(iop_base, data_reg);
9649 DvcSleepMilliSecond(1);
9650 read_back = AscGetChipEEPData(iop_base);
9651 if (read_back == data_reg) {
9652 return (1);
9653 }
9654 if (retry++ > ASC_EEP_MAX_RETRY) {
9655 return (0);
9656 }
9657 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009658}
9659
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009660static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009661{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009662 DvcSleepMilliSecond(1);
9663 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009664}
9665
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009666static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009667{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009668 DvcSleepMilliSecond(20);
9669 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009670}
9671
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009672static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009673{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009674 ushort read_wval;
9675 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009676
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009677 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9678 AscWaitEEPRead();
9679 cmd_reg = addr | ASC_EEP_CMD_READ;
9680 AscWriteEEPCmdReg(iop_base, cmd_reg);
9681 AscWaitEEPRead();
9682 read_wval = AscGetChipEEPData(iop_base);
9683 AscWaitEEPRead();
9684 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009685}
9686
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009687static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009688AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009689{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009690 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009691
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009692 read_wval = AscReadEEPWord(iop_base, addr);
9693 if (read_wval != word_val) {
9694 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
9695 AscWaitEEPRead();
9696 AscWriteEEPDataReg(iop_base, word_val);
9697 AscWaitEEPRead();
9698 AscWriteEEPCmdReg(iop_base,
9699 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
9700 AscWaitEEPWrite();
9701 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9702 AscWaitEEPRead();
9703 return (AscReadEEPWord(iop_base, addr));
9704 }
9705 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009706}
9707
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009708static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009709AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009710{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009711 ushort wval;
9712 ushort sum;
9713 ushort *wbuf;
9714 int cfg_beg;
9715 int cfg_end;
9716 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
9717 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009719 wbuf = (ushort *)cfg_buf;
9720 sum = 0;
9721 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
9722 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9723 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9724 sum += *wbuf;
9725 }
9726 if (bus_type & ASC_IS_VL) {
9727 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9728 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9729 } else {
9730 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9731 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9732 }
9733 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9734 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
9735 if (s_addr <= uchar_end_in_config) {
9736 /*
9737 * Swap all char fields - must unswap bytes already swapped
9738 * by AscReadEEPWord().
9739 */
9740 *wbuf = le16_to_cpu(wval);
9741 } else {
9742 /* Don't swap word field at the end - cntl field. */
9743 *wbuf = wval;
9744 }
9745 sum += wval; /* Checksum treats all EEPROM data as words. */
9746 }
9747 /*
9748 * Read the checksum word which will be compared against 'sum'
9749 * by the caller. Word field already swapped.
9750 */
9751 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9752 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009753}
9754
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009755static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009756AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009757{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009758 int n_error;
9759 ushort *wbuf;
9760 ushort word;
9761 ushort sum;
9762 int s_addr;
9763 int cfg_beg;
9764 int cfg_end;
9765 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009767 wbuf = (ushort *)cfg_buf;
9768 n_error = 0;
9769 sum = 0;
9770 /* Write two config words; AscWriteEEPWord() will swap bytes. */
9771 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9772 sum += *wbuf;
9773 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9774 n_error++;
9775 }
9776 }
9777 if (bus_type & ASC_IS_VL) {
9778 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9779 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9780 } else {
9781 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9782 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9783 }
9784 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9785 if (s_addr <= uchar_end_in_config) {
9786 /*
9787 * This is a char field. Swap char fields before they are
9788 * swapped again by AscWriteEEPWord().
9789 */
9790 word = cpu_to_le16(*wbuf);
9791 if (word !=
9792 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
9793 n_error++;
9794 }
9795 } else {
9796 /* Don't swap word field at the end - cntl field. */
9797 if (*wbuf !=
9798 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9799 n_error++;
9800 }
9801 }
9802 sum += *wbuf; /* Checksum calculated from word values. */
9803 }
9804 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
9805 *wbuf = sum;
9806 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
9807 n_error++;
9808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009809
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009810 /* Read EEPROM back again. */
9811 wbuf = (ushort *)cfg_buf;
9812 /*
9813 * Read two config words; Byte-swapping done by AscReadEEPWord().
9814 */
9815 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9816 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
9817 n_error++;
9818 }
9819 }
9820 if (bus_type & ASC_IS_VL) {
9821 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9822 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9823 } else {
9824 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9825 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9826 }
9827 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9828 if (s_addr <= uchar_end_in_config) {
9829 /*
9830 * Swap all char fields. Must unswap bytes already swapped
9831 * by AscReadEEPWord().
9832 */
9833 word =
9834 le16_to_cpu(AscReadEEPWord
9835 (iop_base, (uchar)s_addr));
9836 } else {
9837 /* Don't swap word field at the end - cntl field. */
9838 word = AscReadEEPWord(iop_base, (uchar)s_addr);
9839 }
9840 if (*wbuf != word) {
9841 n_error++;
9842 }
9843 }
9844 /* Read checksum; Byte swapping not needed. */
9845 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
9846 n_error++;
9847 }
9848 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009849}
9850
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009851static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009852AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009853{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009854 int retry;
9855 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009856
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009857 retry = 0;
9858 while (TRUE) {
9859 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
9860 bus_type)) == 0) {
9861 break;
9862 }
9863 if (++retry > ASC_EEP_MAX_RETRY) {
9864 break;
9865 }
9866 }
9867 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009868}
9869
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009870static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009871{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009872 char type = sdev->type;
9873 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009875 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
9876 if (!(asc_dvc->init_sdtr & tid_bits)) {
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009877 if ((type == TYPE_ROM) &&
9878 (strncmp(sdev->vendor, "HP ", 3) == 0)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009879 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9880 }
9881 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009882 if ((type == TYPE_PROCESSOR) ||
9883 (type == TYPE_SCANNER) || (type == TYPE_ROM) ||
9884 (type == TYPE_TAPE)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009885 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009888 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
9889 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009890 sdev->id,
9891 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009892 }
9893 }
9894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009895}
9896
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009897static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009898{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009899 uchar byte_data;
9900 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009901
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009902 if (isodd_word(addr)) {
9903 AscSetChipLramAddr(iop_base, addr - 1);
9904 word_data = AscGetChipLramData(iop_base);
9905 byte_data = (uchar)((word_data >> 8) & 0xFF);
9906 } else {
9907 AscSetChipLramAddr(iop_base, addr);
9908 word_data = AscGetChipLramData(iop_base);
9909 byte_data = (uchar)(word_data & 0xFF);
9910 }
9911 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009912}
Linus Torvalds1da177e2005-04-16 15:20:36 -07009913
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009914static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
9915{
9916 ushort word_data;
9917
9918 AscSetChipLramAddr(iop_base, addr);
9919 word_data = AscGetChipLramData(iop_base);
9920 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009921}
9922
9923#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009924static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009925{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009926 ushort val_low, val_high;
9927 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009929 AscSetChipLramAddr(iop_base, addr);
9930 val_low = AscGetChipLramData(iop_base);
9931 val_high = AscGetChipLramData(iop_base);
9932 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
9933 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009934}
9935#endif /* CC_VERY_LONG_SG_LIST */
9936
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009937static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009938{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009939 AscSetChipLramAddr(iop_base, addr);
9940 AscSetChipLramData(iop_base, word_val);
9941 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009942}
9943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009944static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009945{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009946 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009947
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009948 if (isodd_word(addr)) {
9949 addr--;
9950 word_data = AscReadLramWord(iop_base, addr);
9951 word_data &= 0x00FF;
9952 word_data |= (((ushort)byte_val << 8) & 0xFF00);
9953 } else {
9954 word_data = AscReadLramWord(iop_base, addr);
9955 word_data &= 0xFF00;
9956 word_data |= ((ushort)byte_val & 0x00FF);
9957 }
9958 AscWriteLramWord(iop_base, addr, word_data);
9959 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009960}
9961
9962/*
9963 * Copy 2 bytes to LRAM.
9964 *
9965 * The source data is assumed to be in little-endian order in memory
9966 * and is maintained in little-endian order when written to LRAM.
9967 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009968static void
9969AscMemWordCopyPtrToLram(PortAddr iop_base,
9970 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009971{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009972 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009973
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009974 AscSetChipLramAddr(iop_base, s_addr);
9975 for (i = 0; i < 2 * words; i += 2) {
9976 /*
9977 * On a little-endian system the second argument below
9978 * produces a little-endian ushort which is written to
9979 * LRAM in little-endian order. On a big-endian system
9980 * the second argument produces a big-endian ushort which
9981 * is "transparently" byte-swapped by outpw() and written
9982 * in little-endian order to LRAM.
9983 */
9984 outpw(iop_base + IOP_RAM_DATA,
9985 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
9986 }
9987 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009988}
9989
9990/*
9991 * Copy 4 bytes to LRAM.
9992 *
9993 * The source data is assumed to be in little-endian order in memory
9994 * and is maintained in little-endian order when writen to LRAM.
9995 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009996static void
9997AscMemDWordCopyPtrToLram(PortAddr iop_base,
9998 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009999{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010000 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010001
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010002 AscSetChipLramAddr(iop_base, s_addr);
10003 for (i = 0; i < 4 * dwords; i += 4) {
10004 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
10005 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
10006 }
10007 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010008}
10009
10010/*
10011 * Copy 2 bytes from LRAM.
10012 *
10013 * The source data is assumed to be in little-endian order in LRAM
10014 * and is maintained in little-endian order when written to memory.
10015 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010016static void
10017AscMemWordCopyPtrFromLram(PortAddr iop_base,
10018 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010019{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010020 int i;
10021 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010022
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010023 AscSetChipLramAddr(iop_base, s_addr);
10024 for (i = 0; i < 2 * words; i += 2) {
10025 word = inpw(iop_base + IOP_RAM_DATA);
10026 d_buffer[i] = word & 0xff;
10027 d_buffer[i + 1] = (word >> 8) & 0xff;
10028 }
10029 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010030}
10031
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010032static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010033{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010034 ASC_DCNT sum;
10035 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010036
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010037 sum = 0L;
10038 for (i = 0; i < words; i++, s_addr += 2) {
10039 sum += AscReadLramWord(iop_base, s_addr);
10040 }
10041 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010042}
10043
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010044static void
10045AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010046{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010047 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010048
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010049 AscSetChipLramAddr(iop_base, s_addr);
10050 for (i = 0; i < words; i++) {
10051 AscSetChipLramData(iop_base, set_wval);
10052 }
10053 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010054}
10055
Linus Torvalds1da177e2005-04-16 15:20:36 -070010056/*
10057 * --- Adv Library Functions
10058 */
10059
10060/* a_mcode.h */
10061
10062/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010063static unsigned char _adv_asc3550_buf[] = {
10064 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010065 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
10066 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
10067 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010068 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010069 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
10070 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
10071 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010072 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010073 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
10074 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
10075 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010076 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010077 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
10078 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
10079 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010080 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010081 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
10082 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
10083 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010084 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010085 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
10086 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
10087 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010088 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010089 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
10090 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
10091 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010092 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010093 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
10094 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
10095 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010096 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010097 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
10098 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
10099 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010100 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010101 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
10102 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
10103 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010104 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010105 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
10106 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
10107 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010108 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010109 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
10110 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10111 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010112 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010113 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
10114 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
10115 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010116 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010117 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
10118 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
10119 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010120 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010121 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
10122 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
10123 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010124 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010125 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
10126 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
10127 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010128 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010129 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
10130 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
10131 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010132 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010133 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
10134 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
10135 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010136 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010137 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
10138 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
10139 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010140 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010141 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
10142 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
10143 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010144 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010145 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
10146 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
10147 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010148 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010149 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
10150 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
10151 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010152 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010153 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
10154 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
10155 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010156 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010157 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
10158 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
10159 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010160 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010161 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
10162 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
10163 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010164 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010165 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
10166 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
10167 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010168 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010169 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
10170 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
10171 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010172 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010173 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
10174 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
10175 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010176 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010177 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
10178 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
10179 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010180 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010181 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
10182 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
10183 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010184 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010185 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
10186 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
10187 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010188 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010189 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
10190 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
10191 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010192 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010193 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
10194 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
10195 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010196 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010197 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
10198 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
10199 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010200 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010201 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
10202 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
10203 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010204 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010205 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
10206 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
10207 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010208 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010209 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
10210 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
10211 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010212 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010213 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
10214 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
10215 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010216 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010217 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
10218 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
10219 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010220 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010221 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
10222 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
10223 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010224 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010225 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
10226 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
10227 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010228 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010229 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
10230 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
10231 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010232 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010233 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
10234 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
10235 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010236 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010237 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
10238 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
10239 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010240 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010241 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
10242 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
10243 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010244 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010245 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
10246 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
10247 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010248 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010249 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
10250 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
10251 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010252 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010253 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
10254 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
10255 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010256 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010257 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
10258 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
10259 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010260 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010261 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
10262 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
10263 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010264 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010265 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
10266 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
10267 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010268 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010269 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
10270 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
10271 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010272 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010273 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
10274 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
10275 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010276 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010277 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
10278 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
10279 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010280 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010281 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
10282 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
10283 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010284 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010285 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
10286 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
10287 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010288 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010289 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
10290 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
10291 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010292 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010293 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
10294 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
10295 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010296 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010297 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
10298 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
10299 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010300 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010301 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
10302 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
10303 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010304 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010305 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
10306 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
10307 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010308 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010309 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
10310 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
10311 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010312 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010313 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
10314 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
10315 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010316 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010317 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
10318 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
10319 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010320 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010321 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
10322 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
10323 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010324 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010325 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
10326 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
10327 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010328 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010329 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
10330 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
10331 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010332 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010333 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
10334 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
10335 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010336 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010337 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
10338 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
10339 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010340 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010341 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
10342 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
10343 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010344 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010345 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
10346 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
10347 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010348 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010349 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
10350 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
10351 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010352 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010353 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
10354 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
10355 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010356 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010357 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
10358 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
10359 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010360 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010361 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
10362 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
10363 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010364 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010365 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
10366 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
10367 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010368 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010369 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
10370 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
10371 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010372 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010373 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
10374 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
10375 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010376 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010377 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
10378 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
10379 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010380 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010381 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
10382 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
10383 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010384 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010385 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
10386 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
10387 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010388 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010389 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
10390 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
10391 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010392 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010393 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
10394 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
10395 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010396 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010397 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
10398 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
10399 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010400 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010401 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
10402 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
10403 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010404 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010405 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
10406 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
10407 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010408 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010409 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
10410 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
10411 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010412 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010413 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
10414 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
10415 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010416 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010417 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
10418 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
10419 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010420 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010421 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
10422 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
10423 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010424 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010425 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
10426 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
10427 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010428 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010429 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
10430 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
10431 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010432 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010433 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
10434 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
10435 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010436 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010437 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
10438 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
10439 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010440 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010441 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
10442 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
10443 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010444 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010445 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
10446 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
10447 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010448 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010449 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
10450 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
10451 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010452 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010453 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
10454 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
10455 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010456 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010457 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
10458 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
10459 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010460 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010461 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
10462 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
10463 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010464 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010465 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
10466 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
10467 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010468 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010469 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
10470 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
10471 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010472 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010473 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
10474 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
10475 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010476 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010477 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
10478 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
10479 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010480 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010481 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
10482 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010483};
10484
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010485static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
10486static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010487
10488/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010489static unsigned char _adv_asc38C0800_buf[] = {
10490 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010491 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
10492 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
10493 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010494 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010495 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
10496 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
10497 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010498 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010499 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
10500 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
10501 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010502 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010503 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
10504 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
10505 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010506 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010507 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
10508 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
10509 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010510 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010511 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
10512 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
10513 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010514 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010515 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
10516 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
10517 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010518 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010519 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
10520 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
10521 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010522 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010523 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
10524 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
10525 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010526 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010527 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
10528 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
10529 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010530 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010531 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
10532 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
10533 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010534 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010535 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
10536 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10537 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010538 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010539 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
10540 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
10541 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010542 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010543 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
10544 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
10545 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010546 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010547 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
10548 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
10549 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010550 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010551 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
10552 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
10553 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010554 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010555 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
10556 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
10557 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010558 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010559 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
10560 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
10561 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010562 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010563 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
10564 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
10565 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010566 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010567 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
10568 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
10569 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010570 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010571 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
10572 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
10573 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010574 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010575 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
10576 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
10577 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010578 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010579 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
10580 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
10581 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010582 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010583 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
10584 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
10585 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010586 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010587 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
10588 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
10589 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010590 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010591 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
10592 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
10593 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010594 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010595 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
10596 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
10597 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010598 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010599 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
10600 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
10601 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010602 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010603 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
10604 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
10605 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010606 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010607 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
10608 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
10609 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010610 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010611 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
10612 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
10613 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010614 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010615 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
10616 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
10617 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010618 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010619 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
10620 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
10621 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010622 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010623 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
10624 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
10625 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010626 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010627 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
10628 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
10629 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010630 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010631 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
10632 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
10633 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010634 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010635 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
10636 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
10637 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010638 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010639 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
10640 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
10641 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010642 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010643 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
10644 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
10645 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010646 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010647 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
10648 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
10649 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010650 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010651 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
10652 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
10653 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010654 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010655 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
10656 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
10657 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010658 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010659 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
10660 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
10661 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010662 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010663 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
10664 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
10665 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010666 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010667 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
10668 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
10669 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010670 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010671 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
10672 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
10673 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010674 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010675 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
10676 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
10677 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010678 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010679 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
10680 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
10681 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010682 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010683 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
10684 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
10685 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010686 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010687 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
10688 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
10689 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010690 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010691 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
10692 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
10693 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010694 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010695 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
10696 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
10697 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010698 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010699 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
10700 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
10701 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010702 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010703 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
10704 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
10705 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010706 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010707 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
10708 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
10709 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010710 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010711 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
10712 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
10713 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010714 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010715 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
10716 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
10717 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010718 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010719 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
10720 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
10721 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010722 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010723 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
10724 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
10725 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010726 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010727 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
10728 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
10729 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010730 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010731 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
10732 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
10733 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010734 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010735 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
10736 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
10737 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010738 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010739 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
10740 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
10741 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010742 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010743 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
10744 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
10745 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010746 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010747 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
10748 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
10749 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010750 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010751 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
10752 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
10753 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010754 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010755 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
10756 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
10757 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010758 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010759 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
10760 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
10761 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010762 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010763 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
10764 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
10765 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010766 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010767 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
10768 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
10769 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010770 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010771 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
10772 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
10773 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010774 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010775 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
10776 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
10777 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010778 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010779 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
10780 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
10781 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010782 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010783 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
10784 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
10785 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010786 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010787 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
10788 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
10789 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010790 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010791 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
10792 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
10793 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010794 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010795 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
10796 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
10797 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010798 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010799 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
10800 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
10801 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010802 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010803 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
10804 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
10805 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010806 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010807 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
10808 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
10809 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010810 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010811 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
10812 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
10813 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010814 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010815 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
10816 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
10817 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010818 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010819 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
10820 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
10821 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010822 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010823 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
10824 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
10825 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010826 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010827 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
10828 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
10829 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010830 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010831 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
10832 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
10833 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010834 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010835 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
10836 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10837 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010838 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010839 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10840 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
10841 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010842 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010843 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
10844 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
10845 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010846 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010847 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
10848 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
10849 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010850 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010851 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
10852 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
10853 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010854 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010855 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
10856 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
10857 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010858 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010859 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
10860 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
10861 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010862 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010863 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
10864 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
10865 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010866 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010867 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
10868 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
10869 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010870 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010871 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
10872 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
10873 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010874 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010875 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
10876 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
10877 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010878 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010879 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
10880 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
10881 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010882 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010883 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
10884 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
10885 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010886 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010887 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
10888 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
10889 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010890 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010891 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
10892 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
10893 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010894 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010895 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
10896 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
10897 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010898 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010899 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
10900 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
10901 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010902 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010903 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
10904 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
10905 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010906 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010907 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
10908 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
10909 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010910 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010911 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
10912 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
10913 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010914 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010915 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
10916 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
10917 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010918 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010919 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
10920 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
10921 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010922 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010923 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
10924 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
10925 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010926 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010927 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
10928 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
10929 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010930 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010931 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
10932 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
10933 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010934 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010935};
10936
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010937static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
10938static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010939
10940/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010941static unsigned char _adv_asc38C1600_buf[] = {
10942 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010943 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
10944 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
10945 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010946 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010947 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
10948 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
10949 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010950 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010951 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
10952 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
10953 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010954 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010955 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
10956 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
10957 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010958 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010959 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
10960 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
10961 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010962 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010963 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
10964 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
10965 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010966 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010967 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
10968 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
10969 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010970 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010971 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
10972 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
10973 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010974 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010975 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
10976 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
10977 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010978 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010979 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
10980 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
10981 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010982 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010983 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
10984 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
10985 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010986 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010987 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
10988 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10989 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010990 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010991 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
10992 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
10993 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010994 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010995 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
10996 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
10997 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010998 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010999 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
11000 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
11001 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011002 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011003 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
11004 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
11005 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011006 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011007 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
11008 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
11009 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011010 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011011 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
11012 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
11013 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011014 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011015 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
11016 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
11017 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011018 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011019 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
11020 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
11021 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011022 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011023 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
11024 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
11025 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011026 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011027 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
11028 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
11029 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011030 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011031 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
11032 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
11033 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011034 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011035 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
11036 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
11037 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011038 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011039 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
11040 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
11041 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011042 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011043 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
11044 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
11045 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011046 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011047 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
11048 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
11049 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011050 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011051 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
11052 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
11053 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011054 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011055 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
11056 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
11057 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011058 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011059 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
11060 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
11061 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011062 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011063 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
11064 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
11065 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011066 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011067 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
11068 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
11069 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011070 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011071 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
11072 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
11073 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011074 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011075 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
11076 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
11077 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011078 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011079 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
11080 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
11081 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011082 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011083 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
11084 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
11085 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011086 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011087 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
11088 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
11089 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011090 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011091 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
11092 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
11093 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011094 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011095 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
11096 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
11097 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011098 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011099 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
11100 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
11101 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011102 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011103 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
11104 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
11105 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011106 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011107 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
11108 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
11109 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011110 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011111 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
11112 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
11113 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011114 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011115 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
11116 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
11117 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011118 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011119 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
11120 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
11121 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011122 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011123 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
11124 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
11125 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011126 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011127 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
11128 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
11129 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011130 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011131 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
11132 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
11133 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011134 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011135 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
11136 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
11137 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011138 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011139 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
11140 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
11141 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011142 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011143 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
11144 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
11145 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011146 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011147 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
11148 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
11149 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011150 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011151 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
11152 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
11153 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011154 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011155 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
11156 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
11157 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011158 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011159 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
11160 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
11161 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011162 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011163 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
11164 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
11165 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011166 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011167 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
11168 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
11169 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011170 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011171 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
11172 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
11173 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011174 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011175 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
11176 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
11177 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011178 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011179 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
11180 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
11181 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011182 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011183 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
11184 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
11185 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011186 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011187 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
11188 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
11189 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011190 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011191 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
11192 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
11193 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011194 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011195 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
11196 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
11197 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011198 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011199 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
11200 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
11201 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011202 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011203 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
11204 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
11205 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011206 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011207 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
11208 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
11209 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011210 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011211 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
11212 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
11213 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011214 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011215 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
11216 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
11217 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011218 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011219 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
11220 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
11221 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011222 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011223 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
11224 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
11225 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011226 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011227 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
11228 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
11229 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011230 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011231 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
11232 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
11233 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011234 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011235 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
11236 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
11237 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011238 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011239 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
11240 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
11241 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011242 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011243 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
11244 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
11245 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011246 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011247 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
11248 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
11249 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011250 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011251 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
11252 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
11253 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011254 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011255 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
11256 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
11257 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011258 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011259 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
11260 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
11261 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011262 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011263 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
11264 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
11265 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011266 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011267 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
11268 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
11269 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011270 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011271 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
11272 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
11273 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011274 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011275 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
11276 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
11277 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011278 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011279 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
11280 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
11281 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011282 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011283 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
11284 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
11285 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011286 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011287 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
11288 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
11289 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011290 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011291 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
11292 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
11293 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011294 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011295 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
11296 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
11297 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011298 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011299 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
11300 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
11301 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011302 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011303 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
11304 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
11305 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011306 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011307 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
11308 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
11309 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011310 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011311 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
11312 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
11313 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011314 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011315 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
11316 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
11317 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011318 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011319 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
11320 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
11321 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011322 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011323 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
11324 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
11325 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011326 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011327 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
11328 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
11329 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011330 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011331 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
11332 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
11333 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011334 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011335 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
11336 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
11337 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011338 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011339 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
11340 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
11341 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011342 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011343 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
11344 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
11345 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011346 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011347 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
11348 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
11349 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011350 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011351 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
11352 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
11353 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011354 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011355 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
11356 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
11357 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011358 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011359 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
11360 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
11361 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011362 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011363 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
11364 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
11365 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011366 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011367 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
11368 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
11369 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011370 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011371 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
11372 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
11373 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011374 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011375 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
11376 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
11377 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011378 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011379 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
11380 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
11381 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011382 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011383 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
11384 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
11385 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011386 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011387 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
11388 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
11389 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011390 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011391 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
11392 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
11393 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011394 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011395 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
11396 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
11397 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011398 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011399 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
11400 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
11401 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011402 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011403 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
11404 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
11405 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011406 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011407 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
11408 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
11409 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011410 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011411 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
11412 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
11413 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011414 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011415 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
11416 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
11417 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011418 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011419 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
11420 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
11421 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011422 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011423 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
11424 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
11425 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011426 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011427 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
11428 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
11429 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011430 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011431 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
11432 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
11433 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011434 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011435 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
11436 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
11437 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011438 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011439 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
11440 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
11441 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011442 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011443 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
11444 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
11445 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011446 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011447 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
11448 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
11449 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011450 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011451 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
11452 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
11453 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011454 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011455 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
11456 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
11457 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011458 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011459 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
11460 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
11461 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011462 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011463 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
11464 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
11465 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011466 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060011467 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
11468 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
11469 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070011470};
11471
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011472static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
11473static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011474
Linus Torvalds1da177e2005-04-16 15:20:36 -070011475/*
11476 * EEPROM Configuration.
11477 *
11478 * All drivers should use this structure to set the default EEPROM
11479 * configuration. The BIOS now uses this structure when it is built.
11480 * Additional structure information can be found in a_condor.h where
11481 * the structure is defined.
11482 *
11483 * The *_Field_IsChar structs are needed to correct for endianness.
11484 * These values are read from the board 16 bits at a time directly
11485 * into the structs. Because some fields are char, the values will be
11486 * in the wrong order. The *_Field_IsChar tells when to flip the
11487 * bytes. Data read and written to PCI memory is automatically swapped
11488 * on big-endian platforms so char fields read as words are actually being
11489 * unswapped on big-endian platforms.
11490 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011491static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011492 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
11493 0x0000, /* cfg_msw */
11494 0xFFFF, /* disc_enable */
11495 0xFFFF, /* wdtr_able */
11496 0xFFFF, /* sdtr_able */
11497 0xFFFF, /* start_motor */
11498 0xFFFF, /* tagqng_able */
11499 0xFFFF, /* bios_scan */
11500 0, /* scam_tolerant */
11501 7, /* adapter_scsi_id */
11502 0, /* bios_boot_delay */
11503 3, /* scsi_reset_delay */
11504 0, /* bios_id_lun */
11505 0, /* termination */
11506 0, /* reserved1 */
11507 0xFFE7, /* bios_ctrl */
11508 0xFFFF, /* ultra_able */
11509 0, /* reserved2 */
11510 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
11511 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11512 0, /* dvc_cntl */
11513 0, /* bug_fix */
11514 0, /* serial_number_word1 */
11515 0, /* serial_number_word2 */
11516 0, /* serial_number_word3 */
11517 0, /* check_sum */
11518 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11519 , /* oem_name[16] */
11520 0, /* dvc_err_code */
11521 0, /* adv_err_code */
11522 0, /* adv_err_addr */
11523 0, /* saved_dvc_err_code */
11524 0, /* saved_adv_err_code */
11525 0, /* saved_adv_err_addr */
11526 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011527};
11528
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011529static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011530 0, /* cfg_lsw */
11531 0, /* cfg_msw */
11532 0, /* -disc_enable */
11533 0, /* wdtr_able */
11534 0, /* sdtr_able */
11535 0, /* start_motor */
11536 0, /* tagqng_able */
11537 0, /* bios_scan */
11538 0, /* scam_tolerant */
11539 1, /* adapter_scsi_id */
11540 1, /* bios_boot_delay */
11541 1, /* scsi_reset_delay */
11542 1, /* bios_id_lun */
11543 1, /* termination */
11544 1, /* reserved1 */
11545 0, /* bios_ctrl */
11546 0, /* ultra_able */
11547 0, /* reserved2 */
11548 1, /* max_host_qng */
11549 1, /* max_dvc_qng */
11550 0, /* dvc_cntl */
11551 0, /* bug_fix */
11552 0, /* serial_number_word1 */
11553 0, /* serial_number_word2 */
11554 0, /* serial_number_word3 */
11555 0, /* check_sum */
11556 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11557 , /* oem_name[16] */
11558 0, /* dvc_err_code */
11559 0, /* adv_err_code */
11560 0, /* adv_err_addr */
11561 0, /* saved_dvc_err_code */
11562 0, /* saved_adv_err_code */
11563 0, /* saved_adv_err_addr */
11564 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011565};
11566
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011567static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011568 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11569 0x0000, /* 01 cfg_msw */
11570 0xFFFF, /* 02 disc_enable */
11571 0xFFFF, /* 03 wdtr_able */
11572 0x4444, /* 04 sdtr_speed1 */
11573 0xFFFF, /* 05 start_motor */
11574 0xFFFF, /* 06 tagqng_able */
11575 0xFFFF, /* 07 bios_scan */
11576 0, /* 08 scam_tolerant */
11577 7, /* 09 adapter_scsi_id */
11578 0, /* bios_boot_delay */
11579 3, /* 10 scsi_reset_delay */
11580 0, /* bios_id_lun */
11581 0, /* 11 termination_se */
11582 0, /* termination_lvd */
11583 0xFFE7, /* 12 bios_ctrl */
11584 0x4444, /* 13 sdtr_speed2 */
11585 0x4444, /* 14 sdtr_speed3 */
11586 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11587 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11588 0, /* 16 dvc_cntl */
11589 0x4444, /* 17 sdtr_speed4 */
11590 0, /* 18 serial_number_word1 */
11591 0, /* 19 serial_number_word2 */
11592 0, /* 20 serial_number_word3 */
11593 0, /* 21 check_sum */
11594 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11595 , /* 22-29 oem_name[16] */
11596 0, /* 30 dvc_err_code */
11597 0, /* 31 adv_err_code */
11598 0, /* 32 adv_err_addr */
11599 0, /* 33 saved_dvc_err_code */
11600 0, /* 34 saved_adv_err_code */
11601 0, /* 35 saved_adv_err_addr */
11602 0, /* 36 reserved */
11603 0, /* 37 reserved */
11604 0, /* 38 reserved */
11605 0, /* 39 reserved */
11606 0, /* 40 reserved */
11607 0, /* 41 reserved */
11608 0, /* 42 reserved */
11609 0, /* 43 reserved */
11610 0, /* 44 reserved */
11611 0, /* 45 reserved */
11612 0, /* 46 reserved */
11613 0, /* 47 reserved */
11614 0, /* 48 reserved */
11615 0, /* 49 reserved */
11616 0, /* 50 reserved */
11617 0, /* 51 reserved */
11618 0, /* 52 reserved */
11619 0, /* 53 reserved */
11620 0, /* 54 reserved */
11621 0, /* 55 reserved */
11622 0, /* 56 cisptr_lsw */
11623 0, /* 57 cisprt_msw */
11624 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11625 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
11626 0, /* 60 reserved */
11627 0, /* 61 reserved */
11628 0, /* 62 reserved */
11629 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011630};
11631
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011632static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011633 0, /* 00 cfg_lsw */
11634 0, /* 01 cfg_msw */
11635 0, /* 02 disc_enable */
11636 0, /* 03 wdtr_able */
11637 0, /* 04 sdtr_speed1 */
11638 0, /* 05 start_motor */
11639 0, /* 06 tagqng_able */
11640 0, /* 07 bios_scan */
11641 0, /* 08 scam_tolerant */
11642 1, /* 09 adapter_scsi_id */
11643 1, /* bios_boot_delay */
11644 1, /* 10 scsi_reset_delay */
11645 1, /* bios_id_lun */
11646 1, /* 11 termination_se */
11647 1, /* termination_lvd */
11648 0, /* 12 bios_ctrl */
11649 0, /* 13 sdtr_speed2 */
11650 0, /* 14 sdtr_speed3 */
11651 1, /* 15 max_host_qng */
11652 1, /* max_dvc_qng */
11653 0, /* 16 dvc_cntl */
11654 0, /* 17 sdtr_speed4 */
11655 0, /* 18 serial_number_word1 */
11656 0, /* 19 serial_number_word2 */
11657 0, /* 20 serial_number_word3 */
11658 0, /* 21 check_sum */
11659 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11660 , /* 22-29 oem_name[16] */
11661 0, /* 30 dvc_err_code */
11662 0, /* 31 adv_err_code */
11663 0, /* 32 adv_err_addr */
11664 0, /* 33 saved_dvc_err_code */
11665 0, /* 34 saved_adv_err_code */
11666 0, /* 35 saved_adv_err_addr */
11667 0, /* 36 reserved */
11668 0, /* 37 reserved */
11669 0, /* 38 reserved */
11670 0, /* 39 reserved */
11671 0, /* 40 reserved */
11672 0, /* 41 reserved */
11673 0, /* 42 reserved */
11674 0, /* 43 reserved */
11675 0, /* 44 reserved */
11676 0, /* 45 reserved */
11677 0, /* 46 reserved */
11678 0, /* 47 reserved */
11679 0, /* 48 reserved */
11680 0, /* 49 reserved */
11681 0, /* 50 reserved */
11682 0, /* 51 reserved */
11683 0, /* 52 reserved */
11684 0, /* 53 reserved */
11685 0, /* 54 reserved */
11686 0, /* 55 reserved */
11687 0, /* 56 cisptr_lsw */
11688 0, /* 57 cisprt_msw */
11689 0, /* 58 subsysvid */
11690 0, /* 59 subsysid */
11691 0, /* 60 reserved */
11692 0, /* 61 reserved */
11693 0, /* 62 reserved */
11694 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011695};
11696
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011697static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011698 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11699 0x0000, /* 01 cfg_msw */
11700 0xFFFF, /* 02 disc_enable */
11701 0xFFFF, /* 03 wdtr_able */
11702 0x5555, /* 04 sdtr_speed1 */
11703 0xFFFF, /* 05 start_motor */
11704 0xFFFF, /* 06 tagqng_able */
11705 0xFFFF, /* 07 bios_scan */
11706 0, /* 08 scam_tolerant */
11707 7, /* 09 adapter_scsi_id */
11708 0, /* bios_boot_delay */
11709 3, /* 10 scsi_reset_delay */
11710 0, /* bios_id_lun */
11711 0, /* 11 termination_se */
11712 0, /* termination_lvd */
11713 0xFFE7, /* 12 bios_ctrl */
11714 0x5555, /* 13 sdtr_speed2 */
11715 0x5555, /* 14 sdtr_speed3 */
11716 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11717 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11718 0, /* 16 dvc_cntl */
11719 0x5555, /* 17 sdtr_speed4 */
11720 0, /* 18 serial_number_word1 */
11721 0, /* 19 serial_number_word2 */
11722 0, /* 20 serial_number_word3 */
11723 0, /* 21 check_sum */
11724 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11725 , /* 22-29 oem_name[16] */
11726 0, /* 30 dvc_err_code */
11727 0, /* 31 adv_err_code */
11728 0, /* 32 adv_err_addr */
11729 0, /* 33 saved_dvc_err_code */
11730 0, /* 34 saved_adv_err_code */
11731 0, /* 35 saved_adv_err_addr */
11732 0, /* 36 reserved */
11733 0, /* 37 reserved */
11734 0, /* 38 reserved */
11735 0, /* 39 reserved */
11736 0, /* 40 reserved */
11737 0, /* 41 reserved */
11738 0, /* 42 reserved */
11739 0, /* 43 reserved */
11740 0, /* 44 reserved */
11741 0, /* 45 reserved */
11742 0, /* 46 reserved */
11743 0, /* 47 reserved */
11744 0, /* 48 reserved */
11745 0, /* 49 reserved */
11746 0, /* 50 reserved */
11747 0, /* 51 reserved */
11748 0, /* 52 reserved */
11749 0, /* 53 reserved */
11750 0, /* 54 reserved */
11751 0, /* 55 reserved */
11752 0, /* 56 cisptr_lsw */
11753 0, /* 57 cisprt_msw */
11754 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11755 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
11756 0, /* 60 reserved */
11757 0, /* 61 reserved */
11758 0, /* 62 reserved */
11759 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011760};
11761
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011762static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011763 0, /* 00 cfg_lsw */
11764 0, /* 01 cfg_msw */
11765 0, /* 02 disc_enable */
11766 0, /* 03 wdtr_able */
11767 0, /* 04 sdtr_speed1 */
11768 0, /* 05 start_motor */
11769 0, /* 06 tagqng_able */
11770 0, /* 07 bios_scan */
11771 0, /* 08 scam_tolerant */
11772 1, /* 09 adapter_scsi_id */
11773 1, /* bios_boot_delay */
11774 1, /* 10 scsi_reset_delay */
11775 1, /* bios_id_lun */
11776 1, /* 11 termination_se */
11777 1, /* termination_lvd */
11778 0, /* 12 bios_ctrl */
11779 0, /* 13 sdtr_speed2 */
11780 0, /* 14 sdtr_speed3 */
11781 1, /* 15 max_host_qng */
11782 1, /* max_dvc_qng */
11783 0, /* 16 dvc_cntl */
11784 0, /* 17 sdtr_speed4 */
11785 0, /* 18 serial_number_word1 */
11786 0, /* 19 serial_number_word2 */
11787 0, /* 20 serial_number_word3 */
11788 0, /* 21 check_sum */
11789 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11790 , /* 22-29 oem_name[16] */
11791 0, /* 30 dvc_err_code */
11792 0, /* 31 adv_err_code */
11793 0, /* 32 adv_err_addr */
11794 0, /* 33 saved_dvc_err_code */
11795 0, /* 34 saved_adv_err_code */
11796 0, /* 35 saved_adv_err_addr */
11797 0, /* 36 reserved */
11798 0, /* 37 reserved */
11799 0, /* 38 reserved */
11800 0, /* 39 reserved */
11801 0, /* 40 reserved */
11802 0, /* 41 reserved */
11803 0, /* 42 reserved */
11804 0, /* 43 reserved */
11805 0, /* 44 reserved */
11806 0, /* 45 reserved */
11807 0, /* 46 reserved */
11808 0, /* 47 reserved */
11809 0, /* 48 reserved */
11810 0, /* 49 reserved */
11811 0, /* 50 reserved */
11812 0, /* 51 reserved */
11813 0, /* 52 reserved */
11814 0, /* 53 reserved */
11815 0, /* 54 reserved */
11816 0, /* 55 reserved */
11817 0, /* 56 cisptr_lsw */
11818 0, /* 57 cisprt_msw */
11819 0, /* 58 subsysvid */
11820 0, /* 59 subsysid */
11821 0, /* 60 reserved */
11822 0, /* 61 reserved */
11823 0, /* 62 reserved */
11824 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011825};
11826
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011827#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -070011828/*
11829 * Initialize the ADV_DVC_VAR structure.
11830 *
11831 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11832 *
11833 * For a non-fatal error return a warning code. If there are no warnings
11834 * then 0 is returned.
11835 */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040011836static int __devinit
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011837AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011838{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011839 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011840 unsigned short warn_code = 0;
11841 AdvPortAddr iop_base = asc_dvc->iop_base;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011842 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011843 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011844
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011845 asc_dvc->err_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011846
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011847 /*
11848 * Save the state of the PCI Configuration Command Register
11849 * "Parity Error Response Control" Bit. If the bit is clear (0),
11850 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
11851 * DMA parity errors.
11852 */
11853 asc_dvc->cfg->control_flag = 0;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011854 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
11855 if ((cmd & PCI_COMMAND_PARITY) == 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011856 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011857
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011858 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
11859 ADV_LIB_VERSION_MINOR;
11860 asc_dvc->cfg->chip_version =
11861 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011862
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011863 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
11864 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
11865 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011866
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011867 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
11868 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
11869 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011870
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011871 /*
11872 * Reset the chip to start and allow register writes.
11873 */
11874 if (AdvFindSignature(iop_base) == 0) {
11875 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11876 return ADV_ERROR;
11877 } else {
11878 /*
11879 * The caller must set 'chip_type' to a valid setting.
11880 */
11881 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
11882 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
11883 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
11884 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
11885 return ADV_ERROR;
11886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011887
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011888 /*
11889 * Reset Chip.
11890 */
11891 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11892 ADV_CTRL_REG_CMD_RESET);
11893 DvcSleepMilliSecond(100);
11894 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11895 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011897 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011898 status = AdvInitFrom38C1600EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011899 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011900 status = AdvInitFrom38C0800EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011901 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011902 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011903 }
11904 warn_code |= status;
11905 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011906
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011907 if (warn_code != 0) {
11908 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
11909 boardp->id, warn_code);
11910 }
11911
11912 if (asc_dvc->err_code) {
11913 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
11914 boardp->id, asc_dvc->err_code);
11915 }
11916
11917 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011918}
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011919#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070011920
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011921static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
11922{
11923 ADV_CARR_T *carrp;
11924 ADV_SDCNT buf_size;
11925 ADV_PADDR carr_paddr;
11926
11927 BUG_ON(!asc_dvc->carrier_buf);
11928
11929 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
11930 asc_dvc->carr_freelist = NULL;
11931 if (carrp == asc_dvc->carrier_buf) {
11932 buf_size = ADV_CARRIER_BUFSIZE;
11933 } else {
11934 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
11935 }
11936
11937 do {
11938 /* Get physical address of the carrier 'carrp'. */
11939 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
11940 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
11941 (uchar *)carrp,
11942 (ADV_SDCNT *)&contig_len,
11943 ADV_IS_CARRIER_FLAG));
11944
11945 buf_size -= sizeof(ADV_CARR_T);
11946
11947 /*
11948 * If the current carrier is not physically contiguous, then
11949 * maybe there was a page crossing. Try the next carrier
11950 * aligned start address.
11951 */
11952 if (contig_len < sizeof(ADV_CARR_T)) {
11953 carrp++;
11954 continue;
11955 }
11956
11957 carrp->carr_pa = carr_paddr;
11958 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
11959
11960 /*
11961 * Insert the carrier at the beginning of the freelist.
11962 */
11963 carrp->next_vpa =
11964 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
11965 asc_dvc->carr_freelist = carrp;
11966
11967 carrp++;
11968 } while (buf_size > 0);
11969}
11970
Linus Torvalds1da177e2005-04-16 15:20:36 -070011971/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011972 * Load the Microcode
11973 *
11974 * Write the microcode image to RISC memory starting at address 0.
11975 *
11976 * The microcode is stored compressed in the following format:
11977 *
11978 * 254 word (508 byte) table indexed by byte code followed
11979 * by the following byte codes:
11980 *
11981 * 1-Byte Code:
11982 * 00: Emit word 0 in table.
11983 * 01: Emit word 1 in table.
11984 * .
11985 * FD: Emit word 253 in table.
11986 *
11987 * Multi-Byte Code:
11988 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
11989 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
11990 *
11991 * Returns 0 or an error if the checksum doesn't match
11992 */
11993static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
11994 int memsize, int chksum)
11995{
11996 int i, j, end, len = 0;
11997 ADV_DCNT sum;
11998
11999 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
12000
12001 for (i = 253 * 2; i < size; i++) {
12002 if (buf[i] == 0xff) {
12003 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
12004 for (j = 0; j < buf[i + 1]; j++) {
12005 AdvWriteWordAutoIncLram(iop_base, word);
12006 len += 2;
12007 }
12008 i += 3;
12009 } else if (buf[i] == 0xfe) {
12010 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
12011 AdvWriteWordAutoIncLram(iop_base, word);
12012 i += 2;
12013 len += 2;
12014 } else {
12015 unsigned char off = buf[i] * 2;
12016 unsigned short word = (buf[off + 1] << 8) | buf[off];
12017 AdvWriteWordAutoIncLram(iop_base, word);
12018 len += 2;
12019 }
12020 }
12021
12022 end = len;
12023
12024 while (len < memsize) {
12025 AdvWriteWordAutoIncLram(iop_base, 0);
12026 len += 2;
12027 }
12028
12029 /* Verify the microcode checksum. */
12030 sum = 0;
12031 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
12032
12033 for (len = 0; len < end; len += 2) {
12034 sum += AdvReadWordAutoIncLram(iop_base);
12035 }
12036
12037 if (sum != chksum)
12038 return ASC_IERR_MCODE_CHKSUM;
12039
12040 return 0;
12041}
12042
12043/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070012044 * Initialize the ASC-3550.
12045 *
12046 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12047 *
12048 * For a non-fatal error return a warning code. If there are no warnings
12049 * then 0 is returned.
12050 *
12051 * Needed after initialization for error recovery.
12052 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012053static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012054{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012055 AdvPortAddr iop_base;
12056 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012057 int begin_addr;
12058 int end_addr;
12059 ushort code_sum;
12060 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012061 int i;
12062 ushort scsi_cfg1;
12063 uchar tid;
12064 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12065 ushort wdtr_able = 0, sdtr_able, tagqng_able;
12066 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012067
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012068 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012069 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012070 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012071
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012072 /*
12073 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
12074 */
12075 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012076 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012077 return ADV_ERROR;
12078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012080 warn_code = 0;
12081 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012082
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012083 /*
12084 * Save the RISC memory BIOS region before writing the microcode.
12085 * The BIOS may already be loaded and using its RISC LRAM region
12086 * so its region must be saved and restored.
12087 *
12088 * Note: This code makes the assumption, which is currently true,
12089 * that a chip reset does not clear RISC LRAM.
12090 */
12091 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12092 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12093 bios_mem[i]);
12094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012095
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012096 /*
12097 * Save current per TID negotiated values.
12098 */
12099 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
12100 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012102 bios_version =
12103 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
12104 major = (bios_version >> 12) & 0xF;
12105 minor = (bios_version >> 8) & 0xF;
12106 if (major < 3 || (major == 3 && minor == 1)) {
12107 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
12108 AdvReadWordLram(iop_base, 0x120, wdtr_able);
12109 } else {
12110 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12111 }
12112 }
12113 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12114 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12115 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12116 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12117 max_cmd[tid]);
12118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012119
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012120 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
12121 _adv_asc3550_size, ADV_3550_MEMSIZE,
12122 _adv_asc3550_chksum);
12123 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012124 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012125
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012126 /*
12127 * Restore the RISC memory BIOS region.
12128 */
12129 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12130 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12131 bios_mem[i]);
12132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012133
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012134 /*
12135 * Calculate and write the microcode code checksum to the microcode
12136 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12137 */
12138 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12139 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12140 code_sum = 0;
12141 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12142 for (word = begin_addr; word < end_addr; word += 2) {
12143 code_sum += AdvReadWordAutoIncLram(iop_base);
12144 }
12145 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012146
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012147 /*
12148 * Read and save microcode version and date.
12149 */
12150 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12151 asc_dvc->cfg->mcode_date);
12152 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12153 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012154
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012155 /*
12156 * Set the chip type to indicate the ASC3550.
12157 */
12158 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012159
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012160 /*
12161 * If the PCI Configuration Command Register "Parity Error Response
12162 * Control" Bit was clear (0), then set the microcode variable
12163 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12164 * to ignore DMA parity errors.
12165 */
12166 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12167 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12168 word |= CONTROL_FLAG_IGNORE_PERR;
12169 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012171
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012172 /*
12173 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
12174 * threshold of 128 bytes. This register is only accessible to the host.
12175 */
12176 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12177 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012178
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012179 /*
12180 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012181 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012182 * device reports it is capable of in Inquiry byte 7.
12183 *
12184 * If SCSI Bus Resets have been disabled, then directly set
12185 * SDTR and WDTR from the EEPROM configuration. This will allow
12186 * the BIOS and warm boot to work without a SCSI bus hang on
12187 * the Inquiry caused by host and target mismatched DTR values.
12188 * Without the SCSI Bus Reset, before an Inquiry a device can't
12189 * be assumed to be in Asynchronous, Narrow mode.
12190 */
12191 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12192 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12193 asc_dvc->wdtr_able);
12194 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12195 asc_dvc->sdtr_able);
12196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012197
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012198 /*
12199 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
12200 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
12201 * bitmask. These values determine the maximum SDTR speed negotiated
12202 * with a device.
12203 *
12204 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12205 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12206 * without determining here whether the device supports SDTR.
12207 *
12208 * 4-bit speed SDTR speed name
12209 * =========== ===============
12210 * 0000b (0x0) SDTR disabled
12211 * 0001b (0x1) 5 Mhz
12212 * 0010b (0x2) 10 Mhz
12213 * 0011b (0x3) 20 Mhz (Ultra)
12214 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
12215 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
12216 * 0110b (0x6) Undefined
12217 * .
12218 * 1111b (0xF) Undefined
12219 */
12220 word = 0;
12221 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12222 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
12223 /* Set Ultra speed for TID 'tid'. */
12224 word |= (0x3 << (4 * (tid % 4)));
12225 } else {
12226 /* Set Fast speed for TID 'tid'. */
12227 word |= (0x2 << (4 * (tid % 4)));
12228 }
12229 if (tid == 3) { /* Check if done with sdtr_speed1. */
12230 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
12231 word = 0;
12232 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
12233 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
12234 word = 0;
12235 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
12236 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
12237 word = 0;
12238 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
12239 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
12240 /* End of loop. */
12241 }
12242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012243
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012244 /*
12245 * Set microcode operating variable for the disconnect per TID bitmask.
12246 */
12247 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12248 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012249
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012250 /*
12251 * Set SCSI_CFG0 Microcode Default Value.
12252 *
12253 * The microcode will set the SCSI_CFG0 register using this value
12254 * after it is started below.
12255 */
12256 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12257 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12258 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012259
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012260 /*
12261 * Determine SCSI_CFG1 Microcode Default Value.
12262 *
12263 * The microcode will set the SCSI_CFG1 register using this value
12264 * after it is started below.
12265 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012266
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012267 /* Read current SCSI_CFG1 Register value. */
12268 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012269
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012270 /*
12271 * If all three connectors are in use, return an error.
12272 */
12273 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
12274 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
12275 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
12276 return ADV_ERROR;
12277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012278
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012279 /*
12280 * If the internal narrow cable is reversed all of the SCSI_CTRL
12281 * register signals will be set. Check for and return an error if
12282 * this condition is found.
12283 */
12284 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12285 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12286 return ADV_ERROR;
12287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012288
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012289 /*
12290 * If this is a differential board and a single-ended device
12291 * is attached to one of the connectors, return an error.
12292 */
12293 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
12294 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
12295 return ADV_ERROR;
12296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012298 /*
12299 * If automatic termination control is enabled, then set the
12300 * termination value based on a table listed in a_condor.h.
12301 *
12302 * If manual termination was specified with an EEPROM setting
12303 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
12304 * is ready to be 'ored' into SCSI_CFG1.
12305 */
12306 if (asc_dvc->cfg->termination == 0) {
12307 /*
12308 * The software always controls termination by setting TERM_CTL_SEL.
12309 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
12310 */
12311 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012312
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012313 switch (scsi_cfg1 & CABLE_DETECT) {
12314 /* TERM_CTL_H: on, TERM_CTL_L: on */
12315 case 0x3:
12316 case 0x7:
12317 case 0xB:
12318 case 0xD:
12319 case 0xE:
12320 case 0xF:
12321 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
12322 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012323
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012324 /* TERM_CTL_H: on, TERM_CTL_L: off */
12325 case 0x1:
12326 case 0x5:
12327 case 0x9:
12328 case 0xA:
12329 case 0xC:
12330 asc_dvc->cfg->termination |= TERM_CTL_H;
12331 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012332
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012333 /* TERM_CTL_H: off, TERM_CTL_L: off */
12334 case 0x2:
12335 case 0x6:
12336 break;
12337 }
12338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012339
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012340 /*
12341 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
12342 */
12343 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012344
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012345 /*
12346 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
12347 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
12348 * referenced, because the hardware internally inverts
12349 * the Termination High and Low bits if TERM_POL is set.
12350 */
12351 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012352
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012353 /*
12354 * Set SCSI_CFG1 Microcode Default Value
12355 *
12356 * Set filter value and possibly modified termination control
12357 * bits in the Microcode SCSI_CFG1 Register Value.
12358 *
12359 * The microcode will set the SCSI_CFG1 register using this value
12360 * after it is started below.
12361 */
12362 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
12363 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012364
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012365 /*
12366 * Set MEM_CFG Microcode Default Value
12367 *
12368 * The microcode will set the MEM_CFG register using this value
12369 * after it is started below.
12370 *
12371 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12372 * are defined.
12373 *
12374 * ASC-3550 has 8KB internal memory.
12375 */
12376 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12377 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012378
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012379 /*
12380 * Set SEL_MASK Microcode Default Value
12381 *
12382 * The microcode will set the SEL_MASK register using this value
12383 * after it is started below.
12384 */
12385 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12386 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012387
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012388 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012389
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012390 /*
12391 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12392 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012393
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012394 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12395 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12396 return ADV_ERROR;
12397 }
12398 asc_dvc->carr_freelist = (ADV_CARR_T *)
12399 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012400
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012401 /*
12402 * The first command issued will be placed in the stopper carrier.
12403 */
12404 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012405
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012406 /*
12407 * Set RISC ICQ physical address start value.
12408 */
12409 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012410
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012411 /*
12412 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12413 */
12414 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12415 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12416 return ADV_ERROR;
12417 }
12418 asc_dvc->carr_freelist = (ADV_CARR_T *)
12419 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012420
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012421 /*
12422 * The first command completed by the RISC will be placed in
12423 * the stopper.
12424 *
12425 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12426 * completed the RISC will set the ASC_RQ_STOPPER bit.
12427 */
12428 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012429
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012430 /*
12431 * Set RISC IRQ physical address start value.
12432 */
12433 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12434 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012435
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012436 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12437 (ADV_INTR_ENABLE_HOST_INTR |
12438 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012439
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012440 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12441 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012442
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012443 /* finally, finally, gentlemen, start your engine */
12444 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012445
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012446 /*
12447 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12448 * Resets should be performed. The RISC has to be running
12449 * to issue a SCSI Bus Reset.
12450 */
12451 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12452 /*
12453 * If the BIOS Signature is present in memory, restore the
12454 * BIOS Handshake Configuration Table and do not perform
12455 * a SCSI Bus Reset.
12456 */
12457 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12458 0x55AA) {
12459 /*
12460 * Restore per TID negotiated values.
12461 */
12462 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12463 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12464 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12465 tagqng_able);
12466 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12467 AdvWriteByteLram(iop_base,
12468 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12469 max_cmd[tid]);
12470 }
12471 } else {
12472 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12473 warn_code = ASC_WARN_BUSRESET_ERROR;
12474 }
12475 }
12476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012477
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012478 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012479}
12480
12481/*
12482 * Initialize the ASC-38C0800.
12483 *
12484 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12485 *
12486 * For a non-fatal error return a warning code. If there are no warnings
12487 * then 0 is returned.
12488 *
12489 * Needed after initialization for error recovery.
12490 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012491static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012492{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012493 AdvPortAddr iop_base;
12494 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012495 int begin_addr;
12496 int end_addr;
12497 ushort code_sum;
12498 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012499 int i;
12500 ushort scsi_cfg1;
12501 uchar byte;
12502 uchar tid;
12503 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12504 ushort wdtr_able, sdtr_able, tagqng_able;
12505 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012506
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012507 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012508 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012509 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012510
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012511 /*
12512 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
12513 */
12514 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
12515 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12516 return ADV_ERROR;
12517 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012518
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012519 warn_code = 0;
12520 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012521
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012522 /*
12523 * Save the RISC memory BIOS region before writing the microcode.
12524 * The BIOS may already be loaded and using its RISC LRAM region
12525 * so its region must be saved and restored.
12526 *
12527 * Note: This code makes the assumption, which is currently true,
12528 * that a chip reset does not clear RISC LRAM.
12529 */
12530 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12531 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12532 bios_mem[i]);
12533 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012534
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012535 /*
12536 * Save current per TID negotiated values.
12537 */
12538 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12539 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12540 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12541 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12542 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12543 max_cmd[tid]);
12544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012545
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012546 /*
12547 * RAM BIST (RAM Built-In Self Test)
12548 *
12549 * Address : I/O base + offset 0x38h register (byte).
12550 * Function: Bit 7-6(RW) : RAM mode
12551 * Normal Mode : 0x00
12552 * Pre-test Mode : 0x40
12553 * RAM Test Mode : 0x80
12554 * Bit 5 : unused
12555 * Bit 4(RO) : Done bit
12556 * Bit 3-0(RO) : Status
12557 * Host Error : 0x08
12558 * Int_RAM Error : 0x04
12559 * RISC Error : 0x02
12560 * SCSI Error : 0x01
12561 * No Error : 0x00
12562 *
12563 * Note: RAM BIST code should be put right here, before loading the
12564 * microcode and after saving the RISC memory BIOS region.
12565 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012566
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012567 /*
12568 * LRAM Pre-test
12569 *
12570 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12571 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12572 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12573 * to NORMAL_MODE, return an error too.
12574 */
12575 for (i = 0; i < 2; i++) {
12576 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
12577 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12578 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12579 if ((byte & RAM_TEST_DONE) == 0
12580 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012581 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012582 return ADV_ERROR;
12583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012584
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012585 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
12586 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
12587 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12588 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012589 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012590 return ADV_ERROR;
12591 }
12592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012593
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012594 /*
12595 * LRAM Test - It takes about 1.5 ms to run through the test.
12596 *
12597 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12598 * If Done bit not set or Status not 0, save register byte, set the
12599 * err_code, and return an error.
12600 */
12601 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
12602 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012603
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012604 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12605 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12606 /* Get here if Done bit not set or Status not 0. */
12607 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012608 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012609 return ADV_ERROR;
12610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012611
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012612 /* We need to reset back to normal mode after LRAM test passes. */
12613 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012614
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012615 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
12616 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
12617 _adv_asc38C0800_chksum);
12618 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012619 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012620
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012621 /*
12622 * Restore the RISC memory BIOS region.
12623 */
12624 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12625 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12626 bios_mem[i]);
12627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012628
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012629 /*
12630 * Calculate and write the microcode code checksum to the microcode
12631 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12632 */
12633 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12634 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12635 code_sum = 0;
12636 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12637 for (word = begin_addr; word < end_addr; word += 2) {
12638 code_sum += AdvReadWordAutoIncLram(iop_base);
12639 }
12640 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012641
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012642 /*
12643 * Read microcode version and date.
12644 */
12645 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12646 asc_dvc->cfg->mcode_date);
12647 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12648 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012649
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012650 /*
12651 * Set the chip type to indicate the ASC38C0800.
12652 */
12653 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012654
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012655 /*
12656 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12657 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12658 * cable detection and then we are able to read C_DET[3:0].
12659 *
12660 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12661 * Microcode Default Value' section below.
12662 */
12663 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12664 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12665 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012666
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012667 /*
12668 * If the PCI Configuration Command Register "Parity Error Response
12669 * Control" Bit was clear (0), then set the microcode variable
12670 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12671 * to ignore DMA parity errors.
12672 */
12673 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12674 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12675 word |= CONTROL_FLAG_IGNORE_PERR;
12676 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012678
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012679 /*
12680 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
12681 * bits for the default FIFO threshold.
12682 *
12683 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
12684 *
12685 * For DMA Errata #4 set the BC_THRESH_ENB bit.
12686 */
12687 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12688 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
12689 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012690
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012691 /*
12692 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012693 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012694 * device reports it is capable of in Inquiry byte 7.
12695 *
12696 * If SCSI Bus Resets have been disabled, then directly set
12697 * SDTR and WDTR from the EEPROM configuration. This will allow
12698 * the BIOS and warm boot to work without a SCSI bus hang on
12699 * the Inquiry caused by host and target mismatched DTR values.
12700 * Without the SCSI Bus Reset, before an Inquiry a device can't
12701 * be assumed to be in Asynchronous, Narrow mode.
12702 */
12703 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12704 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12705 asc_dvc->wdtr_able);
12706 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12707 asc_dvc->sdtr_able);
12708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012709
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012710 /*
12711 * Set microcode operating variables for DISC and SDTR_SPEED1,
12712 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12713 * configuration values.
12714 *
12715 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12716 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12717 * without determining here whether the device supports SDTR.
12718 */
12719 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12720 asc_dvc->cfg->disc_enable);
12721 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12722 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12723 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12724 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012725
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012726 /*
12727 * Set SCSI_CFG0 Microcode Default Value.
12728 *
12729 * The microcode will set the SCSI_CFG0 register using this value
12730 * after it is started below.
12731 */
12732 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12733 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12734 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012735
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012736 /*
12737 * Determine SCSI_CFG1 Microcode Default Value.
12738 *
12739 * The microcode will set the SCSI_CFG1 register using this value
12740 * after it is started below.
12741 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012742
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012743 /* Read current SCSI_CFG1 Register value. */
12744 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012745
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012746 /*
12747 * If the internal narrow cable is reversed all of the SCSI_CTRL
12748 * register signals will be set. Check for and return an error if
12749 * this condition is found.
12750 */
12751 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12752 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12753 return ADV_ERROR;
12754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012755
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012756 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012757 * All kind of combinations of devices attached to one of four
12758 * connectors are acceptable except HVD device attached. For example,
12759 * LVD device can be attached to SE connector while SE device attached
12760 * to LVD connector. If LVD device attached to SE connector, it only
12761 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012762 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012763 * If an HVD device is attached to one of LVD connectors, return an
12764 * error. However, there is no way to detect HVD device attached to
12765 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012766 */
12767 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012768 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012769 return ADV_ERROR;
12770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012772 /*
12773 * If either SE or LVD automatic termination control is enabled, then
12774 * set the termination value based on a table listed in a_condor.h.
12775 *
12776 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012777 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
12778 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012779 */
12780 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
12781 /* SE automatic termination control is enabled. */
12782 switch (scsi_cfg1 & C_DET_SE) {
12783 /* TERM_SE_HI: on, TERM_SE_LO: on */
12784 case 0x1:
12785 case 0x2:
12786 case 0x3:
12787 asc_dvc->cfg->termination |= TERM_SE;
12788 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012789
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012790 /* TERM_SE_HI: on, TERM_SE_LO: off */
12791 case 0x0:
12792 asc_dvc->cfg->termination |= TERM_SE_HI;
12793 break;
12794 }
12795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012796
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012797 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
12798 /* LVD automatic termination control is enabled. */
12799 switch (scsi_cfg1 & C_DET_LVD) {
12800 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
12801 case 0x4:
12802 case 0x8:
12803 case 0xC:
12804 asc_dvc->cfg->termination |= TERM_LVD;
12805 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012806
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012807 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
12808 case 0x0:
12809 break;
12810 }
12811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012812
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012813 /*
12814 * Clear any set TERM_SE and TERM_LVD bits.
12815 */
12816 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012817
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012818 /*
12819 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
12820 */
12821 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012822
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012823 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012824 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
12825 * bits and set possibly modified termination control bits in the
12826 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012827 */
12828 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012829
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012830 /*
12831 * Set SCSI_CFG1 Microcode Default Value
12832 *
12833 * Set possibly modified termination control and reset DIS_TERM_DRV
12834 * bits in the Microcode SCSI_CFG1 Register Value.
12835 *
12836 * The microcode will set the SCSI_CFG1 register using this value
12837 * after it is started below.
12838 */
12839 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012840
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012841 /*
12842 * Set MEM_CFG Microcode Default Value
12843 *
12844 * The microcode will set the MEM_CFG register using this value
12845 * after it is started below.
12846 *
12847 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12848 * are defined.
12849 *
12850 * ASC-38C0800 has 16KB internal memory.
12851 */
12852 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12853 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012854
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012855 /*
12856 * Set SEL_MASK Microcode Default Value
12857 *
12858 * The microcode will set the SEL_MASK register using this value
12859 * after it is started below.
12860 */
12861 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12862 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012863
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012864 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012865
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012866 /*
12867 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12868 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012869
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012870 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12871 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12872 return ADV_ERROR;
12873 }
12874 asc_dvc->carr_freelist = (ADV_CARR_T *)
12875 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012876
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012877 /*
12878 * The first command issued will be placed in the stopper carrier.
12879 */
12880 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012881
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012882 /*
12883 * Set RISC ICQ physical address start value.
12884 * carr_pa is LE, must be native before write
12885 */
12886 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012887
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012888 /*
12889 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12890 */
12891 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12892 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12893 return ADV_ERROR;
12894 }
12895 asc_dvc->carr_freelist = (ADV_CARR_T *)
12896 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012897
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012898 /*
12899 * The first command completed by the RISC will be placed in
12900 * the stopper.
12901 *
12902 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12903 * completed the RISC will set the ASC_RQ_STOPPER bit.
12904 */
12905 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012906
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012907 /*
12908 * Set RISC IRQ physical address start value.
12909 *
12910 * carr_pa is LE, must be native before write *
12911 */
12912 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12913 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012914
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012915 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12916 (ADV_INTR_ENABLE_HOST_INTR |
12917 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012918
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012919 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12920 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012921
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012922 /* finally, finally, gentlemen, start your engine */
12923 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012924
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012925 /*
12926 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12927 * Resets should be performed. The RISC has to be running
12928 * to issue a SCSI Bus Reset.
12929 */
12930 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12931 /*
12932 * If the BIOS Signature is present in memory, restore the
12933 * BIOS Handshake Configuration Table and do not perform
12934 * a SCSI Bus Reset.
12935 */
12936 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12937 0x55AA) {
12938 /*
12939 * Restore per TID negotiated values.
12940 */
12941 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12942 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12943 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12944 tagqng_able);
12945 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12946 AdvWriteByteLram(iop_base,
12947 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12948 max_cmd[tid]);
12949 }
12950 } else {
12951 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12952 warn_code = ASC_WARN_BUSRESET_ERROR;
12953 }
12954 }
12955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012956
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012957 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012958}
12959
12960/*
12961 * Initialize the ASC-38C1600.
12962 *
12963 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
12964 *
12965 * For a non-fatal error return a warning code. If there are no warnings
12966 * then 0 is returned.
12967 *
12968 * Needed after initialization for error recovery.
12969 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012970static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012971{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012972 AdvPortAddr iop_base;
12973 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012974 int begin_addr;
12975 int end_addr;
12976 ushort code_sum;
12977 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012978 int i;
12979 ushort scsi_cfg1;
12980 uchar byte;
12981 uchar tid;
12982 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12983 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
12984 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012985
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012986 /* If there is already an error, don't continue. */
12987 if (asc_dvc->err_code != 0) {
12988 return ADV_ERROR;
12989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012991 /*
12992 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
12993 */
12994 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
12995 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12996 return ADV_ERROR;
12997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012998
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012999 warn_code = 0;
13000 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013001
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013002 /*
13003 * Save the RISC memory BIOS region before writing the microcode.
13004 * The BIOS may already be loaded and using its RISC LRAM region
13005 * so its region must be saved and restored.
13006 *
13007 * Note: This code makes the assumption, which is currently true,
13008 * that a chip reset does not clear RISC LRAM.
13009 */
13010 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
13011 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
13012 bios_mem[i]);
13013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013014
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013015 /*
13016 * Save current per TID negotiated values.
13017 */
13018 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
13019 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
13020 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
13021 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
13022 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13023 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
13024 max_cmd[tid]);
13025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013026
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013027 /*
13028 * RAM BIST (Built-In Self Test)
13029 *
13030 * Address : I/O base + offset 0x38h register (byte).
13031 * Function: Bit 7-6(RW) : RAM mode
13032 * Normal Mode : 0x00
13033 * Pre-test Mode : 0x40
13034 * RAM Test Mode : 0x80
13035 * Bit 5 : unused
13036 * Bit 4(RO) : Done bit
13037 * Bit 3-0(RO) : Status
13038 * Host Error : 0x08
13039 * Int_RAM Error : 0x04
13040 * RISC Error : 0x02
13041 * SCSI Error : 0x01
13042 * No Error : 0x00
13043 *
13044 * Note: RAM BIST code should be put right here, before loading the
13045 * microcode and after saving the RISC memory BIOS region.
13046 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013047
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013048 /*
13049 * LRAM Pre-test
13050 *
13051 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
13052 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
13053 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
13054 * to NORMAL_MODE, return an error too.
13055 */
13056 for (i = 0; i < 2; i++) {
13057 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
13058 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
13059 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
13060 if ((byte & RAM_TEST_DONE) == 0
13061 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060013062 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013063 return ADV_ERROR;
13064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013065
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013066 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
13067 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
13068 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
13069 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060013070 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013071 return ADV_ERROR;
13072 }
13073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013074
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013075 /*
13076 * LRAM Test - It takes about 1.5 ms to run through the test.
13077 *
13078 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
13079 * If Done bit not set or Status not 0, save register byte, set the
13080 * err_code, and return an error.
13081 */
13082 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
13083 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013084
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013085 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
13086 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
13087 /* Get here if Done bit not set or Status not 0. */
13088 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060013089 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013090 return ADV_ERROR;
13091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013092
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013093 /* We need to reset back to normal mode after LRAM test passes. */
13094 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013095
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060013096 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
13097 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
13098 _adv_asc38C1600_chksum);
13099 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013100 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013101
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013102 /*
13103 * Restore the RISC memory BIOS region.
13104 */
13105 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
13106 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
13107 bios_mem[i]);
13108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013109
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013110 /*
13111 * Calculate and write the microcode code checksum to the microcode
13112 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
13113 */
13114 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
13115 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
13116 code_sum = 0;
13117 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
13118 for (word = begin_addr; word < end_addr; word += 2) {
13119 code_sum += AdvReadWordAutoIncLram(iop_base);
13120 }
13121 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013122
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013123 /*
13124 * Read microcode version and date.
13125 */
13126 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
13127 asc_dvc->cfg->mcode_date);
13128 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
13129 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013130
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013131 /*
13132 * Set the chip type to indicate the ASC38C1600.
13133 */
13134 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013135
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013136 /*
13137 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
13138 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
13139 * cable detection and then we are able to read C_DET[3:0].
13140 *
13141 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
13142 * Microcode Default Value' section below.
13143 */
13144 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
13145 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
13146 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013147
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013148 /*
13149 * If the PCI Configuration Command Register "Parity Error Response
13150 * Control" Bit was clear (0), then set the microcode variable
13151 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
13152 * to ignore DMA parity errors.
13153 */
13154 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
13155 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
13156 word |= CONTROL_FLAG_IGNORE_PERR;
13157 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
13158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013159
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013160 /*
13161 * If the BIOS control flag AIPP (Asynchronous Information
13162 * Phase Protection) disable bit is not set, then set the firmware
13163 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
13164 * AIPP checking and encoding.
13165 */
13166 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
13167 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
13168 word |= CONTROL_FLAG_ENABLE_AIPP;
13169 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
13170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013171
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013172 /*
13173 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
13174 * and START_CTL_TH [3:2].
13175 */
13176 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
13177 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013178
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013179 /*
13180 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040013181 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013182 * device reports it is capable of in Inquiry byte 7.
13183 *
13184 * If SCSI Bus Resets have been disabled, then directly set
13185 * SDTR and WDTR from the EEPROM configuration. This will allow
13186 * the BIOS and warm boot to work without a SCSI bus hang on
13187 * the Inquiry caused by host and target mismatched DTR values.
13188 * Without the SCSI Bus Reset, before an Inquiry a device can't
13189 * be assumed to be in Asynchronous, Narrow mode.
13190 */
13191 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
13192 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
13193 asc_dvc->wdtr_able);
13194 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
13195 asc_dvc->sdtr_able);
13196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013197
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013198 /*
13199 * Set microcode operating variables for DISC and SDTR_SPEED1,
13200 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
13201 * configuration values.
13202 *
13203 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
13204 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
13205 * without determining here whether the device supports SDTR.
13206 */
13207 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
13208 asc_dvc->cfg->disc_enable);
13209 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
13210 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
13211 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
13212 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013213
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013214 /*
13215 * Set SCSI_CFG0 Microcode Default Value.
13216 *
13217 * The microcode will set the SCSI_CFG0 register using this value
13218 * after it is started below.
13219 */
13220 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
13221 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
13222 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013223
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013224 /*
13225 * Calculate SCSI_CFG1 Microcode Default Value.
13226 *
13227 * The microcode will set the SCSI_CFG1 register using this value
13228 * after it is started below.
13229 *
13230 * Each ASC-38C1600 function has only two cable detect bits.
13231 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
13232 */
13233 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013234
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013235 /*
13236 * If the cable is reversed all of the SCSI_CTRL register signals
13237 * will be set. Check for and return an error if this condition is
13238 * found.
13239 */
13240 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
13241 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
13242 return ADV_ERROR;
13243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013244
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013245 /*
13246 * Each ASC-38C1600 function has two connectors. Only an HVD device
13247 * can not be connected to either connector. An LVD device or SE device
13248 * may be connected to either connecor. If an SE device is connected,
13249 * then at most Ultra speed (20 Mhz) can be used on both connectors.
13250 *
13251 * If an HVD device is attached, return an error.
13252 */
13253 if (scsi_cfg1 & HVD) {
13254 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
13255 return ADV_ERROR;
13256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013257
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013258 /*
13259 * Each function in the ASC-38C1600 uses only the SE cable detect and
13260 * termination because there are two connectors for each function. Each
13261 * function may use either LVD or SE mode. Corresponding the SE automatic
13262 * termination control EEPROM bits are used for each function. Each
13263 * function has its own EEPROM. If SE automatic control is enabled for
13264 * the function, then set the termination value based on a table listed
13265 * in a_condor.h.
13266 *
13267 * If manual termination is specified in the EEPROM for the function,
13268 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
13269 * ready to be 'ored' into SCSI_CFG1.
13270 */
13271 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013272 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013273 /* SE automatic termination control is enabled. */
13274 switch (scsi_cfg1 & C_DET_SE) {
13275 /* TERM_SE_HI: on, TERM_SE_LO: on */
13276 case 0x1:
13277 case 0x2:
13278 case 0x3:
13279 asc_dvc->cfg->termination |= TERM_SE;
13280 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013281
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013282 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013283 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013284 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
13285 } else {
13286 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
13287 asc_dvc->cfg->termination |= TERM_SE_HI;
13288 }
13289 break;
13290 }
13291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013292
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013293 /*
13294 * Clear any set TERM_SE bits.
13295 */
13296 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013297
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013298 /*
13299 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
13300 */
13301 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013302
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013303 /*
13304 * Clear Big Endian and Terminator Polarity bits and set possibly
13305 * modified termination control bits in the Microcode SCSI_CFG1
13306 * Register Value.
13307 *
13308 * Big Endian bit is not used even on big endian machines.
13309 */
13310 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013311
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013312 /*
13313 * Set SCSI_CFG1 Microcode Default Value
13314 *
13315 * Set possibly modified termination control bits in the Microcode
13316 * SCSI_CFG1 Register Value.
13317 *
13318 * The microcode will set the SCSI_CFG1 register using this value
13319 * after it is started below.
13320 */
13321 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013322
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013323 /*
13324 * Set MEM_CFG Microcode Default Value
13325 *
13326 * The microcode will set the MEM_CFG register using this value
13327 * after it is started below.
13328 *
13329 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
13330 * are defined.
13331 *
13332 * ASC-38C1600 has 32KB internal memory.
13333 *
13334 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
13335 * out a special 16K Adv Library and Microcode version. After the issue
13336 * resolved, we should turn back to the 32K support. Both a_condor.h and
13337 * mcode.sas files also need to be updated.
13338 *
13339 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
13340 * BIOS_EN | RAM_SZ_32KB);
13341 */
13342 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
13343 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013344
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013345 /*
13346 * Set SEL_MASK Microcode Default Value
13347 *
13348 * The microcode will set the SEL_MASK register using this value
13349 * after it is started below.
13350 */
13351 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
13352 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013353
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060013354 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013355
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013356 /*
13357 * Set-up the Host->RISC Initiator Command Queue (ICQ).
13358 */
13359 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
13360 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
13361 return ADV_ERROR;
13362 }
13363 asc_dvc->carr_freelist = (ADV_CARR_T *)
13364 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013365
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013366 /*
13367 * The first command issued will be placed in the stopper carrier.
13368 */
13369 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013370
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013371 /*
13372 * Set RISC ICQ physical address start value. Initialize the
13373 * COMMA register to the same value otherwise the RISC will
13374 * prematurely detect a command is available.
13375 */
13376 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
13377 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
13378 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013379
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013380 /*
13381 * Set-up the RISC->Host Initiator Response Queue (IRQ).
13382 */
13383 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
13384 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
13385 return ADV_ERROR;
13386 }
13387 asc_dvc->carr_freelist = (ADV_CARR_T *)
13388 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013389
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013390 /*
13391 * The first command completed by the RISC will be placed in
13392 * the stopper.
13393 *
13394 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
13395 * completed the RISC will set the ASC_RQ_STOPPER bit.
13396 */
13397 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013398
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013399 /*
13400 * Set RISC IRQ physical address start value.
13401 */
13402 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
13403 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013404
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013405 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
13406 (ADV_INTR_ENABLE_HOST_INTR |
13407 ADV_INTR_ENABLE_GLOBAL_INTR));
13408 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
13409 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013410
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013411 /* finally, finally, gentlemen, start your engine */
13412 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013413
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013414 /*
13415 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
13416 * Resets should be performed. The RISC has to be running
13417 * to issue a SCSI Bus Reset.
13418 */
13419 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
13420 /*
13421 * If the BIOS Signature is present in memory, restore the
13422 * per TID microcode operating variables.
13423 */
13424 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
13425 0x55AA) {
13426 /*
13427 * Restore per TID negotiated values.
13428 */
13429 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
13430 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
13431 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
13432 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
13433 tagqng_able);
13434 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13435 AdvWriteByteLram(iop_base,
13436 ASC_MC_NUMBER_OF_MAX_CMD + tid,
13437 max_cmd[tid]);
13438 }
13439 } else {
13440 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
13441 warn_code = ASC_WARN_BUSRESET_ERROR;
13442 }
13443 }
13444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013445
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013446 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013447}
13448
13449/*
13450 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13451 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13452 * all of this is done.
13453 *
13454 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13455 *
13456 * For a non-fatal error return a warning code. If there are no warnings
13457 * then 0 is returned.
13458 *
13459 * Note: Chip is stopped on entry.
13460 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013461static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013462{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013463 AdvPortAddr iop_base;
13464 ushort warn_code;
13465 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013466
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013467 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013468
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013469 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013470
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013471 /*
13472 * Read the board's EEPROM configuration.
13473 *
13474 * Set default values if a bad checksum is found.
13475 */
13476 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
13477 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013478
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013479 /*
13480 * Set EEPROM default values.
13481 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013482 memcpy(&eep_config, &Default_3550_EEPROM_Config,
13483 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013484
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013485 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013486 * Assume the 6 byte board serial number that was read from
13487 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013488 */
13489 eep_config.serial_number_word3 =
13490 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013491
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013492 eep_config.serial_number_word2 =
13493 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013494
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013495 eep_config.serial_number_word1 =
13496 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013497
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013498 AdvSet3550EEPConfig(iop_base, &eep_config);
13499 }
13500 /*
13501 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13502 * EEPROM configuration that was read.
13503 *
13504 * This is the mapping of EEPROM fields to Adv Library fields.
13505 */
13506 asc_dvc->wdtr_able = eep_config.wdtr_able;
13507 asc_dvc->sdtr_able = eep_config.sdtr_able;
13508 asc_dvc->ultra_able = eep_config.ultra_able;
13509 asc_dvc->tagqng_able = eep_config.tagqng_able;
13510 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13511 asc_dvc->max_host_qng = eep_config.max_host_qng;
13512 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13513 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13514 asc_dvc->start_motor = eep_config.start_motor;
13515 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13516 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13517 asc_dvc->no_scam = eep_config.scam_tolerant;
13518 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13519 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13520 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013521
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013522 /*
13523 * Set the host maximum queuing (max. 253, min. 16) and the per device
13524 * maximum queuing (max. 63, min. 4).
13525 */
13526 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13527 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13528 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13529 /* If the value is zero, assume it is uninitialized. */
13530 if (eep_config.max_host_qng == 0) {
13531 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13532 } else {
13533 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13534 }
13535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013536
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013537 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13538 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13539 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13540 /* If the value is zero, assume it is uninitialized. */
13541 if (eep_config.max_dvc_qng == 0) {
13542 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13543 } else {
13544 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13545 }
13546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013547
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013548 /*
13549 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13550 * set 'max_dvc_qng' to 'max_host_qng'.
13551 */
13552 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13553 eep_config.max_dvc_qng = eep_config.max_host_qng;
13554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013555
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013556 /*
13557 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13558 * values based on possibly adjusted EEPROM values.
13559 */
13560 asc_dvc->max_host_qng = eep_config.max_host_qng;
13561 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013562
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013563 /*
13564 * If the EEPROM 'termination' field is set to automatic (0), then set
13565 * the ADV_DVC_CFG 'termination' field to automatic also.
13566 *
13567 * If the termination is specified with a non-zero 'termination'
13568 * value check that a legal value is set and set the ADV_DVC_CFG
13569 * 'termination' field appropriately.
13570 */
13571 if (eep_config.termination == 0) {
13572 asc_dvc->cfg->termination = 0; /* auto termination */
13573 } else {
13574 /* Enable manual control with low off / high off. */
13575 if (eep_config.termination == 1) {
13576 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013577
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013578 /* Enable manual control with low off / high on. */
13579 } else if (eep_config.termination == 2) {
13580 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013581
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013582 /* Enable manual control with low on / high on. */
13583 } else if (eep_config.termination == 3) {
13584 asc_dvc->cfg->termination =
13585 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
13586 } else {
13587 /*
13588 * The EEPROM 'termination' field contains a bad value. Use
13589 * automatic termination instead.
13590 */
13591 asc_dvc->cfg->termination = 0;
13592 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13593 }
13594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013595
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013596 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013597}
13598
13599/*
13600 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
13601 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
13602 * all of this is done.
13603 *
13604 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
13605 *
13606 * For a non-fatal error return a warning code. If there are no warnings
13607 * then 0 is returned.
13608 *
13609 * Note: Chip is stopped on entry.
13610 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013611static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013612{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013613 AdvPortAddr iop_base;
13614 ushort warn_code;
13615 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013616 uchar tid, termination;
13617 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013618
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013619 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013620
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013621 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013622
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013623 /*
13624 * Read the board's EEPROM configuration.
13625 *
13626 * Set default values if a bad checksum is found.
13627 */
13628 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13629 eep_config.check_sum) {
13630 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013631
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013632 /*
13633 * Set EEPROM default values.
13634 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013635 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13636 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013637
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013638 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013639 * Assume the 6 byte board serial number that was read from
13640 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013641 */
13642 eep_config.serial_number_word3 =
13643 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013644
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013645 eep_config.serial_number_word2 =
13646 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013647
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013648 eep_config.serial_number_word1 =
13649 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013650
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013651 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13652 }
13653 /*
13654 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13655 * EEPROM configuration that was read.
13656 *
13657 * This is the mapping of EEPROM fields to Adv Library fields.
13658 */
13659 asc_dvc->wdtr_able = eep_config.wdtr_able;
13660 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13661 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13662 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13663 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13664 asc_dvc->tagqng_able = eep_config.tagqng_able;
13665 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13666 asc_dvc->max_host_qng = eep_config.max_host_qng;
13667 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13668 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13669 asc_dvc->start_motor = eep_config.start_motor;
13670 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13671 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13672 asc_dvc->no_scam = eep_config.scam_tolerant;
13673 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13674 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13675 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013676
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013677 /*
13678 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13679 * are set, then set an 'sdtr_able' bit for it.
13680 */
13681 asc_dvc->sdtr_able = 0;
13682 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13683 if (tid == 0) {
13684 sdtr_speed = asc_dvc->sdtr_speed1;
13685 } else if (tid == 4) {
13686 sdtr_speed = asc_dvc->sdtr_speed2;
13687 } else if (tid == 8) {
13688 sdtr_speed = asc_dvc->sdtr_speed3;
13689 } else if (tid == 12) {
13690 sdtr_speed = asc_dvc->sdtr_speed4;
13691 }
13692 if (sdtr_speed & ADV_MAX_TID) {
13693 asc_dvc->sdtr_able |= (1 << tid);
13694 }
13695 sdtr_speed >>= 4;
13696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013697
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013698 /*
13699 * Set the host maximum queuing (max. 253, min. 16) and the per device
13700 * maximum queuing (max. 63, min. 4).
13701 */
13702 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13703 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13704 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13705 /* If the value is zero, assume it is uninitialized. */
13706 if (eep_config.max_host_qng == 0) {
13707 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13708 } else {
13709 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13710 }
13711 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013712
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013713 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13714 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13715 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13716 /* If the value is zero, assume it is uninitialized. */
13717 if (eep_config.max_dvc_qng == 0) {
13718 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13719 } else {
13720 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13721 }
13722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013723
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013724 /*
13725 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13726 * set 'max_dvc_qng' to 'max_host_qng'.
13727 */
13728 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13729 eep_config.max_dvc_qng = eep_config.max_host_qng;
13730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013731
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013732 /*
13733 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13734 * values based on possibly adjusted EEPROM values.
13735 */
13736 asc_dvc->max_host_qng = eep_config.max_host_qng;
13737 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013738
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013739 /*
13740 * If the EEPROM 'termination' field is set to automatic (0), then set
13741 * the ADV_DVC_CFG 'termination' field to automatic also.
13742 *
13743 * If the termination is specified with a non-zero 'termination'
13744 * value check that a legal value is set and set the ADV_DVC_CFG
13745 * 'termination' field appropriately.
13746 */
13747 if (eep_config.termination_se == 0) {
13748 termination = 0; /* auto termination for SE */
13749 } else {
13750 /* Enable manual control with low off / high off. */
13751 if (eep_config.termination_se == 1) {
13752 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013753
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013754 /* Enable manual control with low off / high on. */
13755 } else if (eep_config.termination_se == 2) {
13756 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013758 /* Enable manual control with low on / high on. */
13759 } else if (eep_config.termination_se == 3) {
13760 termination = TERM_SE;
13761 } else {
13762 /*
13763 * The EEPROM 'termination_se' field contains a bad value.
13764 * Use automatic termination instead.
13765 */
13766 termination = 0;
13767 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13768 }
13769 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013770
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013771 if (eep_config.termination_lvd == 0) {
13772 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13773 } else {
13774 /* Enable manual control with low off / high off. */
13775 if (eep_config.termination_lvd == 1) {
13776 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013777
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013778 /* Enable manual control with low off / high on. */
13779 } else if (eep_config.termination_lvd == 2) {
13780 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013781
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013782 /* Enable manual control with low on / high on. */
13783 } else if (eep_config.termination_lvd == 3) {
13784 asc_dvc->cfg->termination = termination | TERM_LVD;
13785 } else {
13786 /*
13787 * The EEPROM 'termination_lvd' field contains a bad value.
13788 * Use automatic termination instead.
13789 */
13790 asc_dvc->cfg->termination = termination;
13791 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13792 }
13793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013794
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013795 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013796}
13797
13798/*
13799 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13800 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13801 * all of this is done.
13802 *
13803 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13804 *
13805 * For a non-fatal error return a warning code. If there are no warnings
13806 * then 0 is returned.
13807 *
13808 * Note: Chip is stopped on entry.
13809 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013810static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013811{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013812 AdvPortAddr iop_base;
13813 ushort warn_code;
13814 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013815 uchar tid, termination;
13816 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013817
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013818 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013819
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013820 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013821
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013822 /*
13823 * Read the board's EEPROM configuration.
13824 *
13825 * Set default values if a bad checksum is found.
13826 */
13827 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13828 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013829 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013830 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013831
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013832 /*
13833 * Set EEPROM default values.
13834 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013835 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13836 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013837
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013838 if (PCI_FUNC(pdev->devfn) != 0) {
13839 u8 ints;
13840 /*
13841 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13842 * and old Mac system booting problem. The Expansion
13843 * ROM must be disabled in Function 1 for these systems
13844 */
13845 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13846 /*
13847 * Clear the INTAB (bit 11) if the GPIO 0 input
13848 * indicates the Function 1 interrupt line is wired
13849 * to INTB.
13850 *
13851 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13852 * 1 - Function 1 interrupt line wired to INT A.
13853 * 0 - Function 1 interrupt line wired to INT B.
13854 *
13855 * Note: Function 0 is always wired to INTA.
13856 * Put all 5 GPIO bits in input mode and then read
13857 * their input values.
13858 */
13859 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13860 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13861 if ((ints & 0x01) == 0)
13862 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013864
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013865 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013866 * Assume the 6 byte board serial number that was read from
13867 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013868 */
13869 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013870 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013871 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013872 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013873 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013874 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013875
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013876 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013878
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013879 /*
13880 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13881 * EEPROM configuration that was read.
13882 *
13883 * This is the mapping of EEPROM fields to Adv Library fields.
13884 */
13885 asc_dvc->wdtr_able = eep_config.wdtr_able;
13886 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13887 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13888 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13889 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13890 asc_dvc->ppr_able = 0;
13891 asc_dvc->tagqng_able = eep_config.tagqng_able;
13892 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13893 asc_dvc->max_host_qng = eep_config.max_host_qng;
13894 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13895 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13896 asc_dvc->start_motor = eep_config.start_motor;
13897 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13898 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13899 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013900
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013901 /*
13902 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13903 * are set, then set an 'sdtr_able' bit for it.
13904 */
13905 asc_dvc->sdtr_able = 0;
13906 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13907 if (tid == 0) {
13908 sdtr_speed = asc_dvc->sdtr_speed1;
13909 } else if (tid == 4) {
13910 sdtr_speed = asc_dvc->sdtr_speed2;
13911 } else if (tid == 8) {
13912 sdtr_speed = asc_dvc->sdtr_speed3;
13913 } else if (tid == 12) {
13914 sdtr_speed = asc_dvc->sdtr_speed4;
13915 }
13916 if (sdtr_speed & ASC_MAX_TID) {
13917 asc_dvc->sdtr_able |= (1 << tid);
13918 }
13919 sdtr_speed >>= 4;
13920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013921
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013922 /*
13923 * Set the host maximum queuing (max. 253, min. 16) and the per device
13924 * maximum queuing (max. 63, min. 4).
13925 */
13926 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13927 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13928 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13929 /* If the value is zero, assume it is uninitialized. */
13930 if (eep_config.max_host_qng == 0) {
13931 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13932 } else {
13933 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13934 }
13935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013936
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013937 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13938 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13939 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13940 /* If the value is zero, assume it is uninitialized. */
13941 if (eep_config.max_dvc_qng == 0) {
13942 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13943 } else {
13944 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13945 }
13946 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013947
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013948 /*
13949 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13950 * set 'max_dvc_qng' to 'max_host_qng'.
13951 */
13952 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13953 eep_config.max_dvc_qng = eep_config.max_host_qng;
13954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013955
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013956 /*
13957 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13958 * values based on possibly adjusted EEPROM values.
13959 */
13960 asc_dvc->max_host_qng = eep_config.max_host_qng;
13961 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013962
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013963 /*
13964 * If the EEPROM 'termination' field is set to automatic (0), then set
13965 * the ASC_DVC_CFG 'termination' field to automatic also.
13966 *
13967 * If the termination is specified with a non-zero 'termination'
13968 * value check that a legal value is set and set the ASC_DVC_CFG
13969 * 'termination' field appropriately.
13970 */
13971 if (eep_config.termination_se == 0) {
13972 termination = 0; /* auto termination for SE */
13973 } else {
13974 /* Enable manual control with low off / high off. */
13975 if (eep_config.termination_se == 1) {
13976 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013977
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013978 /* Enable manual control with low off / high on. */
13979 } else if (eep_config.termination_se == 2) {
13980 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013981
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013982 /* Enable manual control with low on / high on. */
13983 } else if (eep_config.termination_se == 3) {
13984 termination = TERM_SE;
13985 } else {
13986 /*
13987 * The EEPROM 'termination_se' field contains a bad value.
13988 * Use automatic termination instead.
13989 */
13990 termination = 0;
13991 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13992 }
13993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013994
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013995 if (eep_config.termination_lvd == 0) {
13996 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13997 } else {
13998 /* Enable manual control with low off / high off. */
13999 if (eep_config.termination_lvd == 1) {
14000 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014001
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014002 /* Enable manual control with low off / high on. */
14003 } else if (eep_config.termination_lvd == 2) {
14004 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014005
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014006 /* Enable manual control with low on / high on. */
14007 } else if (eep_config.termination_lvd == 3) {
14008 asc_dvc->cfg->termination = termination | TERM_LVD;
14009 } else {
14010 /*
14011 * The EEPROM 'termination_lvd' field contains a bad value.
14012 * Use automatic termination instead.
14013 */
14014 asc_dvc->cfg->termination = termination;
14015 warn_code |= ASC_WARN_EEPROM_TERMINATION;
14016 }
14017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014018
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014019 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014020}
14021
14022/*
14023 * Read EEPROM configuration into the specified buffer.
14024 *
14025 * Return a checksum based on the EEPROM configuration read.
14026 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014027static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070014028AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
14029{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014030 ushort wval, chksum;
14031 ushort *wbuf;
14032 int eep_addr;
14033 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014034
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014035 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
14036 wbuf = (ushort *)cfg_buf;
14037 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014038
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014039 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
14040 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
14041 wval = AdvReadEEPWord(iop_base, eep_addr);
14042 chksum += wval; /* Checksum is calculated from word values. */
14043 if (*charfields++) {
14044 *wbuf = le16_to_cpu(wval);
14045 } else {
14046 *wbuf = wval;
14047 }
14048 }
14049 /* Read checksum word. */
14050 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14051 wbuf++;
14052 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014053
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014054 /* Read rest of EEPROM not covered by the checksum. */
14055 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
14056 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
14057 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14058 if (*charfields++) {
14059 *wbuf = le16_to_cpu(*wbuf);
14060 }
14061 }
14062 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014063}
14064
14065/*
14066 * Read EEPROM configuration into the specified buffer.
14067 *
14068 * Return a checksum based on the EEPROM configuration read.
14069 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014070static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014071AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014072{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014073 ushort wval, chksum;
14074 ushort *wbuf;
14075 int eep_addr;
14076 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014077
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014078 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
14079 wbuf = (ushort *)cfg_buf;
14080 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014081
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014082 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
14083 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
14084 wval = AdvReadEEPWord(iop_base, eep_addr);
14085 chksum += wval; /* Checksum is calculated from word values. */
14086 if (*charfields++) {
14087 *wbuf = le16_to_cpu(wval);
14088 } else {
14089 *wbuf = wval;
14090 }
14091 }
14092 /* Read checksum word. */
14093 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14094 wbuf++;
14095 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014096
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014097 /* Read rest of EEPROM not covered by the checksum. */
14098 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
14099 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
14100 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14101 if (*charfields++) {
14102 *wbuf = le16_to_cpu(*wbuf);
14103 }
14104 }
14105 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014106}
14107
14108/*
14109 * Read EEPROM configuration into the specified buffer.
14110 *
14111 * Return a checksum based on the EEPROM configuration read.
14112 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014113static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014114AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014115{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014116 ushort wval, chksum;
14117 ushort *wbuf;
14118 int eep_addr;
14119 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014120
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014121 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
14122 wbuf = (ushort *)cfg_buf;
14123 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014124
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014125 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
14126 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
14127 wval = AdvReadEEPWord(iop_base, eep_addr);
14128 chksum += wval; /* Checksum is calculated from word values. */
14129 if (*charfields++) {
14130 *wbuf = le16_to_cpu(wval);
14131 } else {
14132 *wbuf = wval;
14133 }
14134 }
14135 /* Read checksum word. */
14136 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14137 wbuf++;
14138 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014139
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014140 /* Read rest of EEPROM not covered by the checksum. */
14141 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
14142 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
14143 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14144 if (*charfields++) {
14145 *wbuf = le16_to_cpu(*wbuf);
14146 }
14147 }
14148 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014149}
14150
14151/*
14152 * Read the EEPROM from specified location
14153 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014154static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014155{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014156 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14157 ASC_EEP_CMD_READ | eep_word_addr);
14158 AdvWaitEEPCmd(iop_base);
14159 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014160}
14161
14162/*
14163 * Wait for EEPROM command to complete
14164 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014165static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014166{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014167 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014168
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014169 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
14170 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
14171 ASC_EEP_CMD_DONE) {
14172 break;
14173 }
14174 DvcSleepMilliSecond(1);
14175 }
14176 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
14177 0) {
14178 ASC_ASSERT(0);
14179 }
14180 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014181}
14182
14183/*
14184 * Write the EEPROM from 'cfg_buf'.
14185 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014186void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070014187AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
14188{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189 ushort *wbuf;
14190 ushort addr, chksum;
14191 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014192
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014193 wbuf = (ushort *)cfg_buf;
14194 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
14195 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014197 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
14198 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014199
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014200 /*
14201 * Write EEPROM from word 0 to word 20.
14202 */
14203 for (addr = ADV_EEP_DVC_CFG_BEGIN;
14204 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
14205 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014206
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014207 if (*charfields++) {
14208 word = cpu_to_le16(*wbuf);
14209 } else {
14210 word = *wbuf;
14211 }
14212 chksum += *wbuf; /* Checksum is calculated from word values. */
14213 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
14214 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14215 ASC_EEP_CMD_WRITE | addr);
14216 AdvWaitEEPCmd(iop_base);
14217 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
14218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014219
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014220 /*
14221 * Write EEPROM checksum at word 21.
14222 */
14223 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
14224 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14225 AdvWaitEEPCmd(iop_base);
14226 wbuf++;
14227 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014228
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014229 /*
14230 * Write EEPROM OEM name at words 22 to 29.
14231 */
14232 for (addr = ADV_EEP_DVC_CTL_BEGIN;
14233 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
14234 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014235
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014236 if (*charfields++) {
14237 word = cpu_to_le16(*wbuf);
14238 } else {
14239 word = *wbuf;
14240 }
14241 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
14242 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14243 ASC_EEP_CMD_WRITE | addr);
14244 AdvWaitEEPCmd(iop_base);
14245 }
14246 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
14247 AdvWaitEEPCmd(iop_base);
14248 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014249}
14250
14251/*
14252 * Write the EEPROM from 'cfg_buf'.
14253 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014254void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014255AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014256{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014257 ushort *wbuf;
14258 ushort *charfields;
14259 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014260
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014261 wbuf = (ushort *)cfg_buf;
14262 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
14263 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014264
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014265 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
14266 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014267
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014268 /*
14269 * Write EEPROM from word 0 to word 20.
14270 */
14271 for (addr = ADV_EEP_DVC_CFG_BEGIN;
14272 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
14273 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014274
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014275 if (*charfields++) {
14276 word = cpu_to_le16(*wbuf);
14277 } else {
14278 word = *wbuf;
14279 }
14280 chksum += *wbuf; /* Checksum is calculated from word values. */
14281 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
14282 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14283 ASC_EEP_CMD_WRITE | addr);
14284 AdvWaitEEPCmd(iop_base);
14285 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
14286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014287
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014288 /*
14289 * Write EEPROM checksum at word 21.
14290 */
14291 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
14292 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14293 AdvWaitEEPCmd(iop_base);
14294 wbuf++;
14295 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014296
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014297 /*
14298 * Write EEPROM OEM name at words 22 to 29.
14299 */
14300 for (addr = ADV_EEP_DVC_CTL_BEGIN;
14301 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
14302 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014303
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014304 if (*charfields++) {
14305 word = cpu_to_le16(*wbuf);
14306 } else {
14307 word = *wbuf;
14308 }
14309 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
14310 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14311 ASC_EEP_CMD_WRITE | addr);
14312 AdvWaitEEPCmd(iop_base);
14313 }
14314 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
14315 AdvWaitEEPCmd(iop_base);
14316 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014317}
14318
14319/*
14320 * Write the EEPROM from 'cfg_buf'.
14321 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014322void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014323AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014324{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014325 ushort *wbuf;
14326 ushort *charfields;
14327 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014328
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014329 wbuf = (ushort *)cfg_buf;
14330 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
14331 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014332
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014333 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
14334 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014335
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014336 /*
14337 * Write EEPROM from word 0 to word 20.
14338 */
14339 for (addr = ADV_EEP_DVC_CFG_BEGIN;
14340 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
14341 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014342
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014343 if (*charfields++) {
14344 word = cpu_to_le16(*wbuf);
14345 } else {
14346 word = *wbuf;
14347 }
14348 chksum += *wbuf; /* Checksum is calculated from word values. */
14349 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
14350 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14351 ASC_EEP_CMD_WRITE | addr);
14352 AdvWaitEEPCmd(iop_base);
14353 DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
14354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014355
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014356 /*
14357 * Write EEPROM checksum at word 21.
14358 */
14359 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
14360 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14361 AdvWaitEEPCmd(iop_base);
14362 wbuf++;
14363 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014364
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014365 /*
14366 * Write EEPROM OEM name at words 22 to 29.
14367 */
14368 for (addr = ADV_EEP_DVC_CTL_BEGIN;
14369 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
14370 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014371
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014372 if (*charfields++) {
14373 word = cpu_to_le16(*wbuf);
14374 } else {
14375 word = *wbuf;
14376 }
14377 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
14378 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14379 ASC_EEP_CMD_WRITE | addr);
14380 AdvWaitEEPCmd(iop_base);
14381 }
14382 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
14383 AdvWaitEEPCmd(iop_base);
14384 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014385}
14386
14387/* a_advlib.c */
14388/*
14389 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
14390 *
14391 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
14392 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
14393 * RISC to notify it a new command is ready to be executed.
14394 *
14395 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
14396 * set to SCSI_MAX_RETRY.
14397 *
14398 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
14399 * for DMA addresses or math operations are byte swapped to little-endian
14400 * order.
14401 *
14402 * Return:
14403 * ADV_SUCCESS(1) - The request was successfully queued.
14404 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
14405 * request completes.
14406 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
14407 * host IC error.
14408 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014409static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014410{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014411 ulong last_int_level;
14412 AdvPortAddr iop_base;
14413 ADV_DCNT req_size;
14414 ADV_PADDR req_paddr;
14415 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014416
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014417 ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014418
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014419 /*
14420 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
14421 */
14422 if (scsiq->target_id > ADV_MAX_TID) {
14423 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
14424 scsiq->done_status = QD_WITH_ERROR;
14425 return ADV_ERROR;
14426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014427
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014428 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014429
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014430 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014431
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014432 /*
14433 * Allocate a carrier ensuring at least one carrier always
14434 * remains on the freelist and initialize fields.
14435 */
14436 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
14437 DvcLeaveCritical(last_int_level);
14438 return ADV_BUSY;
14439 }
14440 asc_dvc->carr_freelist = (ADV_CARR_T *)
14441 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
14442 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014443
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014444 /*
14445 * Set the carrier to be a stopper by setting 'next_vpa'
14446 * to the stopper value. The current stopper will be changed
14447 * below to point to the new stopper.
14448 */
14449 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014450
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014451 /*
14452 * Clear the ADV_SCSI_REQ_Q done flag.
14453 */
14454 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014455
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014456 req_size = sizeof(ADV_SCSI_REQ_Q);
14457 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
14458 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014459
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014460 ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
14461 ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014462
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014463 /* Wait for assertion before making little-endian */
14464 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014465
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014466 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
14467 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
14468 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014469
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014470 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
14471 /*
14472 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
14473 * order during initialization.
14474 */
14475 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014476
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014477 /*
14478 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
14479 * the microcode. The newly allocated stopper will become the new
14480 * stopper.
14481 */
14482 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014483
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014484 /*
14485 * Set the 'next_vpa' pointer for the old stopper to be the
14486 * physical address of the new stopper. The RISC can only
14487 * follow physical addresses.
14488 */
14489 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014490
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014491 /*
14492 * Set the host adapter stopper pointer to point to the new carrier.
14493 */
14494 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014495
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014496 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14497 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14498 /*
14499 * Tickle the RISC to tell it to read its Command Queue Head pointer.
14500 */
14501 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
14502 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14503 /*
14504 * Clear the tickle value. In the ASC-3550 the RISC flag
14505 * command 'clr_tickle_a' does not work unless the host
14506 * value is cleared.
14507 */
14508 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14509 ADV_TICKLE_NOP);
14510 }
14511 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14512 /*
14513 * Notify the RISC a carrier is ready by writing the physical
14514 * address of the new carrier stopper to the COMMA register.
14515 */
14516 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
14517 le32_to_cpu(new_carrp->carr_pa));
14518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014519
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014520 DvcLeaveCritical(last_int_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014521
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014522 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014523}
14524
14525/*
14526 * Reset SCSI Bus and purge all outstanding requests.
14527 *
14528 * Return Value:
14529 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
14530 * ADV_FALSE(0) - Microcode command failed.
14531 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
14532 * may be hung which requires driver recovery.
14533 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014534static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014535{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014536 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014537
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014538 /*
14539 * Send the SCSI Bus Reset idle start idle command which asserts
14540 * the SCSI Bus Reset signal.
14541 */
14542 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
14543 if (status != ADV_TRUE) {
14544 return status;
14545 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014546
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014547 /*
14548 * Delay for the specified SCSI Bus Reset hold time.
14549 *
14550 * The hold time delay is done on the host because the RISC has no
14551 * microsecond accurate timer.
14552 */
14553 DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014554
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014555 /*
14556 * Send the SCSI Bus Reset end idle command which de-asserts
14557 * the SCSI Bus Reset signal and purges any pending requests.
14558 */
14559 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
14560 if (status != ADV_TRUE) {
14561 return status;
14562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014563
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014564 DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014565
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014566 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014567}
14568
14569/*
14570 * Reset chip and SCSI Bus.
14571 *
14572 * Return Value:
14573 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
14574 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
14575 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014576static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014577{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014578 int status;
14579 ushort wdtr_able, sdtr_able, tagqng_able;
14580 ushort ppr_able = 0;
14581 uchar tid, max_cmd[ADV_MAX_TID + 1];
14582 AdvPortAddr iop_base;
14583 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014584
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014585 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014586
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014587 /*
14588 * Save current per TID negotiated values.
14589 */
14590 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14591 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14592 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14593 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14594 }
14595 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14596 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14597 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14598 max_cmd[tid]);
14599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014600
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014601 /*
14602 * Force the AdvInitAsc3550/38C0800Driver() function to
14603 * perform a SCSI Bus Reset by clearing the BIOS signature word.
14604 * The initialization functions assumes a SCSI Bus Reset is not
14605 * needed if the BIOS signature word is present.
14606 */
14607 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
14608 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014609
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014610 /*
14611 * Stop chip and reset it.
14612 */
14613 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
14614 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14615 DvcSleepMilliSecond(100);
14616 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
14617 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014618
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014619 /*
14620 * Reset Adv Library error code, if any, and try
14621 * re-initializing the chip.
14622 */
14623 asc_dvc->err_code = 0;
14624 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14625 status = AdvInitAsc38C1600Driver(asc_dvc);
14626 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14627 status = AdvInitAsc38C0800Driver(asc_dvc);
14628 } else {
14629 status = AdvInitAsc3550Driver(asc_dvc);
14630 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014631
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014632 /* Translate initialization return value to status value. */
14633 if (status == 0) {
14634 status = ADV_TRUE;
14635 } else {
14636 status = ADV_FALSE;
14637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014638
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014639 /*
14640 * Restore the BIOS signature word.
14641 */
14642 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014643
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014644 /*
14645 * Restore per TID negotiated values.
14646 */
14647 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14648 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14649 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14650 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14651 }
14652 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14653 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14654 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14655 max_cmd[tid]);
14656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014657
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014658 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014659}
14660
14661/*
14662 * Adv Library Interrupt Service Routine
14663 *
14664 * This function is called by a driver's interrupt service routine.
14665 * The function disables and re-enables interrupts.
14666 *
14667 * When a microcode idle command is completed, the ADV_DVC_VAR
14668 * 'idle_cmd_done' field is set to ADV_TRUE.
14669 *
14670 * Note: AdvISR() can be called when interrupts are disabled or even
14671 * when there is no hardware interrupt condition present. It will
14672 * always check for completed idle commands and microcode requests.
14673 * This is an important feature that shouldn't be changed because it
14674 * allows commands to be completed from polling mode loops.
14675 *
14676 * Return:
14677 * ADV_TRUE(1) - interrupt was pending
14678 * ADV_FALSE(0) - no interrupt was pending
14679 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014680static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014681{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014682 AdvPortAddr iop_base;
14683 uchar int_stat;
14684 ushort target_bit;
14685 ADV_CARR_T *free_carrp;
14686 ADV_VADDR irq_next_vpa;
14687 int flags;
14688 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014689
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014690 flags = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014691
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014692 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014693
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014694 /* Reading the register clears the interrupt. */
14695 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014696
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014697 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
14698 ADV_INTR_STATUS_INTRC)) == 0) {
14699 DvcLeaveCritical(flags);
14700 return ADV_FALSE;
14701 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014702
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014703 /*
14704 * Notify the driver of an asynchronous microcode condition by
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014705 * calling the adv_async_callback function. The function
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014706 * is passed the microcode ASC_MC_INTRB_CODE byte value.
14707 */
14708 if (int_stat & ADV_INTR_STATUS_INTRB) {
14709 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014710
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014711 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014712
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014713 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14714 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14715 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
14716 asc_dvc->carr_pending_cnt != 0) {
14717 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14718 ADV_TICKLE_A);
14719 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14720 AdvWriteByteRegister(iop_base,
14721 IOPB_TICKLE,
14722 ADV_TICKLE_NOP);
14723 }
14724 }
14725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014726
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014727 adv_async_callback(asc_dvc, intrb_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014729
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014730 /*
14731 * Check if the IRQ stopper carrier contains a completed request.
14732 */
14733 while (((irq_next_vpa =
14734 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
14735 /*
14736 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
14737 * The RISC will have set 'areq_vpa' to a virtual address.
14738 *
14739 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
14740 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
14741 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
14742 * in AdvExeScsiQueue().
14743 */
14744 scsiq = (ADV_SCSI_REQ_Q *)
14745 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014746
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014747 /*
14748 * Request finished with good status and the queue was not
14749 * DMAed to host memory by the firmware. Set all status fields
14750 * to indicate good status.
14751 */
14752 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
14753 scsiq->done_status = QD_NO_ERROR;
14754 scsiq->host_status = scsiq->scsi_status = 0;
14755 scsiq->data_cnt = 0L;
14756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014757
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014758 /*
14759 * Advance the stopper pointer to the next carrier
14760 * ignoring the lower four bits. Free the previous
14761 * stopper carrier.
14762 */
14763 free_carrp = asc_dvc->irq_sp;
14764 asc_dvc->irq_sp = (ADV_CARR_T *)
14765 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014766
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014767 free_carrp->next_vpa =
14768 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14769 asc_dvc->carr_freelist = free_carrp;
14770 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014771
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014772 ASC_ASSERT(scsiq != NULL);
14773 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014774
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014775 /*
14776 * Clear request microcode control flag.
14777 */
14778 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014779
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014780 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014781 * Notify the driver of the completed request by passing
14782 * the ADV_SCSI_REQ_Q pointer to its callback function.
14783 */
14784 scsiq->a_flag |= ADV_SCSIQ_DONE;
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014785 adv_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014786 /*
14787 * Note: After the driver callback function is called, 'scsiq'
14788 * can no longer be referenced.
14789 *
14790 * Fall through and continue processing other completed
14791 * requests...
14792 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014793
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014794 /*
14795 * Disable interrupts again in case the driver inadvertently
14796 * enabled interrupts in its callback function.
14797 *
14798 * The DvcEnterCritical() return value is ignored, because
14799 * the 'flags' saved when AdvISR() was first entered will be
14800 * used to restore the interrupt flag on exit.
14801 */
14802 (void)DvcEnterCritical();
14803 }
14804 DvcLeaveCritical(flags);
14805 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014806}
14807
14808/*
14809 * Send an idle command to the chip and wait for completion.
14810 *
14811 * Command completion is polled for once per microsecond.
14812 *
14813 * The function can be called from anywhere including an interrupt handler.
14814 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
14815 * functions to prevent reentrancy.
14816 *
14817 * Return Values:
14818 * ADV_TRUE - command completed successfully
14819 * ADV_FALSE - command failed
14820 * ADV_ERROR - command timed out
14821 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014822static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070014823AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014824 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014825{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014826 ulong last_int_level;
14827 int result;
14828 ADV_DCNT i, j;
14829 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014830
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014831 last_int_level = DvcEnterCritical();
Linus Torvalds1da177e2005-04-16 15:20:36 -070014832
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014833 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014834
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014835 /*
14836 * Clear the idle command status which is set by the microcode
14837 * to a non-zero value to indicate when the command is completed.
14838 * The non-zero result is one of the IDLE_CMD_STATUS_* values
14839 * defined in a_advlib.h.
14840 */
14841 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014842
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014843 /*
14844 * Write the idle command value after the idle command parameter
14845 * has been written to avoid a race condition. If the order is not
14846 * followed, the microcode may process the idle command before the
14847 * parameters have been written to LRAM.
14848 */
14849 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
14850 cpu_to_le32(idle_cmd_parameter));
14851 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014852
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014853 /*
14854 * Tickle the RISC to tell it to process the idle command.
14855 */
14856 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
14857 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14858 /*
14859 * Clear the tickle value. In the ASC-3550 the RISC flag
14860 * command 'clr_tickle_b' does not work unless the host
14861 * value is cleared.
14862 */
14863 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
14864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014865
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014866 /* Wait for up to 100 millisecond for the idle command to timeout. */
14867 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
14868 /* Poll once each microsecond for command completion. */
14869 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
14870 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
14871 result);
14872 if (result != 0) {
14873 DvcLeaveCritical(last_int_level);
14874 return result;
14875 }
14876 DvcDelayMicroSecond(asc_dvc, (ushort)1);
14877 }
14878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014879
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014880 ASC_ASSERT(0); /* The idle command should never timeout. */
14881 DvcLeaveCritical(last_int_level);
14882 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014883}
14884
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014885static int __devinit
14886advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
14887{
14888 int req_cnt = 0;
14889 adv_req_t *reqp = NULL;
14890 int sg_cnt = 0;
14891 adv_sgblk_t *sgp;
14892 int warn_code, err_code;
14893
14894 /*
14895 * Allocate buffer carrier structures. The total size
14896 * is about 4 KB, so allocate all at once.
14897 */
14898 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
14899 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
14900
14901 if (!boardp->carrp)
14902 goto kmalloc_failed;
14903
14904 /*
14905 * Allocate up to 'max_host_qng' request structures for the Wide
14906 * board. The total size is about 16 KB, so allocate all at once.
14907 * If the allocation fails decrement and try again.
14908 */
14909 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
14910 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
14911
14912 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
14913 "bytes %lu\n", reqp, req_cnt,
14914 (ulong)sizeof(adv_req_t) * req_cnt);
14915
14916 if (reqp)
14917 break;
14918 }
14919
14920 if (!reqp)
14921 goto kmalloc_failed;
14922
14923 boardp->orig_reqp = reqp;
14924
14925 /*
14926 * Allocate up to ADV_TOT_SG_BLOCK request structures for
14927 * the Wide board. Each structure is about 136 bytes.
14928 */
14929 boardp->adv_sgblkp = NULL;
14930 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
14931 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
14932
14933 if (!sgp)
14934 break;
14935
14936 sgp->next_sgblkp = boardp->adv_sgblkp;
14937 boardp->adv_sgblkp = sgp;
14938
14939 }
14940
14941 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
14942 sg_cnt, sizeof(adv_sgblk_t),
14943 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
14944
14945 if (!boardp->adv_sgblkp)
14946 goto kmalloc_failed;
14947
14948 adv_dvc_varp->carrier_buf = boardp->carrp;
14949
14950 /*
14951 * Point 'adv_reqp' to the request structures and
14952 * link them together.
14953 */
14954 req_cnt--;
14955 reqp[req_cnt].next_reqp = NULL;
14956 for (; req_cnt > 0; req_cnt--) {
14957 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
14958 }
14959 boardp->adv_reqp = &reqp[0];
14960
14961 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14962 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
14963 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
14964 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14965 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
14966 "\n");
14967 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
14968 } else {
14969 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
14970 "\n");
14971 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
14972 }
14973 err_code = adv_dvc_varp->err_code;
14974
14975 if (warn_code || err_code) {
14976 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
14977 " error 0x%x\n", boardp->id, warn_code, err_code);
14978 }
14979
14980 goto exit;
14981
14982 kmalloc_failed:
14983 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
14984 "failed\n", boardp->id);
14985 err_code = ADV_ERROR;
14986 exit:
14987 return err_code;
14988}
14989
14990static void advansys_wide_free_mem(asc_board_t *boardp)
14991{
14992 kfree(boardp->carrp);
14993 boardp->carrp = NULL;
14994 kfree(boardp->orig_reqp);
14995 boardp->orig_reqp = boardp->adv_reqp = NULL;
14996 while (boardp->adv_sgblkp) {
14997 adv_sgblk_t *sgp = boardp->adv_sgblkp;
14998 boardp->adv_sgblkp = sgp->next_sgblkp;
14999 kfree(sgp);
15000 }
15001}
15002
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015003static struct Scsi_Host *__devinit
15004advansys_board_found(int iop, struct device *dev, int bus_type)
15005{
15006 struct Scsi_Host *shost;
15007 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
15008 asc_board_t *boardp;
15009 ASC_DVC_VAR *asc_dvc_varp = NULL;
15010 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015011 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015012 int warn_code, err_code;
15013 int ret;
15014
15015 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015016 * Register the adapter, get its configuration, and
15017 * initialize it.
15018 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015019 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
15020 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015021 if (!shost)
15022 return NULL;
15023
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015024 /* Initialize private per board data */
15025 boardp = ASC_BOARDP(shost);
15026 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015027 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015028 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040015029 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015030
15031 /*
15032 * Handle both narrow and wide boards.
15033 *
15034 * If a Wide board was detected, set the board structure
15035 * wide board flag. Set-up the board structure based on
15036 * the board type.
15037 */
15038#ifdef CONFIG_PCI
15039 if (bus_type == ASC_IS_PCI &&
15040 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
15041 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
15042 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
15043 boardp->flags |= ASC_IS_WIDE_BOARD;
15044 }
15045#endif /* CONFIG_PCI */
15046
15047 if (ASC_NARROW_BOARD(boardp)) {
15048 ASC_DBG(1, "advansys_board_found: narrow board\n");
15049 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
15050 asc_dvc_varp->bus_type = bus_type;
15051 asc_dvc_varp->drv_ptr = boardp;
15052 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
15053 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
15054 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015055 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040015056#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015057 ASC_DBG(1, "advansys_board_found: wide board\n");
15058 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
15059 adv_dvc_varp->drv_ptr = boardp;
15060 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015061 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
15062 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
15063 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
15064 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
15065 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
15066 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
15067 } else {
15068 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
15069 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
15070 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015071
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040015072 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
15073 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
15074 boardp->asc_n_io_port);
15075 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015076 ASC_PRINT3
15077 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040015078 boardp->id, pci_resource_start(pdev, 1),
15079 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015080 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015081 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040015082 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f36112007-07-30 08:04:53 -060015083 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015084 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015085
15086 /*
15087 * Even though it isn't used to access wide boards, other
15088 * than for the debug line below, save I/O Port address so
15089 * that it can be reported.
15090 */
15091 boardp->ioport = iop;
15092
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040015093 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
15094 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
15095 (ushort)inpw(iop));
15096#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015097 }
15098
15099#ifdef CONFIG_PROC_FS
15100 /*
15101 * Allocate buffer for printing information from
15102 * /proc/scsi/advansys/[0...].
15103 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015104 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
15105 if (!boardp->prtbuf) {
15106 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
15107 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
15108 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015109 }
15110#endif /* CONFIG_PROC_FS */
15111
15112 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015113 /*
15114 * Set the board bus type and PCI IRQ before
15115 * calling AscInitGetConfig().
15116 */
15117 switch (asc_dvc_varp->bus_type) {
15118#ifdef CONFIG_ISA
15119 case ASC_IS_ISA:
15120 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015121 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015122 break;
15123 case ASC_IS_VL:
15124 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015125 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015126 break;
15127 case ASC_IS_EISA:
15128 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015129 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015130 break;
15131#endif /* CONFIG_ISA */
15132#ifdef CONFIG_PCI
15133 case ASC_IS_PCI:
15134 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015135 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015136 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015137 break;
15138#endif /* CONFIG_PCI */
15139 default:
15140 ASC_PRINT2
15141 ("advansys_board_found: board %d: unknown adapter type: %d\n",
15142 boardp->id, asc_dvc_varp->bus_type);
15143 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015144 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015145 break;
15146 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015147
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015148 /*
15149 * NOTE: AscInitGetConfig() may change the board's
15150 * bus_type value. The bus_type value should no
15151 * longer be used. If the bus_type field must be
15152 * referenced only use the bit-wise AND operator "&".
15153 */
15154 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060015155 err_code = AscInitGetConfig(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015156 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060015157#ifdef CONFIG_PCI
15158 /*
15159 * For Wide boards set PCI information before calling
15160 * AdvInitGetConfig().
15161 */
15162 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
15163 shost->unchecked_isa_dma = FALSE;
15164 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015165 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040015166
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060015167 err_code = AdvInitGetConfig(pdev, boardp);
15168#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015169 }
15170
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015171 if (err_code != 0)
15172 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015173
15174 /*
15175 * Save the EEPROM configuration so that it can be displayed
15176 * from /proc/scsi/advansys/[0...].
15177 */
15178 if (ASC_NARROW_BOARD(boardp)) {
15179
15180 ASCEEP_CONFIG *ep;
15181
15182 /*
15183 * Set the adapter's target id bit in the 'init_tidmask' field.
15184 */
15185 boardp->init_tidmask |=
15186 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
15187
15188 /*
15189 * Save EEPROM settings for the board.
15190 */
15191 ep = &boardp->eep_config.asc_eep;
15192
15193 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
15194 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
15195 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
15196 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
15197 ep->start_motor = asc_dvc_varp->start_motor;
15198 ep->cntl = asc_dvc_varp->dvc_cntl;
15199 ep->no_scam = asc_dvc_varp->no_scam;
15200 ep->max_total_qng = asc_dvc_varp->max_total_qng;
15201 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
15202 /* 'max_tag_qng' is set to the same value for every device. */
15203 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
15204 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
15205 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
15206 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
15207 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
15208 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
15209 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
15210
15211 /*
15212 * Modify board configuration.
15213 */
15214 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060015215 err_code = AscInitSetConfig(pdev, boardp);
15216 if (err_code)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015217 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015218
15219 /*
15220 * Finish initializing the 'Scsi_Host' structure.
15221 */
15222 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
15223 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
15224 shost->irq = asc_dvc_varp->irq_no;
15225 }
15226 } else {
15227 ADVEEP_3550_CONFIG *ep_3550;
15228 ADVEEP_38C0800_CONFIG *ep_38C0800;
15229 ADVEEP_38C1600_CONFIG *ep_38C1600;
15230
15231 /*
15232 * Save Wide EEP Configuration Information.
15233 */
15234 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
15235 ep_3550 = &boardp->eep_config.adv_3550_eep;
15236
15237 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
15238 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
15239 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
15240 ep_3550->termination = adv_dvc_varp->cfg->termination;
15241 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
15242 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
15243 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
15244 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
15245 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
15246 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
15247 ep_3550->start_motor = adv_dvc_varp->start_motor;
15248 ep_3550->scsi_reset_delay =
15249 adv_dvc_varp->scsi_reset_wait;
15250 ep_3550->serial_number_word1 =
15251 adv_dvc_varp->cfg->serial1;
15252 ep_3550->serial_number_word2 =
15253 adv_dvc_varp->cfg->serial2;
15254 ep_3550->serial_number_word3 =
15255 adv_dvc_varp->cfg->serial3;
15256 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
15257 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
15258
15259 ep_38C0800->adapter_scsi_id =
15260 adv_dvc_varp->chip_scsi_id;
15261 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
15262 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
15263 ep_38C0800->termination_lvd =
15264 adv_dvc_varp->cfg->termination;
15265 ep_38C0800->disc_enable =
15266 adv_dvc_varp->cfg->disc_enable;
15267 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
15268 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
15269 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
15270 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
15271 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
15272 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
15273 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
15274 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
15275 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
15276 ep_38C0800->scsi_reset_delay =
15277 adv_dvc_varp->scsi_reset_wait;
15278 ep_38C0800->serial_number_word1 =
15279 adv_dvc_varp->cfg->serial1;
15280 ep_38C0800->serial_number_word2 =
15281 adv_dvc_varp->cfg->serial2;
15282 ep_38C0800->serial_number_word3 =
15283 adv_dvc_varp->cfg->serial3;
15284 } else {
15285 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
15286
15287 ep_38C1600->adapter_scsi_id =
15288 adv_dvc_varp->chip_scsi_id;
15289 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
15290 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
15291 ep_38C1600->termination_lvd =
15292 adv_dvc_varp->cfg->termination;
15293 ep_38C1600->disc_enable =
15294 adv_dvc_varp->cfg->disc_enable;
15295 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
15296 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
15297 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
15298 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
15299 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
15300 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
15301 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
15302 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
15303 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
15304 ep_38C1600->scsi_reset_delay =
15305 adv_dvc_varp->scsi_reset_wait;
15306 ep_38C1600->serial_number_word1 =
15307 adv_dvc_varp->cfg->serial1;
15308 ep_38C1600->serial_number_word2 =
15309 adv_dvc_varp->cfg->serial2;
15310 ep_38C1600->serial_number_word3 =
15311 adv_dvc_varp->cfg->serial3;
15312 }
15313
15314 /*
15315 * Set the adapter's target id bit in the 'init_tidmask' field.
15316 */
15317 boardp->init_tidmask |=
15318 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015319 }
15320
15321 /*
15322 * Channels are numbered beginning with 0. For AdvanSys one host
15323 * structure supports one channel. Multi-channel boards have a
15324 * separate host structure for each channel.
15325 */
15326 shost->max_channel = 0;
15327 if (ASC_NARROW_BOARD(boardp)) {
15328 shost->max_id = ASC_MAX_TID + 1;
15329 shost->max_lun = ASC_MAX_LUN + 1;
15330
15331 shost->io_port = asc_dvc_varp->iop_base;
15332 boardp->asc_n_io_port = ASC_IOADR_GAP;
15333 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
15334
15335 /* Set maximum number of queues the adapter can handle. */
15336 shost->can_queue = asc_dvc_varp->max_total_qng;
15337 } else {
15338 shost->max_id = ADV_MAX_TID + 1;
15339 shost->max_lun = ADV_MAX_LUN + 1;
15340
15341 /*
15342 * Save the I/O Port address and length even though
15343 * I/O ports are not used to access Wide boards.
15344 * Instead the Wide boards are accessed with
15345 * PCI Memory Mapped I/O.
15346 */
15347 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015348
15349 shost->this_id = adv_dvc_varp->chip_scsi_id;
15350
15351 /* Set maximum number of queues the adapter can handle. */
15352 shost->can_queue = adv_dvc_varp->max_host_qng;
15353 }
15354
15355 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015356 * Following v1.3.89, 'cmd_per_lun' is no longer needed
15357 * and should be set to zero.
15358 *
15359 * But because of a bug introduced in v1.3.89 if the driver is
15360 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
15361 * SCSI function 'allocate_device' will panic. To allow the driver
15362 * to work as a module in these kernels set 'cmd_per_lun' to 1.
15363 *
15364 * Note: This is wrong. cmd_per_lun should be set to the depth
15365 * you want on untagged devices always.
15366 #ifdef MODULE
15367 */
15368 shost->cmd_per_lun = 1;
15369/* #else
15370 shost->cmd_per_lun = 0;
15371#endif */
15372
15373 /*
15374 * Set the maximum number of scatter-gather elements the
15375 * adapter can handle.
15376 */
15377 if (ASC_NARROW_BOARD(boardp)) {
15378 /*
15379 * Allow two commands with 'sg_tablesize' scatter-gather
15380 * elements to be executed simultaneously. This value is
15381 * the theoretical hardware limit. It may be decreased
15382 * below.
15383 */
15384 shost->sg_tablesize =
15385 (((asc_dvc_varp->max_total_qng - 2) / 2) *
15386 ASC_SG_LIST_PER_Q) + 1;
15387 } else {
15388 shost->sg_tablesize = ADV_MAX_SG_LIST;
15389 }
15390
15391 /*
15392 * The value of 'sg_tablesize' can not exceed the SCSI
15393 * mid-level driver definition of SG_ALL. SG_ALL also
15394 * must not be exceeded, because it is used to define the
15395 * size of the scatter-gather table in 'struct asc_sg_head'.
15396 */
15397 if (shost->sg_tablesize > SG_ALL) {
15398 shost->sg_tablesize = SG_ALL;
15399 }
15400
15401 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
15402
15403 /* BIOS start address. */
15404 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015405 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
15406 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015407 } else {
15408 /*
15409 * Fill-in BIOS board variables. The Wide BIOS saves
15410 * information in LRAM that is used by the driver.
15411 */
15412 AdvReadWordLram(adv_dvc_varp->iop_base,
15413 BIOS_SIGNATURE, boardp->bios_signature);
15414 AdvReadWordLram(adv_dvc_varp->iop_base,
15415 BIOS_VERSION, boardp->bios_version);
15416 AdvReadWordLram(adv_dvc_varp->iop_base,
15417 BIOS_CODESEG, boardp->bios_codeseg);
15418 AdvReadWordLram(adv_dvc_varp->iop_base,
15419 BIOS_CODELEN, boardp->bios_codelen);
15420
15421 ASC_DBG2(1,
15422 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
15423 boardp->bios_signature, boardp->bios_version);
15424
15425 ASC_DBG2(1,
15426 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
15427 boardp->bios_codeseg, boardp->bios_codelen);
15428
15429 /*
15430 * If the BIOS saved a valid signature, then fill in
15431 * the BIOS code segment base address.
15432 */
15433 if (boardp->bios_signature == 0x55AA) {
15434 /*
15435 * Convert x86 realmode code segment to a linear
15436 * address by shifting left 4.
15437 */
15438 shost->base = ((ulong)boardp->bios_codeseg << 4);
15439 } else {
15440 shost->base = 0;
15441 }
15442 }
15443
15444 /*
15445 * Register Board Resources - I/O Port, DMA, IRQ
15446 */
15447
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015448 /* Register DMA Channel for Narrow boards. */
15449 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
15450#ifdef CONFIG_ISA
15451 if (ASC_NARROW_BOARD(boardp)) {
15452 /* Register DMA channel for ISA bus. */
15453 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
15454 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015455 ret = request_dma(shost->dma_channel, "advansys");
15456 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015457 ASC_PRINT3
15458 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
15459 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015460 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015461 }
15462 AscEnableIsaDma(shost->dma_channel);
15463 }
15464 }
15465#endif /* CONFIG_ISA */
15466
15467 /* Register IRQ Number. */
15468 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015469
15470 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
15471 "advansys", shost);
15472
15473 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015474 if (ret == -EBUSY) {
15475 ASC_PRINT2
15476 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
15477 boardp->id, shost->irq);
15478 } else if (ret == -EINVAL) {
15479 ASC_PRINT2
15480 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
15481 boardp->id, shost->irq);
15482 } else {
15483 ASC_PRINT3
15484 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
15485 boardp->id, shost->irq, ret);
15486 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015487 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015488 }
15489
15490 /*
15491 * Initialize board RISC chip and enable interrupts.
15492 */
15493 if (ASC_NARROW_BOARD(boardp)) {
15494 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
15495 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
15496 err_code = asc_dvc_varp->err_code;
15497
15498 if (warn_code || err_code) {
15499 ASC_PRINT4
15500 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
15501 boardp->id,
15502 asc_dvc_varp->init_state, warn_code, err_code);
15503 }
15504 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015505 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015506 }
15507
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015508 if (err_code != 0)
15509 goto err_free_wide_mem;
15510
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015511 ASC_DBG_PRT_SCSI_HOST(2, shost);
15512
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015513 ret = scsi_add_host(shost, dev);
15514 if (ret)
15515 goto err_free_wide_mem;
15516
15517 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015518 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015519
15520 err_free_wide_mem:
15521 advansys_wide_free_mem(boardp);
15522 free_irq(shost->irq, shost);
15523 err_free_dma:
15524 if (shost->dma_channel != NO_ISA_DMA)
15525 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015526 err_free_proc:
15527 kfree(boardp->prtbuf);
15528 err_unmap:
15529 if (boardp->ioremap_addr)
15530 iounmap(boardp->ioremap_addr);
15531 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015532 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015533 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015534}
15535
15536/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015537 * advansys_release()
15538 *
15539 * Release resources allocated for a single AdvanSys adapter.
15540 */
15541static int advansys_release(struct Scsi_Host *shost)
15542{
15543 asc_board_t *boardp;
15544
15545 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015546 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015547 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060015548 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015549 if (shost->dma_channel != NO_ISA_DMA) {
15550 ASC_DBG(1, "advansys_release: free_dma()\n");
15551 free_dma(shost->dma_channel);
15552 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015553 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015554 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060015555 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015556 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015557 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015558 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015559 ASC_DBG(1, "advansys_release: end\n");
15560 return 0;
15561}
15562
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015563static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
15564 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
15565 0x0210, 0x0230, 0x0250, 0x0330
15566};
15567
15568static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
15569{
15570 PortAddr iop_base = _asc_def_iop_base[id];
15571 struct Scsi_Host *shost;
15572
15573 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015574 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
15575 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015576 return -ENODEV;
15577 }
15578 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015579 if (!AscFindSignature(iop_base))
15580 goto nodev;
15581 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
15582 goto nodev;
15583
15584 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015585 if (!shost)
15586 goto nodev;
15587
15588 dev_set_drvdata(dev, shost);
15589 return 0;
15590
15591 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015592 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015593 return -ENODEV;
15594}
15595
15596static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
15597{
Matthew Wilcox71f36112007-07-30 08:04:53 -060015598 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015599 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015600 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015601 return 0;
15602}
15603
15604static struct isa_driver advansys_isa_driver = {
15605 .probe = advansys_isa_probe,
15606 .remove = __devexit_p(advansys_isa_remove),
15607 .driver = {
15608 .owner = THIS_MODULE,
15609 .name = "advansys",
15610 },
15611};
15612
15613static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
15614{
15615 PortAddr iop_base = _asc_def_iop_base[id];
15616 struct Scsi_Host *shost;
15617
15618 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015619 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
15620 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015621 return -ENODEV;
15622 }
15623 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015624 if (!AscFindSignature(iop_base))
15625 goto nodev;
15626 /*
15627 * I don't think this condition can actually happen, but the old
15628 * driver did it, and the chances of finding a VLB setup in 2007
15629 * to do testing with is slight to none.
15630 */
15631 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
15632 goto nodev;
15633
15634 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015635 if (!shost)
15636 goto nodev;
15637
15638 dev_set_drvdata(dev, shost);
15639 return 0;
15640
15641 nodev:
Matthew Wilcox71f36112007-07-30 08:04:53 -060015642 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015643 return -ENODEV;
15644}
15645
15646static struct isa_driver advansys_vlb_driver = {
15647 .probe = advansys_vlb_probe,
15648 .remove = __devexit_p(advansys_isa_remove),
15649 .driver = {
15650 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060015651 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015652 },
15653};
15654
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015655static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
15656 { "ABP7401" },
15657 { "ABP7501" },
15658 { "" }
15659};
15660
15661MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
15662
15663/*
15664 * EISA is a little more tricky than PCI; each EISA device may have two
15665 * channels, and this driver is written to make each channel its own Scsi_Host
15666 */
15667struct eisa_scsi_data {
15668 struct Scsi_Host *host[2];
15669};
15670
15671static int __devinit advansys_eisa_probe(struct device *dev)
15672{
15673 int i, ioport;
15674 int err;
15675 struct eisa_device *edev = to_eisa_device(dev);
15676 struct eisa_scsi_data *data;
15677
15678 err = -ENOMEM;
15679 data = kzalloc(sizeof(*data), GFP_KERNEL);
15680 if (!data)
15681 goto fail;
15682 ioport = edev->base_addr + 0xc30;
15683
15684 err = -ENODEV;
15685 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015686 if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
15687 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
15688 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015689 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015690 }
15691 if (!AscFindSignature(ioport)) {
15692 release_region(ioport, ASC_IOADR_GAP);
15693 continue;
15694 }
15695
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015696 /*
15697 * I don't know why we need to do this for EISA chips, but
15698 * not for any others. It looks to be equivalent to
15699 * AscGetChipCfgMsw, but I may have overlooked something,
15700 * so I'm not converting it until I get an EISA board to
15701 * test with.
15702 */
15703 inw(ioport + 4);
15704 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015705 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015706 err = 0;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015707 } else {
15708 release_region(ioport, ASC_IOADR_GAP);
15709 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015710 }
15711
15712 if (err) {
15713 kfree(data);
15714 } else {
15715 dev_set_drvdata(dev, data);
15716 }
15717
15718 fail:
15719 return err;
15720}
15721
15722static __devexit int advansys_eisa_remove(struct device *dev)
15723{
15724 int i;
15725 struct eisa_scsi_data *data = dev_get_drvdata(dev);
15726
15727 for (i = 0; i < 2; i++) {
Matthew Wilcox71f36112007-07-30 08:04:53 -060015728 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015729 struct Scsi_Host *shost = data->host[i];
15730 if (!shost)
15731 continue;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015732 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015733 advansys_release(shost);
Matthew Wilcox71f36112007-07-30 08:04:53 -060015734 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015735 }
15736
15737 kfree(data);
15738 return 0;
15739}
15740
15741static struct eisa_driver advansys_eisa_driver = {
15742 .id_table = advansys_eisa_table,
15743 .driver = {
15744 .name = "advansys",
15745 .probe = advansys_eisa_probe,
15746 .remove = __devexit_p(advansys_eisa_remove),
15747 }
15748};
15749
Dave Jones2672ea82006-08-02 17:11:49 -040015750/* PCI Devices supported by this driver */
15751static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015752 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
15753 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15754 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
15755 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15756 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
15757 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15758 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
15759 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15760 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
15761 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15762 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
15763 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15764 {}
Dave Jones2672ea82006-08-02 17:11:49 -040015765};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015766
Dave Jones2672ea82006-08-02 17:11:49 -040015767MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015768
Matthew Wilcox9649af32007-07-26 21:51:47 -060015769static void __devinit advansys_set_latency(struct pci_dev *pdev)
15770{
15771 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
15772 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
15773 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
15774 } else {
15775 u8 latency;
15776 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
15777 if (latency < 0x20)
15778 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
15779 }
15780}
15781
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015782static int __devinit
15783advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15784{
15785 int err, ioport;
15786 struct Scsi_Host *shost;
15787
15788 err = pci_enable_device(pdev);
15789 if (err)
15790 goto fail;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015791 err = pci_request_regions(pdev, "advansys");
15792 if (err)
15793 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060015794 pci_set_master(pdev);
15795 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015796
15797 if (pci_resource_len(pdev, 0) == 0)
15798 goto nodev;
15799
15800 ioport = pci_resource_start(pdev, 0);
15801 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
15802
15803 if (!shost)
15804 goto nodev;
15805
15806 pci_set_drvdata(pdev, shost);
15807 return 0;
15808
15809 nodev:
15810 err = -ENODEV;
Matthew Wilcox71f36112007-07-30 08:04:53 -060015811 pci_release_regions(pdev);
15812 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015813 pci_disable_device(pdev);
15814 fail:
15815 return err;
15816}
15817
15818static void __devexit advansys_pci_remove(struct pci_dev *pdev)
15819{
15820 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f36112007-07-30 08:04:53 -060015821 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015822 pci_disable_device(pdev);
15823}
15824
15825static struct pci_driver advansys_pci_driver = {
15826 .name = "advansys",
15827 .id_table = advansys_pci_tbl,
15828 .probe = advansys_pci_probe,
15829 .remove = __devexit_p(advansys_pci_remove),
15830};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015831
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015832static int __init advansys_init(void)
15833{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015834 int error;
15835
15836 error = isa_register_driver(&advansys_isa_driver,
15837 ASC_IOADR_TABLE_MAX_IX);
15838 if (error)
15839 goto fail;
15840
15841 error = isa_register_driver(&advansys_vlb_driver,
15842 ASC_IOADR_TABLE_MAX_IX);
15843 if (error)
15844 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015845
15846 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015847 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015848 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015849
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015850 error = pci_register_driver(&advansys_pci_driver);
15851 if (error)
15852 goto unregister_eisa;
15853
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015854 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015855
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015856 unregister_eisa:
15857 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015858 unregister_vlb:
15859 isa_unregister_driver(&advansys_vlb_driver);
15860 unregister_isa:
15861 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015862 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015863 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015864}
15865
15866static void __exit advansys_exit(void)
15867{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015868 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015869 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015870 isa_unregister_driver(&advansys_vlb_driver);
15871 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015872}
15873
15874module_init(advansys_init);
15875module_exit(advansys_exit);
15876
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015877MODULE_LICENSE("GPL");